atlas-init 0.7.0__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {atlas_init-0.7.0 → atlas_init-0.8.0}/.gitignore +3 -1
- {atlas_init-0.7.0 → atlas_init-0.8.0}/PKG-INFO +4 -3
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/__init__.py +1 -1
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/atlas_init.yaml +1 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/example_update.py +20 -8
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/hcl/modifier.py +22 -8
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/env_vars.py +12 -2
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/api_call.py +9 -9
- atlas_init-0.8.0/atlas_init/tf_ext/args.py +32 -0
- atlas_init-0.8.0/atlas_init/tf_ext/gen_examples.py +141 -0
- atlas_init-0.8.0/atlas_init/tf_ext/gen_module_readme.py +131 -0
- atlas_init-0.8.0/atlas_init/tf_ext/gen_resource_main.py +195 -0
- atlas_init-0.8.0/atlas_init/tf_ext/gen_resource_output.py +71 -0
- atlas_init-0.8.0/atlas_init/tf_ext/gen_resource_variables.py +159 -0
- atlas_init-0.8.0/atlas_init/tf_ext/gen_versions.py +10 -0
- atlas_init-0.8.0/atlas_init/tf_ext/models_module.py +454 -0
- atlas_init-0.8.0/atlas_init/tf_ext/newres.py +90 -0
- atlas_init-0.8.0/atlas_init/tf_ext/plan_diffs.py +140 -0
- atlas_init-0.8.0/atlas_init/tf_ext/provider_schema.py +199 -0
- atlas_init-0.8.0/atlas_init/tf_ext/py_gen.py +294 -0
- atlas_init-0.8.0/atlas_init/tf_ext/schema_to_dataclass.py +522 -0
- atlas_init-0.8.0/atlas_init/tf_ext/settings.py +188 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/tf_dep.py +5 -5
- atlas_init-0.8.0/atlas_init/tf_ext/tf_desc_gen.py +53 -0
- atlas_init-0.8.0/atlas_init/tf_ext/tf_desc_update.py +0 -0
- atlas_init-0.8.0/atlas_init/tf_ext/tf_mod_gen.py +263 -0
- atlas_init-0.8.0/atlas_init/tf_ext/tf_mod_gen_provider.py +124 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/tf_modules.py +5 -4
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/tf_vars.py +13 -28
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/typer_app.py +6 -2
- {atlas_init-0.7.0 → atlas_init-0.8.0}/pyproject.toml +6 -3
- atlas_init-0.7.0/atlas_init/tf_ext/args.py +0 -17
- atlas_init-0.7.0/atlas_init/tf_ext/settings.py +0 -39
- {atlas_init-0.7.0 → atlas_init-0.8.0}/LICENSE +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/__main__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_args.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/app.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/aws.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/cfn_parameter_finder.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/contract.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/example.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_cfn/files.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/go.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/run.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/run_manager.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/sdk.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/sdk_auto_changes.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_helper/tf_runner.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_root/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_root/go_test.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_root/mms_released.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_root/trigger.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/app.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/changelog.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/ci_tests.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/codegen/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/codegen/models.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/codegen/openapi_minimal.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/debug_logs.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/debug_logs_test_data.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/debug_logs_test_data_package_config.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/github_logs.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/go_test_run.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/go_test_summary.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/go_test_tf_error.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/hcl/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/hcl/cli.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/hcl/cluster_mig.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/hcl/modifier2.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/hcl/parser.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/log_clean.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/mock_tf_log.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/openapi.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_go_parser.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_inspection.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_table.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_table_models.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_v2.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_v2_sdk.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_v3.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_v3_sdk.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_v3_sdk_base.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cli_tf/schema_v3_sdk_create.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cloud/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/cloud/aws.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/crud/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/crud/mongo_client.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/crud/mongo_dao.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/crud/mongo_utils.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/html_out/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/html_out/md_export.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/humps.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/repos/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/repos/cfn.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/repos/go_sdk.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/repos/path.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/sdk_ext/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/sdk_ext/go.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/sdk_ext/typer_app.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/config.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/env_vars_generated.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/env_vars_modules.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/interactive.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/interactive2.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/path.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/settings/rich_utils.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/terraform.yaml +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/.terraform.lock.hcl +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/always.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/main.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_kms/aws_kms.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_kms/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_s3/aws_s3.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_s3/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_vars/aws_vars.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_vpc/aws_vpc.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/aws_vpc/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cfn/assume_role_services.yaml +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cfn/cfn.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cfn/kms.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cfn/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cfn/resource_actions.yaml +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cfn/variables.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cloud_provider/cloud_provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cloud_provider/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cluster/cluster.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/cluster/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/encryption_at_rest/main.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/encryption_at_rest/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/federated_vars/federated_vars.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/federated_vars/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/project_extra/project_extra.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/project_extra/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/stream_instance/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/stream_instance/stream_instance.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/vpc_peering/provider.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/vpc_peering/vpc_peering.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/vpc_privatelink/atlas-privatelink.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/vpc_privatelink/variables.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/modules/vpc_privatelink/versions.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/outputs.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/providers.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf/variables.tf +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/__init__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/__main__.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/constants.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/models.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/tf_ext/paths.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/atlas_init/typer_app.py +0 -0
- {atlas_init-0.7.0 → atlas_init-0.8.0}/readme.md +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: atlas-init
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.0
|
4
4
|
Project-URL: Documentation, https://github.com/EspenAlbert/atlas-init#readme
|
5
5
|
Project-URL: Issues, https://github.com/EspenAlbert/atlas-init/issues
|
6
6
|
Project-URL: Source, https://github.com/EspenAlbert/atlas-init
|
@@ -12,10 +12,11 @@ Classifier: Programming Language :: Python
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
13
13
|
Requires-Python: >=3.13
|
14
14
|
Requires-Dist: appdirs==1.4.4
|
15
|
-
Requires-Dist: ask-shell>=0.0.
|
15
|
+
Requires-Dist: ask-shell>=0.0.5
|
16
16
|
Requires-Dist: boto3==1.35.92
|
17
17
|
Requires-Dist: gitpython==3.1.42
|
18
18
|
Requires-Dist: humanize==4.9.0
|
19
|
+
Requires-Dist: inflection==0.5.1
|
19
20
|
Requires-Dist: model-lib
|
20
21
|
Requires-Dist: motor==3.7.1
|
21
22
|
Requires-Dist: mypy-boto3-cloudformation==1.37.22
|
@@ -30,7 +31,7 @@ Requires-Dist: rich==14.0.0
|
|
30
31
|
Requires-Dist: stringcase==1.2.0
|
31
32
|
Requires-Dist: tenacity==9.0.0
|
32
33
|
Requires-Dist: typer>=0.15.1
|
33
|
-
Requires-Dist: zero-3rdparty
|
34
|
+
Requires-Dist: zero-3rdparty==1.0.0b5
|
34
35
|
Description-Content-Type: text/markdown
|
35
36
|
|
36
37
|
# Atlas Init - A CLI for developing integrations with MongoDB Atlas
|
@@ -2,26 +2,30 @@ import logging
|
|
2
2
|
from collections import defaultdict
|
3
3
|
from functools import total_ordering
|
4
4
|
from pathlib import Path
|
5
|
+
from typing import Callable
|
5
6
|
|
6
7
|
import typer
|
7
8
|
from model_lib import Entity, Event, dump, parse_payload
|
8
|
-
from pydantic import Field
|
9
|
+
from pydantic import BaseModel, ConfigDict, Field
|
9
10
|
|
10
11
|
from atlas_init.cli_helper.run import run_binary_command_is_ok
|
11
12
|
from atlas_init.cli_tf.hcl.modifier import (
|
12
13
|
BLOCK_TYPE_OUTPUT,
|
13
14
|
BLOCK_TYPE_VARIABLE,
|
15
|
+
NewDescription,
|
14
16
|
update_descriptions,
|
15
17
|
)
|
16
18
|
|
17
19
|
logger = logging.getLogger(__name__)
|
18
20
|
|
19
21
|
|
20
|
-
class UpdateExamples(
|
22
|
+
class UpdateExamples(BaseModel):
|
23
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
21
24
|
examples_base_dir: Path
|
22
|
-
var_descriptions: dict[str, str]
|
25
|
+
var_descriptions: dict[str, str] = Field(default_factory=dict)
|
23
26
|
output_descriptions: dict[str, str] = Field(default_factory=dict)
|
24
27
|
skip_tf_fmt: bool = False
|
28
|
+
new_description_call: Callable[[str, str, Path], str] | None = None # Protocol not supported for Pydantic
|
25
29
|
|
26
30
|
|
27
31
|
@total_ordering
|
@@ -50,16 +54,24 @@ class UpdateExamplesOutput(Entity):
|
|
50
54
|
|
51
55
|
def update_examples(event_in: UpdateExamples) -> UpdateExamplesOutput:
|
52
56
|
changes = []
|
57
|
+
|
58
|
+
def get_description(name: str, old_description: str, path: Path) -> str:
|
59
|
+
return event_in.var_descriptions.get(name, "")
|
60
|
+
|
53
61
|
existing_var_descriptions = update_block_descriptions(
|
54
62
|
event_in.examples_base_dir,
|
55
63
|
changes,
|
56
|
-
event_in.
|
64
|
+
event_in.new_description_call or get_description, # type: ignore
|
57
65
|
BLOCK_TYPE_VARIABLE,
|
58
66
|
)
|
67
|
+
|
68
|
+
def get_output_description(name: str, old_description: str, path: Path) -> str:
|
69
|
+
return event_in.output_descriptions.get(name, "")
|
70
|
+
|
59
71
|
existing_output_descriptions = update_block_descriptions(
|
60
72
|
event_in.examples_base_dir,
|
61
73
|
changes,
|
62
|
-
event_in.
|
74
|
+
event_in.new_description_call or get_output_description, # type: ignore
|
63
75
|
BLOCK_TYPE_OUTPUT,
|
64
76
|
)
|
65
77
|
if event_in.skip_tf_fmt:
|
@@ -85,14 +97,14 @@ def flatten_descriptions(descriptions: dict[str, list[str]]) -> dict[str, str]:
|
|
85
97
|
def update_block_descriptions(
|
86
98
|
base_dir: Path,
|
87
99
|
changes: list[TFConfigDescriptionChange],
|
88
|
-
|
100
|
+
get_description: NewDescription,
|
89
101
|
block_type: str,
|
90
102
|
):
|
91
103
|
all_existing_descriptions = defaultdict(list)
|
92
104
|
in_files = sorted(base_dir.rglob("*.tf"))
|
93
105
|
for tf_file in in_files:
|
94
106
|
logger.info(f"looking for {block_type} in {tf_file}")
|
95
|
-
new_tf, existing_descriptions = update_descriptions(tf_file,
|
107
|
+
new_tf, existing_descriptions = update_descriptions(tf_file, get_description, block_type=block_type)
|
96
108
|
if not existing_descriptions: # probably no variables in the file
|
97
109
|
continue
|
98
110
|
for name, descriptions in existing_descriptions.items():
|
@@ -101,7 +113,7 @@ def update_block_descriptions(
|
|
101
113
|
path=tf_file,
|
102
114
|
name=name,
|
103
115
|
before=description,
|
104
|
-
after=
|
116
|
+
after=get_description(name, description, tf_file),
|
105
117
|
block_type=block_type,
|
106
118
|
)
|
107
119
|
for description in descriptions
|
@@ -1,8 +1,9 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import logging
|
2
3
|
from collections import defaultdict
|
3
4
|
from copy import deepcopy
|
4
5
|
from pathlib import Path
|
5
|
-
from typing import Callable
|
6
|
+
from typing import Callable, Protocol
|
6
7
|
|
7
8
|
import hcl2
|
8
9
|
from lark import Token, Tree
|
@@ -40,14 +41,16 @@ def is_block_type(tree: Tree, block_type: str) -> bool:
|
|
40
41
|
return False
|
41
42
|
|
42
43
|
|
43
|
-
def update_description(
|
44
|
+
def update_description(
|
45
|
+
path: Path, tree: Tree, get_new_description: NewDescription, existing_names: dict[str, list[str]]
|
46
|
+
) -> Tree:
|
44
47
|
new_children = tree.children.copy()
|
45
48
|
variable_body = new_children[2]
|
46
49
|
assert variable_body.data == "body"
|
47
50
|
name = token_name(new_children[1])
|
48
51
|
old_description = read_description_attribute(variable_body)
|
49
52
|
existing_names[name].append(old_description)
|
50
|
-
new_description =
|
53
|
+
new_description = get_new_description(name, old_description, path)
|
51
54
|
if not new_description:
|
52
55
|
debug_log(f"no description found for variable {name}", 0)
|
53
56
|
return tree
|
@@ -60,6 +63,8 @@ def token_name(token: Token | Tree) -> str:
|
|
60
63
|
return token.value.strip('"')
|
61
64
|
if isinstance(token, Tree) and token.data == "identifier":
|
62
65
|
return token.children[0].value.strip('"') # type: ignore
|
66
|
+
if isinstance(token, Tree) and isinstance(token.data, Token) and token.data.value == "heredoc_template_trim":
|
67
|
+
return token.children[0].value.strip('"') # type: ignore
|
63
68
|
err_msg = f"unexpected token type {type(token)} for token name"
|
64
69
|
raise ValueError(err_msg)
|
65
70
|
|
@@ -103,10 +108,11 @@ def read_description_attribute(tree: Tree) -> str:
|
|
103
108
|
|
104
109
|
|
105
110
|
def create_description_attribute(description_value: str) -> Tree:
|
111
|
+
token_value = f"<<-EOT\n{description_value}\nEOT\n" if "\n" in description_value else f'"{description_value}"'
|
106
112
|
children = [
|
107
113
|
Tree(Token("RULE", "identifier"), [Token("NAME", "description")]),
|
108
114
|
Token("EQ", " ="),
|
109
|
-
Tree(Token("RULE", "expr_term"), [Token("STRING_LIT",
|
115
|
+
Tree(Token("RULE", "expr_term"), [Token("STRING_LIT", token_value)]),
|
110
116
|
]
|
111
117
|
return Tree(Token("RULE", "attribute"), children)
|
112
118
|
|
@@ -129,9 +135,14 @@ def process_generic(
|
|
129
135
|
return Tree(node.data, new_children)
|
130
136
|
|
131
137
|
|
138
|
+
class NewDescription(Protocol):
|
139
|
+
def __call__(self, name: str, old_description: str, path: Path) -> str: ...
|
140
|
+
|
141
|
+
|
132
142
|
def process_descriptions(
|
143
|
+
path: Path,
|
133
144
|
node: Tree,
|
134
|
-
|
145
|
+
new_description: NewDescription,
|
135
146
|
existing_names: dict[str, list[str]],
|
136
147
|
depth=0,
|
137
148
|
*,
|
@@ -141,7 +152,7 @@ def process_descriptions(
|
|
141
152
|
return is_block_type(tree, block_type)
|
142
153
|
|
143
154
|
def tree_call(tree: Tree) -> Tree:
|
144
|
-
return update_description(tree,
|
155
|
+
return update_description(path, tree, new_description, existing_names)
|
145
156
|
|
146
157
|
return process_generic(
|
147
158
|
node,
|
@@ -151,14 +162,17 @@ def process_descriptions(
|
|
151
162
|
)
|
152
163
|
|
153
164
|
|
154
|
-
def update_descriptions(
|
165
|
+
def update_descriptions(
|
166
|
+
tf_path: Path, new_description: NewDescription, block_type: str
|
167
|
+
) -> tuple[str, dict[str, list[str]]]:
|
155
168
|
tree = safe_parse(tf_path)
|
156
169
|
if tree is None:
|
157
170
|
return "", {}
|
158
171
|
existing_descriptions = defaultdict(list)
|
159
172
|
new_tree = process_descriptions(
|
173
|
+
tf_path,
|
160
174
|
tree,
|
161
|
-
|
175
|
+
new_description,
|
162
176
|
existing_descriptions,
|
163
177
|
block_type=block_type,
|
164
178
|
)
|
@@ -243,7 +243,9 @@ def detect_ambiguous_env_vars(manual_env_vars: dict[str, str]) -> list[str]:
|
|
243
243
|
|
244
244
|
def find_missing_env_vars(required_env_vars: list[str], manual_env_vars: dict[str, str]) -> list[str]:
|
245
245
|
return sorted(
|
246
|
-
env_name
|
246
|
+
env_name
|
247
|
+
for env_name in required_env_vars
|
248
|
+
if read_from_env(env_name) == "" and env_name not in manual_env_vars and env_name
|
247
249
|
)
|
248
250
|
|
249
251
|
|
@@ -255,7 +257,15 @@ def init_settings(
|
|
255
257
|
profile_env_vars = settings.manual_env_vars
|
256
258
|
vscode_env_vars = settings.env_vars_vs_code
|
257
259
|
if vscode_env_vars.exists():
|
258
|
-
|
260
|
+
skip_generated_vars: set[str] = set()
|
261
|
+
if "AWS_PROFILE" in profile_env_vars:
|
262
|
+
skip_generated_vars |= {
|
263
|
+
"AWS_ACCESS_KEY_ID",
|
264
|
+
"AWS_SECRET_ACCESS_KEY",
|
265
|
+
} # avoid generated env-vars overwriting AWS PROFILE
|
266
|
+
profile_env_vars |= {
|
267
|
+
key: value for key, value in load_dotenv(vscode_env_vars).items() if key not in skip_generated_vars
|
268
|
+
}
|
259
269
|
required_env_vars = collect_required_env_vars(list(settings_classes))
|
260
270
|
ambiguous = [] if skip_ambiguous_check else detect_ambiguous_env_vars(profile_env_vars)
|
261
271
|
missing_env_vars = find_missing_env_vars(required_env_vars, profile_env_vars)
|
@@ -1,18 +1,18 @@
|
|
1
|
-
from collections import defaultdict
|
2
|
-
from concurrent.futures import Future, as_completed
|
3
|
-
from functools import lru_cache
|
4
1
|
import json
|
5
2
|
import logging
|
6
3
|
import os
|
4
|
+
from collections import defaultdict
|
5
|
+
from concurrent.futures import Future, as_completed
|
6
|
+
from functools import lru_cache
|
7
7
|
from pathlib import Path
|
8
8
|
|
9
|
+
import requests
|
10
|
+
import typer
|
9
11
|
from ask_shell import new_task, print_to_live, run_pool
|
10
12
|
from model_lib import dump, parse_model
|
11
13
|
from pydantic import BaseModel, Field, model_validator
|
12
|
-
import requests
|
13
|
-
from rich.markdown import Markdown
|
14
|
-
import typer
|
15
14
|
from requests.auth import HTTPDigestAuth
|
15
|
+
from rich.markdown import Markdown
|
16
16
|
from zero_3rdparty.file_utils import ensure_parents_write_text
|
17
17
|
from zero_3rdparty.str_utils import ensure_prefix, ensure_suffix, instance_repr
|
18
18
|
|
@@ -27,7 +27,7 @@ from atlas_init.settings.env_vars_modules import (
|
|
27
27
|
TFModuleStream_Instance,
|
28
28
|
)
|
29
29
|
from atlas_init.settings.path import load_dotenv
|
30
|
-
from atlas_init.tf_ext.settings import
|
30
|
+
from atlas_init.tf_ext.settings import TfExtSettings
|
31
31
|
|
32
32
|
logger = logging.getLogger(__name__)
|
33
33
|
|
@@ -259,7 +259,7 @@ def api_config(
|
|
259
259
|
md_content = "\n".join(md_report)
|
260
260
|
md = Markdown(md_content)
|
261
261
|
print_to_live(md)
|
262
|
-
output_path =
|
262
|
+
output_path = TfExtSettings.from_env().pagination_output_path(query_args_str)
|
263
263
|
ensure_parents_write_text(output_path, md_content)
|
264
264
|
logger.info(f"Pagination report saved to {output_path}")
|
265
265
|
return md
|
@@ -288,7 +288,7 @@ def api(
|
|
288
288
|
|
289
289
|
|
290
290
|
def dump_config_path(query_args: dict[str, str]) -> Path:
|
291
|
-
settings =
|
291
|
+
settings = TfExtSettings.from_env()
|
292
292
|
latest_api_spec = resolve_admin_api_path()
|
293
293
|
model = parse_model(latest_api_spec, t=OpenapiSchema)
|
294
294
|
paginated_paths: list[ApiCall] = []
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import typer
|
2
|
+
|
3
|
+
|
4
|
+
def default_skippped_directories() -> list[str]:
|
5
|
+
return [
|
6
|
+
"prometheus-and-teams", # Provider registry.terraform.io/hashicorp/template v2.2.0 does not have a package available for your current platform, darwin_arm64.
|
7
|
+
]
|
8
|
+
|
9
|
+
|
10
|
+
REPO_PATH_ATLAS_ARG = typer.Argument(..., help="Path to the mongodbatlas-terraform-provider repository")
|
11
|
+
SKIP_EXAMPLES_DIRS_OPTION = typer.Option(
|
12
|
+
...,
|
13
|
+
"--skip-examples",
|
14
|
+
help="Skip example directories with these names",
|
15
|
+
default_factory=default_skippped_directories,
|
16
|
+
show_default=True,
|
17
|
+
)
|
18
|
+
TF_CLI_CONFIG_FILE_ENV_NAME = "TF_CLI_CONFIG_FILE"
|
19
|
+
TF_CLI_CONFIG_FILE_ARG = typer.Option(
|
20
|
+
"",
|
21
|
+
"-tf-cli",
|
22
|
+
"--tf-cli-config-file",
|
23
|
+
envvar=TF_CLI_CONFIG_FILE_ENV_NAME,
|
24
|
+
help="Terraform CLI config file",
|
25
|
+
)
|
26
|
+
ENV_NAME_REPO_PATH_ATLAS_PROVIDER = "REPO_PATH_ATLAS_PROVIDER"
|
27
|
+
TF_REPO_PATH_ATLAS = typer.Option(
|
28
|
+
"",
|
29
|
+
"--tf-repo-path-atlas",
|
30
|
+
help="Path to the mongodbatlas-terraform-provider repository",
|
31
|
+
envvar=ENV_NAME_REPO_PATH_ATLAS_PROVIDER,
|
32
|
+
)
|
@@ -0,0 +1,141 @@
|
|
1
|
+
from contextlib import suppress
|
2
|
+
from dataclasses import asdict
|
3
|
+
from functools import singledispatch
|
4
|
+
from pathlib import Path
|
5
|
+
|
6
|
+
from zero_3rdparty import humps
|
7
|
+
from zero_3rdparty.file_utils import clean_dir, ensure_parents_write_text
|
8
|
+
|
9
|
+
from atlas_init.tf_ext.gen_resource_variables import generate_resource_variables
|
10
|
+
from atlas_init.tf_ext.gen_versions import dump_versions_tf
|
11
|
+
from atlas_init.tf_ext.models_module import ModuleGenConfig, ResourceAbs, ResourceGenConfig, ResourceTypePythonModule
|
12
|
+
from atlas_init.tf_ext.py_gen import import_module_by_using_parents
|
13
|
+
|
14
|
+
VARIABLE_PLACEHOLDER = "var."
|
15
|
+
INDENT = " "
|
16
|
+
|
17
|
+
|
18
|
+
def _examples_casted(examples: dict) -> dict[str, ResourceAbs]:
|
19
|
+
return examples
|
20
|
+
|
21
|
+
|
22
|
+
def read_example_dirs(module_path: Path) -> list[Path]:
|
23
|
+
return sorted(
|
24
|
+
example_dir
|
25
|
+
for example_dir in (module_path / "examples").glob("*")
|
26
|
+
if example_dir.is_dir()
|
27
|
+
and len(example_dir.name) > 2
|
28
|
+
and example_dir.name[:2].isdigit()
|
29
|
+
and (example_dir / "main.tf").exists()
|
30
|
+
)
|
31
|
+
|
32
|
+
|
33
|
+
def generate_module_examples(
|
34
|
+
config: ModuleGenConfig,
|
35
|
+
module: ResourceTypePythonModule,
|
36
|
+
resource_type: str,
|
37
|
+
*,
|
38
|
+
skip_clean_dir: bool = False,
|
39
|
+
) -> list[Path]:
|
40
|
+
test_path = config.examples_test_path
|
41
|
+
imported_module = import_module_by_using_parents(test_path)
|
42
|
+
examples = getattr(imported_module, "EXAMPLES")
|
43
|
+
assert isinstance(examples, dict), f"{imported_module} does not have an EXAMPLES attribute"
|
44
|
+
examples_parsed = _examples_casted(examples)
|
45
|
+
examples_generated: list[Path] = []
|
46
|
+
for example_name, example in examples_parsed.items():
|
47
|
+
dumped_resource = {k: v for k, v in asdict(example).items() if v is not None}
|
48
|
+
variables = {
|
49
|
+
k: f"{v}{k}"
|
50
|
+
for k, v in dumped_resource.items()
|
51
|
+
if isinstance(v, str) and v.startswith(VARIABLE_PLACEHOLDER)
|
52
|
+
}
|
53
|
+
dumped_resource |= variables
|
54
|
+
variable_names = set(variables.keys())
|
55
|
+
ignored_names = set(module.all_field_names) - variable_names
|
56
|
+
ignored_names |= module.all_skip_variables
|
57
|
+
resource_cls = module.resource_ext or module.resource
|
58
|
+
assert resource_cls, f"{module} does not have a resource class"
|
59
|
+
example_path = config.example_path(example_name)
|
60
|
+
if not skip_clean_dir and example_path.exists():
|
61
|
+
clean_dir(example_path)
|
62
|
+
|
63
|
+
variables_tf = generate_resource_variables(
|
64
|
+
resource_cls,
|
65
|
+
ResourceGenConfig(
|
66
|
+
name=resource_type, skip_variables_extra=ignored_names, required_variables=variable_names
|
67
|
+
),
|
68
|
+
)
|
69
|
+
ensure_parents_write_text(example_path / "variables.tf", variables_tf)
|
70
|
+
variables_str = "\n".join(f"{k} = {dump_variable(v)}" for k, v in dumped_resource.items() if can_dump(v))
|
71
|
+
example_main = example_main_tf(config, variables_str)
|
72
|
+
ensure_parents_write_text(example_path / "main.tf", example_main)
|
73
|
+
dump_versions_tf(example_path, skip_python=config.skip_python, minimal=True)
|
74
|
+
examples_generated.append(example_path)
|
75
|
+
return examples_generated
|
76
|
+
|
77
|
+
|
78
|
+
class NotDumpableError(Exception):
|
79
|
+
def __init__(self, value: object) -> None:
|
80
|
+
super().__init__(f"Cannot dump variable {value!r}")
|
81
|
+
|
82
|
+
|
83
|
+
def can_dump(variable: object) -> bool:
|
84
|
+
with suppress(NotDumpableError):
|
85
|
+
dump_variable(variable)
|
86
|
+
return True
|
87
|
+
return False
|
88
|
+
|
89
|
+
|
90
|
+
@singledispatch
|
91
|
+
def dump_variable(variable: object) -> str:
|
92
|
+
raise NotDumpableError(variable)
|
93
|
+
|
94
|
+
|
95
|
+
@dump_variable.register
|
96
|
+
def dump_variable_str(variable: str) -> str:
|
97
|
+
if "." in variable:
|
98
|
+
return variable
|
99
|
+
return f'"{variable}"'
|
100
|
+
|
101
|
+
|
102
|
+
@dump_variable.register
|
103
|
+
def dump_variable_int(variable: int) -> str:
|
104
|
+
return str(variable)
|
105
|
+
|
106
|
+
|
107
|
+
@dump_variable.register
|
108
|
+
def dump_variable_float(variable: float) -> str:
|
109
|
+
return str(variable)
|
110
|
+
|
111
|
+
|
112
|
+
@dump_variable.register
|
113
|
+
def dump_variable_bool(variable: bool) -> str:
|
114
|
+
return "true" if variable else "false"
|
115
|
+
|
116
|
+
|
117
|
+
@dump_variable.register
|
118
|
+
def dump_variable_list(variable: list) -> str:
|
119
|
+
return f"[\n{', '.join(f'{INDENT}{dump_variable(nested)}' for nested in variable if can_dump(nested))}\n]"
|
120
|
+
|
121
|
+
|
122
|
+
@dump_variable.register
|
123
|
+
def dump_variable_set(variable: set) -> str:
|
124
|
+
return f"[\n{', '.join(f'{INDENT}{dump_variable(nested)}' for nested in variable if can_dump(nested))}\n]"
|
125
|
+
|
126
|
+
|
127
|
+
@dump_variable.register
|
128
|
+
def dump_variable_dict(variable: dict) -> str:
|
129
|
+
return "{\n" + "\n".join(f"{INDENT}{k} = {dump_variable(v)}" for k, v in variable.items() if can_dump(v)) + "\n}"
|
130
|
+
|
131
|
+
|
132
|
+
def example_main_tf(module: ModuleGenConfig, variables: str) -> str:
|
133
|
+
variables_indented = "\n".join(f"{INDENT}{var}" for var in variables.split("\n"))
|
134
|
+
module_name_snake = humps.dekebabize(module.name)
|
135
|
+
return f"""\
|
136
|
+
module "{module_name_snake}" {{
|
137
|
+
source = "../.."
|
138
|
+
|
139
|
+
{variables_indented}
|
140
|
+
}}
|
141
|
+
"""
|
@@ -0,0 +1,131 @@
|
|
1
|
+
import logging
|
2
|
+
from enum import StrEnum
|
3
|
+
|
4
|
+
from ask_shell import run_and_wait
|
5
|
+
from zero_3rdparty.file_utils import ensure_parents_write_text, update_between_markers
|
6
|
+
|
7
|
+
from atlas_init.tf_ext.gen_examples import read_example_dirs
|
8
|
+
from atlas_init.tf_ext.models_module import ModuleGenConfig
|
9
|
+
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
_readme_disclaimer = """\
|
12
|
+
## Disclaimer
|
13
|
+
This Module is not meant for external consumption.
|
14
|
+
It is part of a development PoC.
|
15
|
+
Any usage problems will not be supported.
|
16
|
+
However, if you have any ideas or feedback feel free to open a Github Issue!
|
17
|
+
"""
|
18
|
+
|
19
|
+
|
20
|
+
class ReadmeMarkers(StrEnum):
|
21
|
+
DISCLAIMER = "DISCLAIMER"
|
22
|
+
EXAMPLE = "TF_EXAMPLES"
|
23
|
+
TF_DOCS = "TF_DOCS"
|
24
|
+
|
25
|
+
@classmethod
|
26
|
+
def as_start(cls, marker_name: str) -> str:
|
27
|
+
return f"<!-- BEGIN_{marker_name} -->"
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def as_end(cls, marker_name: str) -> str:
|
31
|
+
return f"<!-- END_{marker_name} -->"
|
32
|
+
|
33
|
+
@classmethod
|
34
|
+
def marker_lines(cls, marker_name: str) -> str:
|
35
|
+
return f"""\
|
36
|
+
{cls.as_start(marker_name)}
|
37
|
+
|
38
|
+
{cls.as_end(marker_name)}
|
39
|
+
"""
|
40
|
+
|
41
|
+
@classmethod
|
42
|
+
def example_boilerplate(cls) -> str:
|
43
|
+
return "\n".join(cls.marker_lines(marker_name) for marker_name in list(cls))
|
44
|
+
|
45
|
+
|
46
|
+
def read_examples(module: ModuleGenConfig) -> str:
|
47
|
+
example_dirs = read_example_dirs(module.module_out_path)
|
48
|
+
content = ["# Examples"]
|
49
|
+
for example_dir in example_dirs:
|
50
|
+
example_name = example_dir.name
|
51
|
+
header_name = example_name.replace("_", " ").replace("-", " ").title()
|
52
|
+
main_path = example_dir / "main.tf"
|
53
|
+
assert main_path.exists(), f"{main_path} does not exist, every example must have a main.tf"
|
54
|
+
content.extend(
|
55
|
+
[
|
56
|
+
f"## [{header_name}](./examples/{example_name})",
|
57
|
+
"",
|
58
|
+
"```terraform",
|
59
|
+
main_path.read_text(),
|
60
|
+
"```",
|
61
|
+
"",
|
62
|
+
"",
|
63
|
+
]
|
64
|
+
)
|
65
|
+
return "\n".join(content)
|
66
|
+
|
67
|
+
|
68
|
+
_static_terraform_config = """\
|
69
|
+
formatter: markdown document
|
70
|
+
output:
|
71
|
+
file: "FILENAME"
|
72
|
+
mode: inject
|
73
|
+
template: |-
|
74
|
+
START_MARKER
|
75
|
+
{{ .Content }}
|
76
|
+
END_MARKER
|
77
|
+
sort:
|
78
|
+
enabled: true
|
79
|
+
by: required
|
80
|
+
"""
|
81
|
+
|
82
|
+
|
83
|
+
def terraform_docs_config_content(module: ModuleGenConfig) -> str:
|
84
|
+
config = _static_terraform_config
|
85
|
+
for replacement_in, replacement_out in [
|
86
|
+
("FILENAME", module.readme_path().name),
|
87
|
+
("START_MARKER", ReadmeMarkers.as_start(ReadmeMarkers.TF_DOCS)),
|
88
|
+
("END_MARKER", ReadmeMarkers.as_end(ReadmeMarkers.TF_DOCS)),
|
89
|
+
]:
|
90
|
+
config = config.replace(replacement_in, replacement_out)
|
91
|
+
return config
|
92
|
+
|
93
|
+
|
94
|
+
def generate_readme(module: ModuleGenConfig) -> str:
|
95
|
+
readme_path = module.readme_path()
|
96
|
+
assert readme_path.exists(), (
|
97
|
+
f"{readme_path} does not exist, currently a boilerplate is expected, consider adding to {readme_path}\n{ReadmeMarkers.example_boilerplate()}"
|
98
|
+
)
|
99
|
+
update_between_markers(
|
100
|
+
readme_path,
|
101
|
+
_readme_disclaimer,
|
102
|
+
ReadmeMarkers.as_start(ReadmeMarkers.DISCLAIMER),
|
103
|
+
ReadmeMarkers.as_end(ReadmeMarkers.DISCLAIMER),
|
104
|
+
)
|
105
|
+
run_and_wait("terraform fmt -recursive .", cwd=module.module_out_path, allow_non_zero_exit=True, ansi_content=False)
|
106
|
+
example_section = read_examples(module)
|
107
|
+
update_between_markers(
|
108
|
+
readme_path,
|
109
|
+
example_section,
|
110
|
+
ReadmeMarkers.as_start(ReadmeMarkers.EXAMPLE),
|
111
|
+
ReadmeMarkers.as_end(ReadmeMarkers.EXAMPLE),
|
112
|
+
)
|
113
|
+
docs_config_path = module.terraform_docs_config_path()
|
114
|
+
if docs_config_path.exists():
|
115
|
+
logger.warning(f"{docs_config_path} already exists, skipping generation")
|
116
|
+
else:
|
117
|
+
config_content = terraform_docs_config_content(module)
|
118
|
+
ensure_parents_write_text(docs_config_path, config_content)
|
119
|
+
logger.info(f"generated {docs_config_path}")
|
120
|
+
run_and_wait(f"terraform-docs -c {docs_config_path} .", cwd=module.module_out_path)
|
121
|
+
readme_content = _default_link_updater(readme_path.read_text())
|
122
|
+
ensure_parents_write_text(readme_path, readme_content)
|
123
|
+
return readme_path.read_text()
|
124
|
+
|
125
|
+
|
126
|
+
def _default_link_updater(readme_content: str) -> str: # can be a global replacer for now
|
127
|
+
for replace_in, replace_out in {
|
128
|
+
"docs/resources/advanced_cluster": r"docs/resources/advanced_cluster%2520%2528preview%2520provider%25202.0.0%2529"
|
129
|
+
}.items():
|
130
|
+
readme_content = readme_content.replace(replace_in, replace_out)
|
131
|
+
return readme_content
|