diff --git a/README.md b/README.md index bc9157e..359be3a 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ ADDITIONAL_TF_OVERRIDE_LOCATIONS=/path/to/module1,path/to/module2 tflocal plan ## Change Log +* v0.26.0: Fix compatibility with `python-hcl2` v8+ by using `SerializationOptions` to handle quoted dict keys, block metadata, and comments * v0.25.0: Improve `s3control` local endpoint override and respect `AWS_ENDPOINT_URL` configuration for `mwaa` * v0.24.1: Exclude broken `python-hcl2` version from requirements * v0.24.0: Add support to return `terraform-local` version when calling `tflocal -version` and fix AWS provider detection diff --git a/bin/tflocal b/bin/tflocal index 2a3ae8a..8d3ada2 100755 --- a/bin/tflocal +++ b/bin/tflocal @@ -26,6 +26,11 @@ if os.path.isdir(os.path.join(PARENT_FOLDER, ".venv")): from localstack_client import config # noqa: E402 import hcl2 # noqa: E402 +from hcl2 import SerializationOptions # noqa: E402 + +HCL2_SERIALIZATION_OPTIONS = SerializationOptions( + strip_string_quotes=True, explicit_blocks=False, with_comments=False +) DRY_RUN = str(os.environ.get("DRY_RUN")).strip().lower() in ["1", "true"] DEFAULT_REGION = "us-east-1" @@ -611,7 +616,7 @@ def parse_tf_files() -> dict: for _file in glob.glob("*.tf"): try: with open(_file, "r") as fp: - result[_file] = hcl2.load(fp) + result[_file] = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) except Exception as e: print(f'Unable to parse "{_file}" as HCL file: {e}') return result @@ -634,7 +639,7 @@ def get_provider_version_from_lock_file() -> Optional[version.Version]: provider_version = None with open(lock_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) for provider in result.get("provider", []): for provider_name, provider_config in provider.items(): if provider_name.endswith(AWS_PROVIDER_NAME_SUFFIX): diff --git a/setup.cfg b/setup.cfg index 19569f9..beed58f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = terraform-local -version = 0.25.0 +version = 0.26.0 url = https://github.com/localstack/terraform-local author = LocalStack Team author_email = info@localstack.cloud @@ -28,7 +28,7 @@ packages = find: install_requires = localstack-client - python-hcl2!=7.3.0 + python-hcl2>=8 packaging [options.extras_require] diff --git a/tests/test_apply.py b/tests/test_apply.py index 88dda01..f353ccc 100644 --- a/tests/test_apply.py +++ b/tests/test_apply.py @@ -12,6 +12,11 @@ import boto3 import pytest import hcl2 +from hcl2 import SerializationOptions + +HCL2_SERIALIZATION_OPTIONS = SerializationOptions( + strip_string_quotes=True, explicit_blocks=False, with_comments=False +) # TODO set up the tests to run with tox so we can run the tests with different python versions @@ -385,7 +390,7 @@ def test_s3_remote_data_source_with_workspace(monkeypatch): assert check_override_file_exists(override_file) with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) assert result["data"][0]["terraform_remote_state"]["terraform_infra"]["workspace"] == "${terraform.workspace}" assert result["data"][1]["terraform_remote_state"]["build_infra"]["workspace"] == "build" @@ -432,7 +437,7 @@ def test_versioned_endpoints(monkeypatch, provider_version): assert check_override_file_exists(override_file) with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) endpoints = result["provider"][0]["aws"]["endpoints"][0] if provider_version == "5.99.1": assert "iotanalytics" in endpoints @@ -486,7 +491,7 @@ def test_subdomain_endpoints(monkeypatch, endpoint_host): assert check_override_file_exists(override_file) with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) endpoints = result["provider"][0]["aws"]["endpoints"][0] assert "s3control" in endpoints assert "mwaa" in endpoints @@ -570,7 +575,7 @@ def test_service_endpoint_alias_replacements(monkeypatch): def check_override_file_content(override_file): try: with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) result = result["provider"][0]["aws"] except Exception as e: raise Exception(f'Unable to parse "{override_file}" as HCL file: {e}') @@ -616,7 +621,7 @@ def test_s3_backend_configs_merge(monkeypatch): def check_override_file_backend_extra_content(override_file): try: with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) result = result["terraform"][0]["backend"][0]["s3"] except Exception as e: raise Exception(f'Unable to parse "{override_file}" as HCL file: {e}') @@ -690,7 +695,7 @@ def check_override_file_backend_endpoints_content(override_file, is_legacy: bool } try: with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) result = result["terraform"][0]["backend"][0]["s3"] except Exception as e: print(f'Unable to parse "{override_file}" as HCL file: {e}') @@ -727,7 +732,7 @@ def test_provider_aliases_ignored(monkeypatch): def check_override_file_content_for_alias(override_file): try: with open(override_file, "r") as fp: - result = hcl2.load(fp) + result = hcl2.load(fp, serialization_options=HCL2_SERIALIZATION_OPTIONS) result = result["provider"] except Exception as e: raise Exception(f'Unable to parse "{override_file}" as HCL file: {e}')