From c82bc7f041c15c9942d24fc4e5f9cf5177da9374 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 17 Apr 2021 22:53:50 +0200 Subject: [PATCH] Fix for Terraform 0.15 (#2246) (#2260) * Fix for Terraform 0.15 removed the append of variables in terraform validate because this is deprecated in Terraform 0.15. See: https://github.com/hashicorp/terraform/blob/v0.15/CHANGELOG.md >> The -var and -var-file options are no longer available on terraform validate. These were deprecated and have had no effect since Terraform v0.12 * Create terraform-validate.yaml * Update and rename terraform-validate.yaml to 2246-terraform-validate.yaml * Update changelogs/fragments/2246-terraform-validate.yaml Co-authored-by: Amin Vakil * Update terraform.py remove `-force` add `-auto-approve` on destroy as described in issue #2247 * Update and rename 2246-terraform-validate.yaml to 2246-terraform.yaml * Update 2246-terraform.yaml * add a function which check the used tf version * add a function which check the used tf version * Update changelogs/fragments/2246-terraform.yaml Co-authored-by: Amin Vakil * Update changelogs/fragments/2246-terraform.yaml Co-authored-by: Amin Vakil * add version return to function * changed it to pass sanity check * change variable name * changed to a more specialized data types * remove use_unsafe_shell=True * Update changelogs/fragments/2246-terraform.yaml Co-authored-by: Felix Fontein * add description * Update changelogs/fragments/2246-terraform.yaml Co-authored-by: Felix Fontein Co-authored-by: Amin Vakil Co-authored-by: Rainer Leber Co-authored-by: Felix Fontein (cherry picked from commit 1400051890cbf5674c2aa4939f9c716a0f3e4bd8) Co-authored-by: rainerleber <39616583+rainerleber@users.noreply.github.com> --- changelogs/fragments/2246-terraform.yaml | 4 +++ plugins/modules/cloud/misc/terraform.py | 32 ++++++++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 changelogs/fragments/2246-terraform.yaml diff --git a/changelogs/fragments/2246-terraform.yaml b/changelogs/fragments/2246-terraform.yaml new file mode 100644 index 0000000000..d2dd93e22e --- /dev/null +++ b/changelogs/fragments/2246-terraform.yaml @@ -0,0 +1,4 @@ +bugfixes: + - terraform - fix issue that cause the execution fail because from Terraform 0.15 on, the ``-var`` and ``-var-file`` options are no longer available on ``terraform validate`` (https://github.com/ansible-collections/community.general/pull/2246). + - terraform - fix issue that cause the destroy to fail because from Terraform 0.15 on, the ``terraform destroy -force`` option is replaced with ``terraform destroy -auto-approve`` (https://github.com/ansible-collections/community.general/issues/2247). + - terraform - remove uses of ``use_unsafe_shell=True`` (https://github.com/ansible-collections/community.general/pull/2246). diff --git a/plugins/modules/cloud/misc/terraform.py b/plugins/modules/cloud/misc/terraform.py index 680bab9aed..f395c8e278 100644 --- a/plugins/modules/cloud/misc/terraform.py +++ b/plugins/modules/cloud/misc/terraform.py @@ -8,7 +8,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -DOCUMENTATION = ''' +DOCUMENTATION = r''' --- module: terraform short_description: Manages a Terraform deployment (and plans) @@ -177,24 +177,31 @@ command: import os import json import tempfile +from distutils.version import LooseVersion from ansible.module_utils.six.moves import shlex_quote from ansible.module_utils.basic import AnsibleModule -DESTROY_ARGS = ('destroy', '-no-color', '-force') -APPLY_ARGS = ('apply', '-no-color', '-input=false', '-auto-approve=true') module = None -def preflight_validation(bin_path, project_path, variables_args=None, plan_file=None): +def get_version(bin_path): + extract_version = module.run_command([bin_path, 'version', '-json']) + terraform_version = (json.loads(extract_version[1]))['terraform_version'] + return terraform_version + + +def preflight_validation(bin_path, project_path, version, variables_args=None, plan_file=None): if project_path in [None, ''] or '/' not in project_path: module.fail_json(msg="Path for Terraform project can not be None or ''.") if not os.path.exists(bin_path): module.fail_json(msg="Path for Terraform binary '{0}' doesn't exist on this host - check the path and try again please.".format(bin_path)) if not os.path.isdir(project_path): module.fail_json(msg="Path for Terraform project '{0}' doesn't exist on this host - check the path and try again please.".format(project_path)) - - rc, out, err = module.run_command([bin_path, 'validate'] + variables_args, check_rc=True, cwd=project_path, use_unsafe_shell=True) + if LooseVersion(version) < LooseVersion('0.15.0'): + rc, out, err = module.run_command([bin_path, 'validate'] + variables_args, check_rc=True, cwd=project_path) + else: + rc, out, err = module.run_command([bin_path, 'validate'], check_rc=True, cwd=project_path) def _state_args(state_file): @@ -267,7 +274,7 @@ def build_plan(command, project_path, variables_args, state_file, targets, state plan_command.extend(_state_args(state_file)) - rc, out, err = module.run_command(plan_command + variables_args, cwd=project_path, use_unsafe_shell=True) + rc, out, err = module.run_command(plan_command + variables_args, cwd=project_path) if rc == 0: # no changes @@ -326,6 +333,15 @@ def main(): else: command = [module.get_bin_path('terraform', required=True)] + checked_version = get_version(command[0]) + + if LooseVersion(checked_version) < LooseVersion('0.15.0'): + DESTROY_ARGS = ('destroy', '-no-color', '-force') + APPLY_ARGS = ('apply', '-no-color', '-input=false', '-auto-approve=true') + else: + DESTROY_ARGS = ('destroy', '-no-color', '-auto-approve') + APPLY_ARGS = ('apply', '-no-color', '-input=false', '-auto-approve') + if force_init: init_plugins(command[0], project_path, backend_config, backend_config_files, init_reconfigure) @@ -351,7 +367,7 @@ def main(): for f in variables_files: variables_args.extend(['-var-file', f]) - preflight_validation(command[0], project_path, variables_args) + preflight_validation(command[0], project_path, checked_version, variables_args) if module.params.get('lock') is not None: if module.params.get('lock'):