atlas-init 0.4.3__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.
Files changed (109) hide show
  1. atlas_init-0.4.3/.gitignore +28 -0
  2. atlas_init-0.4.3/LICENSE +21 -0
  3. atlas_init-0.4.3/PKG-INFO +166 -0
  4. atlas_init-0.4.3/atlas_init/__init__.py +9 -0
  5. atlas_init-0.4.3/atlas_init/__main__.py +3 -0
  6. atlas_init-0.4.3/atlas_init/atlas_init.yaml +105 -0
  7. atlas_init-0.4.3/atlas_init/cli.py +261 -0
  8. atlas_init-0.4.3/atlas_init/cli_args.py +16 -0
  9. atlas_init-0.4.3/atlas_init/cli_cfn/__init__.py +0 -0
  10. atlas_init-0.4.3/atlas_init/cli_cfn/app.py +173 -0
  11. atlas_init-0.4.3/atlas_init/cli_cfn/aws.py +453 -0
  12. atlas_init-0.4.3/atlas_init/cli_cfn/cfn_parameter_finder.py +269 -0
  13. atlas_init-0.4.3/atlas_init/cli_cfn/contract.py +227 -0
  14. atlas_init-0.4.3/atlas_init/cli_cfn/example.py +215 -0
  15. atlas_init-0.4.3/atlas_init/cli_cfn/files.py +82 -0
  16. atlas_init-0.4.3/atlas_init/cli_helper/__init__.py +0 -0
  17. atlas_init-0.4.3/atlas_init/cli_helper/go.py +270 -0
  18. atlas_init-0.4.3/atlas_init/cli_helper/run.py +109 -0
  19. atlas_init-0.4.3/atlas_init/cli_helper/run_manager.py +272 -0
  20. atlas_init-0.4.3/atlas_init/cli_helper/sdk.py +91 -0
  21. atlas_init-0.4.3/atlas_init/cli_helper/sdk_auto_changes.py +2 -0
  22. atlas_init-0.4.3/atlas_init/cli_helper/tf_runner.py +98 -0
  23. atlas_init-0.4.3/atlas_init/cli_root/__init__.py +10 -0
  24. atlas_init-0.4.3/atlas_init/cli_root/go_test.py +104 -0
  25. atlas_init-0.4.3/atlas_init/cli_root/trigger.py +241 -0
  26. atlas_init-0.4.3/atlas_init/cli_tf/__init__.py +0 -0
  27. atlas_init-0.4.3/atlas_init/cli_tf/app.py +287 -0
  28. atlas_init-0.4.3/atlas_init/cli_tf/changelog.py +103 -0
  29. atlas_init-0.4.3/atlas_init/cli_tf/debug_logs.py +272 -0
  30. atlas_init-0.4.3/atlas_init/cli_tf/debug_logs_test_data.py +277 -0
  31. atlas_init-0.4.3/atlas_init/cli_tf/debug_logs_test_data_package_config.py +55 -0
  32. atlas_init-0.4.3/atlas_init/cli_tf/example_update.py +142 -0
  33. atlas_init-0.4.3/atlas_init/cli_tf/example_update_test/test_update_example.tf +23 -0
  34. atlas_init-0.4.3/atlas_init/cli_tf/example_update_test.py +96 -0
  35. atlas_init-0.4.3/atlas_init/cli_tf/github_logs.py +235 -0
  36. atlas_init-0.4.3/atlas_init/cli_tf/go_test_run.py +247 -0
  37. atlas_init-0.4.3/atlas_init/cli_tf/go_test_summary.py +150 -0
  38. atlas_init-0.4.3/atlas_init/cli_tf/hcl/__init__.py +0 -0
  39. atlas_init-0.4.3/atlas_init/cli_tf/hcl/cli.py +161 -0
  40. atlas_init-0.4.3/atlas_init/cli_tf/hcl/cluster_mig.py +348 -0
  41. atlas_init-0.4.3/atlas_init/cli_tf/hcl/modifier.py +144 -0
  42. atlas_init-0.4.3/atlas_init/cli_tf/hcl/modifier_test/test_process_variables_output_.tf +25 -0
  43. atlas_init-0.4.3/atlas_init/cli_tf/hcl/modifier_test/test_process_variables_variable_.tf +24 -0
  44. atlas_init-0.4.3/atlas_init/cli_tf/hcl/modifier_test.py +95 -0
  45. atlas_init-0.4.3/atlas_init/cli_tf/hcl/parser.py +140 -0
  46. atlas_init-0.4.3/atlas_init/cli_tf/log_clean.py +29 -0
  47. atlas_init-0.4.3/atlas_init/cli_tf/mock_tf_log.py +189 -0
  48. atlas_init-0.4.3/atlas_init/cli_tf/schema.py +369 -0
  49. atlas_init-0.4.3/atlas_init/cli_tf/schema_go_parser.py +236 -0
  50. atlas_init-0.4.3/atlas_init/cli_tf/schema_inspection.py +54 -0
  51. atlas_init-0.4.3/atlas_init/cli_tf/schema_table.py +148 -0
  52. atlas_init-0.4.3/atlas_init/cli_tf/schema_table_models.py +155 -0
  53. atlas_init-0.4.3/atlas_init/cli_tf/schema_v2.py +599 -0
  54. atlas_init-0.4.3/atlas_init/cli_tf/schema_v2_api_parsing.py +298 -0
  55. atlas_init-0.4.3/atlas_init/cli_tf/schema_v2_sdk.py +361 -0
  56. atlas_init-0.4.3/atlas_init/cli_tf/schema_v3.py +222 -0
  57. atlas_init-0.4.3/atlas_init/cli_tf/schema_v3_sdk.py +279 -0
  58. atlas_init-0.4.3/atlas_init/cli_tf/schema_v3_sdk_base.py +68 -0
  59. atlas_init-0.4.3/atlas_init/cli_tf/schema_v3_sdk_create.py +216 -0
  60. atlas_init-0.4.3/atlas_init/cloud/__init__.py +0 -0
  61. atlas_init-0.4.3/atlas_init/cloud/aws.py +127 -0
  62. atlas_init-0.4.3/atlas_init/humps.py +253 -0
  63. atlas_init-0.4.3/atlas_init/repos/__init__.py +0 -0
  64. atlas_init-0.4.3/atlas_init/repos/cfn.py +80 -0
  65. atlas_init-0.4.3/atlas_init/repos/go_sdk.py +47 -0
  66. atlas_init-0.4.3/atlas_init/repos/path.py +155 -0
  67. atlas_init-0.4.3/atlas_init/settings/__init__.py +0 -0
  68. atlas_init-0.4.3/atlas_init/settings/config.py +190 -0
  69. atlas_init-0.4.3/atlas_init/settings/env_vars.py +303 -0
  70. atlas_init-0.4.3/atlas_init/settings/env_vars_generated.py +34 -0
  71. atlas_init-0.4.3/atlas_init/settings/interactive.py +12 -0
  72. atlas_init-0.4.3/atlas_init/settings/path.py +74 -0
  73. atlas_init-0.4.3/atlas_init/settings/rich_utils.py +64 -0
  74. atlas_init-0.4.3/atlas_init/terraform.yaml +106 -0
  75. atlas_init-0.4.3/atlas_init/tf/.terraform.lock.hcl +125 -0
  76. atlas_init-0.4.3/atlas_init/tf/always.tf +52 -0
  77. atlas_init-0.4.3/atlas_init/tf/main.tf +168 -0
  78. atlas_init-0.4.3/atlas_init/tf/modules/aws_kms/aws_kms.tf +100 -0
  79. atlas_init-0.4.3/atlas_init/tf/modules/aws_kms/provider.tf +7 -0
  80. atlas_init-0.4.3/atlas_init/tf/modules/aws_s3/aws_s3.tf +45 -0
  81. atlas_init-0.4.3/atlas_init/tf/modules/aws_s3/provider.tf +9 -0
  82. atlas_init-0.4.3/atlas_init/tf/modules/aws_vars/aws_vars.tf +20 -0
  83. atlas_init-0.4.3/atlas_init/tf/modules/aws_vpc/aws_vpc.tf +75 -0
  84. atlas_init-0.4.3/atlas_init/tf/modules/aws_vpc/provider.tf +12 -0
  85. atlas_init-0.4.3/atlas_init/tf/modules/cfn/assume_role_services.yaml +3 -0
  86. atlas_init-0.4.3/atlas_init/tf/modules/cfn/cfn.tf +105 -0
  87. atlas_init-0.4.3/atlas_init/tf/modules/cfn/kms.tf +54 -0
  88. atlas_init-0.4.3/atlas_init/tf/modules/cfn/resource_actions.yaml +19 -0
  89. atlas_init-0.4.3/atlas_init/tf/modules/cfn/variables.tf +31 -0
  90. atlas_init-0.4.3/atlas_init/tf/modules/cloud_provider/cloud_provider.tf +66 -0
  91. atlas_init-0.4.3/atlas_init/tf/modules/cloud_provider/provider.tf +13 -0
  92. atlas_init-0.4.3/atlas_init/tf/modules/cluster/cluster.tf +116 -0
  93. atlas_init-0.4.3/atlas_init/tf/modules/cluster/provider.tf +9 -0
  94. atlas_init-0.4.3/atlas_init/tf/modules/encryption_at_rest/main.tf +29 -0
  95. atlas_init-0.4.3/atlas_init/tf/modules/encryption_at_rest/provider.tf +9 -0
  96. atlas_init-0.4.3/atlas_init/tf/modules/federated_vars/federated_vars.tf +43 -0
  97. atlas_init-0.4.3/atlas_init/tf/modules/federated_vars/provider.tf +9 -0
  98. atlas_init-0.4.3/atlas_init/tf/modules/project_extra/project_extra.tf +57 -0
  99. atlas_init-0.4.3/atlas_init/tf/modules/stream_instance/stream_instance.tf +31 -0
  100. atlas_init-0.4.3/atlas_init/tf/modules/vpc_peering/vpc_peering.tf +93 -0
  101. atlas_init-0.4.3/atlas_init/tf/modules/vpc_privatelink/atlas-privatelink.tf +32 -0
  102. atlas_init-0.4.3/atlas_init/tf/modules/vpc_privatelink/variables.tf +19 -0
  103. atlas_init-0.4.3/atlas_init/tf/modules/vpc_privatelink/versions.tf +13 -0
  104. atlas_init-0.4.3/atlas_init/tf/outputs.tf +112 -0
  105. atlas_init-0.4.3/atlas_init/tf/providers.tf +42 -0
  106. atlas_init-0.4.3/atlas_init/tf/variables.tf +145 -0
  107. atlas_init-0.4.3/atlas_init/typer_app.py +122 -0
  108. atlas_init-0.4.3/pyproject.toml +113 -0
  109. atlas_init-0.4.3/readme.md +135 -0
@@ -0,0 +1,28 @@
1
+ *.tfstate*
2
+ *.code-workspace
3
+ *.auto.tfvars
4
+ dev*.tfrc
5
+ *.env-generated
6
+ *.env
7
+ *.env_manual
8
+ profiles/
9
+ tf/modules/playground/
10
+ tf/playground_caller.tf
11
+ schema/
12
+ tf_debug/
13
+ dist
14
+ .ruff_cache
15
+ .coverage
16
+ coverage.xml
17
+ profiles_ci/
18
+ .venv
19
+ .sourcery.yaml
20
+ github_ci_run_logs
21
+ tf_bug_files
22
+ github_ci_summary
23
+ *.pyc
24
+ demo/
25
+ .env*
26
+ tf_log/
27
+ downloads
28
+ htmlcov
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Espen Albert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: atlas-init
3
+ Version: 0.4.3
4
+ Project-URL: Documentation, https://github.com/EspenAlbert/atlas-init#readme
5
+ Project-URL: Issues, https://github.com/EspenAlbert/atlas-init/issues
6
+ Project-URL: Source, https://github.com/EspenAlbert/atlas-init
7
+ Author-email: EspenAlbert <albertespen@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Python: >=3.13
14
+ Requires-Dist: appdirs==1.4.4
15
+ Requires-Dist: boto3==1.35.92
16
+ Requires-Dist: gitpython==3.1.42
17
+ Requires-Dist: humanize==4.9.0
18
+ Requires-Dist: model-lib[toml]==1.0.0b3
19
+ Requires-Dist: mypy-boto3-cloudformation==1.37.22
20
+ Requires-Dist: orjson==3.10.13
21
+ Requires-Dist: pydantic-settings==2.7.1
22
+ Requires-Dist: pygithub==2.6.1
23
+ Requires-Dist: python-hcl2==6.1.0
24
+ Requires-Dist: requests==2.32.2
25
+ Requires-Dist: rich==14.0.0
26
+ Requires-Dist: stringcase==1.2.0
27
+ Requires-Dist: tenacity==9.0.0
28
+ Requires-Dist: typer==0.15.1
29
+ Requires-Dist: zero-3rdparty==1.0.0b2
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Atlas Init - A CLI for developing integrations with MongoDB Atlas
33
+ <p align="center">
34
+ <a href="https://pypi.org/project/atlas-init/" target="_blank">
35
+ <img src="https://img.shields.io/pypi/v/atlas-init.svg">
36
+ </a>
37
+ <a href="https://pypi.org/project/atlas-init/" target="_blank">
38
+ <img src="https://img.shields.io/pypi/pyversions/atlas-init.svg">
39
+ </a>
40
+ <a href="https://github.com/EspenAlbert/py-libs/blob/main/LICENSE" target="_blank">
41
+ <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License">
42
+ </a>
43
+ <a href="https://codecov.io/github/EspenAlbert/atlas-init" target="_blank">
44
+ <img src="https://codecov.io/github/EspenAlbert/atlas-init/graph/badge.svg?token=DR7FDJXNZY" alt="Coverage">
45
+ </a>
46
+ </p>
47
+
48
+ Currently, used with
49
+ - <https://github.com/mongodb/terraform-provider-mongodbatlas>
50
+ - <https://github.com/mongodb/mongodb/mongodbatlas-cloudformation-resources>
51
+ - see [atlas_init#repo_aliases](atlas_init.yaml) for an up-to-date list
52
+
53
+ ## Quickstart
54
+ Recommended as a tool with [uvx](https://docs.astral.sh/uv/guides/tools/#running-tools)
55
+ ```shell
56
+ uvx atlas-init # help info
57
+ uvx atlas-init tf # help for tf specific commands
58
+ uvx atlas-init cfn # help for cfn specific commands
59
+ ```
60
+
61
+ ## Profile Configuration
62
+ 1. [Create an organization](https://cloud-dev.mongodb.com/v2#/preferences/organizations)
63
+ 2. Go to `access_manager` and click `Create Api Key`: <https://cloud-dev.mongodb.com/v2#/org/{ORG_ID_IN_URL_FROM_1}/access/apiKeys>
64
+ - Tick all permissions
65
+ 3. create directories and store a file in `profiles/default/.env-manual` (`ATLAS_INIT_PROFILES_PATH/{profile_name}/.env-manual`)
66
+
67
+ ```env
68
+ AWS_PROFILE=REPLACE_ME # your AWS profile used to create resources or other env-vars supported by AWS TF provider
69
+ MONGODB_ATLAS_ORG_ID=REPLACE_ME # ORG_ID_IN_URL_FROM_1
70
+ MONGODB_ATLAS_PUBLIC_KEY=REPLACE_ME # with 2
71
+ MONGODB_ATLAS_PRIVATE_KEY=REPLACE_ME # with 2
72
+ ATLAS_INIT_PROJECT_NAME=YOUR_NAME # the name of the project
73
+ MONGODB_ATLAS_BASE_URL=https://cloud-dev.mongodb.com/ # replace with https://cloud.mongodb.com/ if you are not a MongoDB Employe
74
+
75
+ # optional
76
+ TF_VAR_federated_settings_id=REPLACE_ME # will need to add organization: <https://cloud-dev.mongodb.com/v2#/federation/{FEDERATION_SETTINGS_ID}/organizations> (see internal testing wiki)
77
+
78
+ # if you want to use your locally built MongoDB atlas provider
79
+ # see appendix for details on the content
80
+ TF_CLI_CONFIG_FILE=REPLACE_ME/dev.tfrc
81
+
82
+ # if you plan developing with cloudformation
83
+ ATLAS_INIT_CFN_PROFILE=YOUR_NAME
84
+ ATLAS_INIT_CFN_REGION=eu-south-2 # find a region with few other profiles
85
+ ```
86
+
87
+ ## Local development
88
+
89
+ ```shell
90
+ git clone https://github.com/EspenAlbert/atlas-init
91
+ cd atlas-init
92
+ brew install pre-commit uv hatch
93
+ # https://github.com/astral-sh/uv <-- python packaging lightning fast
94
+ # https://hatch.pypa.io/latest/ <-- uv compatible build system for python
95
+
96
+ pre-commit install
97
+
98
+ # check that everything works
99
+ pre-commit run --all-files
100
+
101
+ # configure your virtualenv and validate the tests are working
102
+ cd py
103
+ hatch test
104
+ export VENV_DIR=$(hatch env find hatch-test | grep py3.12) # hatch venv path for env=hatch-test
105
+ export VENV_PYTHON=$VENV_DIR/bin/python
106
+ $VENV_PYTHON # ensure you are in shell with python3.12 (cmd+d to exit)
107
+ cd .. # back to repo root
108
+
109
+ # open in your IDE with virtualenv enabled
110
+ code .
111
+ # select venv path from $VENV_PYTHON output as python interpreter
112
+ # in vs code: use cmd+p and `Python: select interpreter` command
113
+
114
+ # to make it easy to invoke from any terminal (replace .zprofile with your terminal)
115
+ export pypath=$(git rev-parse --show-toplevel)/py
116
+ echo "alias atlas_init='export PYTHONPATH=$pypath && \"$VENV_PYTHON\" -m atlas_init'" >> ~/.zprofile
117
+
118
+ # test that it works
119
+ atlas_init # should show how to use the cli
120
+ ```
121
+
122
+ ### CI Installation Tests (`pip install` local wheel)
123
+ - `uv sync`
124
+ - creates a local `.venv` builds the wheel from this repo and installs it
125
+ - use `export ATLAS_INIT_PROFILES_PATH=/somewhere/to/store/your/env-vars/and/tf/state`
126
+
127
+
128
+ ## Appendix
129
+
130
+ ### Configuring vscode to use your env vars
131
+ - add to your `settings.json`
132
+
133
+ ```json
134
+ {
135
+ "go.testEnvFile": "/{SOME_PREFIX}/atlas-init/profiles/default/.env-vscode",
136
+ }
137
+ ```
138
+
139
+ ### Content of `dev.tfrc`
140
+ usually, it will look something like this:
141
+
142
+ ```hcl
143
+
144
+ provider_installation {
145
+
146
+ dev_overrides {
147
+
148
+ "mongodb/mongodbatlas" = "REPO_PATH_TF_PROVIDER/bin"
149
+
150
+ }
151
+
152
+ direct {}
153
+
154
+ }
155
+ ```
156
+
157
+ ### Re-generating the lock files
158
+
159
+ ```shell
160
+ terraform providers lock \
161
+ -platform=darwin_amd64 \
162
+ -platform=linux_amd64 \
163
+ -platform=darwin_arm64 \
164
+ -platform=linux_arm64
165
+ # -platform=windows_amd64 \
166
+ ```
@@ -0,0 +1,9 @@
1
+ from pathlib import Path
2
+
3
+ VERSION = "0.4.3"
4
+
5
+
6
+ def running_in_repo() -> bool:
7
+ maybe_git_directory = Path(__file__).parent.parent / ".git"
8
+ git_config = maybe_git_directory / "config"
9
+ return git_config.exists() and "atlas-init" in git_config.read_text()
@@ -0,0 +1,3 @@
1
+ from atlas_init.cli import typer_main
2
+
3
+ typer_main()
@@ -0,0 +1,105 @@
1
+ repo_aliases:
2
+ mongodb/terraform-provider-mongodbatlas: tf
3
+ mongodb/mongodbatlas-cloudformation-resources: cfn
4
+ test_suites:
5
+ - name: cluster
6
+ repo_go_packages:
7
+ cfn:
8
+ - cfn-resources/cluster
9
+ - name: cluster_sdk
10
+ repo_go_packages:
11
+ tf:
12
+ - internal/service/advancedcluster
13
+ - name: clusterm10
14
+ vars:
15
+ cluster_info_m10: true
16
+ - name: encryption_at_rest
17
+ vars:
18
+ use_encryption_at_rest: true
19
+ - name: federated
20
+ repo_go_packages:
21
+ tf:
22
+ - internal/service/federatedsettingsorgrolemapping
23
+ vars:
24
+ use_federated_vars: true
25
+ - name: network
26
+ repo_go_packages:
27
+ tf:
28
+ - internal/service/privatelinkendpointservicedatafederationonlinearchive
29
+ vars:
30
+ use_private_link: true
31
+ - name: network_peering
32
+ repo_go_packages:
33
+ tf:
34
+ - internal/service/networkpeering
35
+ vars:
36
+ use_vpc_peering: true
37
+ use_aws_vars: true
38
+ use_aws_vpc: true
39
+ - name: private_endpoint_regional_mode
40
+ repo_go_packages:
41
+ tf:
42
+ - internal/service/privateendpointregionalmode
43
+ vars:
44
+ use_aws_vars: true
45
+ - name: privatelink
46
+ repo_go_packages:
47
+ cfn:
48
+ - cfn-resources/cfn-private-endpoint-aws
49
+ tf:
50
+ - internal/service/privatelinkendpointservice
51
+ vars:
52
+ use_aws_vars: true
53
+ use_aws_vpc: true
54
+ - name: project
55
+ repo_go_packages:
56
+ cfn:
57
+ - cfn-resources/project
58
+ tf:
59
+ - internal/service/project
60
+ vars:
61
+ use_project_extra: true
62
+ - name: resource_policy
63
+ sequential_tests: true
64
+ repo_go_packages:
65
+ cfn:
66
+ - cfn-resources/resource-policy
67
+ tf:
68
+ - internal/service/resourcepolicy
69
+ - name: s3
70
+ repo_go_packages:
71
+ tf:
72
+ - internal/service/cloudbackupsnapshotexportbucket
73
+ vars:
74
+ use_aws_s3: true
75
+ - name: s3_with_cluster
76
+ repo_go_packages:
77
+ tf:
78
+ - internal/service/cloudbackupsnapshotexportjob
79
+ vars:
80
+ cluster_info_m10: true
81
+ use_aws_s3: true
82
+ - name: search_index
83
+ repo_go_packages:
84
+ tf:
85
+ - internal/service/searchindex
86
+ vars:
87
+ cluster_info: true
88
+ - name: stream_connection
89
+ repo_go_packages:
90
+ tf:
91
+ - internal/service/streamconnection
92
+ cfn:
93
+ - cfn-resources/stream-connection
94
+ vars:
95
+ cluster_info_m10: true
96
+ stream_instance: true
97
+ - name: trigger
98
+ repo_go_packages:
99
+ cfn:
100
+ - cfn-resources/trigger
101
+ vars:
102
+ cluster_info_m10: true
103
+ post_apply_hooks:
104
+ - name: create_realm_resources
105
+ locate: atlas_init.cli_root.trigger.create_realm_app
@@ -0,0 +1,261 @@
1
+ import logging
2
+ from collections.abc import Callable
3
+ from pathlib import Path
4
+ from pydoc import locate
5
+ from typing import Literal
6
+
7
+ import typer
8
+ from model_lib import dump, parse_payload
9
+ from zero_3rdparty.file_utils import iter_paths
10
+
11
+ from atlas_init.cli_helper import sdk_auto_changes
12
+ from atlas_init.cli_helper.run import (
13
+ run_binary_command_is_ok,
14
+ run_command_exit_on_failure,
15
+ run_command_receive_result,
16
+ )
17
+ from atlas_init.cli_helper.sdk import (
18
+ SDK_VERSION_HELP,
19
+ SdkVersion,
20
+ SdkVersionUpgrade,
21
+ find_breaking_changes,
22
+ find_latest_sdk_version,
23
+ format_breaking_changes,
24
+ is_removed,
25
+ parse_breaking_changes,
26
+ )
27
+ from atlas_init.cli_helper.tf_runner import (
28
+ TerraformRunError,
29
+ dump_tf_vars,
30
+ export_outputs,
31
+ get_tf_vars,
32
+ run_terraform,
33
+ )
34
+ from atlas_init.repos.go_sdk import go_sdk_breaking_changes
35
+ from atlas_init.repos.path import (
36
+ Repo,
37
+ current_repo,
38
+ current_repo_path,
39
+ find_go_mod_dir,
40
+ find_paths,
41
+ resource_name,
42
+ )
43
+ from atlas_init.settings.config import RepoAliasNotFoundError, TestSuite
44
+ from atlas_init.settings.env_vars import (
45
+ active_suites,
46
+ init_settings,
47
+ )
48
+ from atlas_init.settings.path import (
49
+ CwdIsNoRepoPathError,
50
+ dump_vscode_dotenv,
51
+ repo_path_rel_path,
52
+ )
53
+ from atlas_init.typer_app import app, app_command, extra_root_commands
54
+
55
+ logger = logging.getLogger(__name__)
56
+
57
+
58
+ @app_command()
59
+ def init(context: typer.Context):
60
+ settings = init_settings()
61
+ extra_args = context.args
62
+ logger.info(f"in the init command: {extra_args}")
63
+ run_terraform(settings, "init", extra_args)
64
+
65
+
66
+ @app_command()
67
+ def plan(context: typer.Context, *, skip_outputs: bool = False):
68
+ _plan_or_apply(context.args, "plan", skip_outputs=skip_outputs)
69
+
70
+
71
+ @app_command()
72
+ def apply(context: typer.Context, *, skip_outputs: bool = False):
73
+ suites = _plan_or_apply(context.args, "apply", skip_outputs=skip_outputs)
74
+ for suite in suites:
75
+ for hook in suite.post_apply_hooks:
76
+ logger.info(f"running post apply hook: {hook.name}")
77
+ hook_func = locate(hook.locate)
78
+ hook_func() # type: ignore
79
+
80
+
81
+ def _plan_or_apply(extra_args: list[str], command: Literal["plan", "apply"], *, skip_outputs: bool) -> list[TestSuite]: # type: ignore
82
+ settings = init_settings()
83
+ logger.info(f"using the '{command}' command, extra args: {extra_args}")
84
+ try:
85
+ suites = active_suites(settings)
86
+ except (CwdIsNoRepoPathError, RepoAliasNotFoundError) as e:
87
+ logger.warning(repr(e))
88
+ suites = []
89
+
90
+ tf_vars = get_tf_vars(settings, suites)
91
+ dump_tf_vars(settings, tf_vars)
92
+
93
+ try:
94
+ run_terraform(settings, command, extra_args)
95
+ except TerraformRunError as e:
96
+ logger.error(repr(e)) # noqa: TRY400
97
+ raise typer.Exit(1) from e
98
+
99
+ if not skip_outputs:
100
+ export_outputs(settings)
101
+
102
+ if settings.env_vars_generated.exists():
103
+ dump_vscode_dotenv(settings.env_vars_generated, settings.env_vars_vs_code)
104
+ logger.info(f"your .env file is ready @ {settings.env_vars_vs_code}")
105
+ return suites
106
+
107
+
108
+ @app_command()
109
+ def destroy(context: typer.Context):
110
+ extra_args = context.args
111
+ settings = init_settings()
112
+ if not settings.tf_state_path.exists():
113
+ logger.warning(f"no terraform state found {settings.tf_state_path}, exiting")
114
+ return
115
+ tf_vars = get_tf_vars(settings, [])
116
+ dump_tf_vars(settings, tf_vars)
117
+ try:
118
+ run_terraform(settings, "destroy", extra_args)
119
+ except TerraformRunError as e:
120
+ logger.error(repr(e)) # noqa: TRY400
121
+ return
122
+
123
+
124
+ @app_command()
125
+ def sdk_upgrade(
126
+ old: SdkVersion = typer.Argument(help=SDK_VERSION_HELP),
127
+ new: SdkVersion = typer.Argument(
128
+ default_factory=find_latest_sdk_version,
129
+ help=SDK_VERSION_HELP + "\nNo Value=Latest",
130
+ ),
131
+ resource: str = typer.Option("", help="for only upgrading a single resource"),
132
+ dry_run: bool = typer.Option(False, help="only log out the changes"),
133
+ auto_change_name: str = typer.Option("", help="any extra replacements done in the file"),
134
+ ):
135
+ SdkVersionUpgrade(old=old, new=new)
136
+ repo_path, _ = repo_path_rel_path()
137
+ logger.info(f"bumping from {old} -> {new} @ {repo_path}")
138
+
139
+ sdk_breaking_changes_path = go_sdk_breaking_changes(repo_path)
140
+ all_breaking_changes = parse_breaking_changes(sdk_breaking_changes_path, old, new)
141
+ replacements = {
142
+ f"go.mongodb.org/atlas-sdk/{old}/mockadmin": f"go.mongodb.org/atlas-sdk/{new}/mockadmin",
143
+ f"go.mongodb.org/atlas-sdk/{old}/admin": f"go.mongodb.org/atlas-sdk/{new}/admin",
144
+ }
145
+ auto_modifier: Callable[[str, str], str] | None = None
146
+ if auto_change_name:
147
+ func_path = f"{sdk_auto_changes.__name__}.{auto_change_name}"
148
+ auto_modifier = locate(func_path) # type: ignore
149
+
150
+ change_count = 0
151
+ resources: set[str] = set()
152
+ resources_breaking_changes: set[str] = set()
153
+ for path in iter_paths(repo_path, "*.go", ".mockery.yaml"):
154
+ text_old = path.read_text()
155
+ if all(replace_in not in text_old for replace_in in replacements):
156
+ continue
157
+ r_name = resource_name(repo_path, path)
158
+ if resource and resource != r_name:
159
+ continue
160
+ resources.add(r_name)
161
+ logger.info(f"updating sdk version in {path}")
162
+ if breaking_changes := find_breaking_changes(text_old, all_breaking_changes):
163
+ changes_formatted = format_breaking_changes(text_old, breaking_changes)
164
+ logger.warning(f"found breaking changes: {changes_formatted}")
165
+ if is_removed(breaking_changes):
166
+ resources_breaking_changes.add(r_name)
167
+ text_new = text_old
168
+ for replace_in, replace_out in replacements.items():
169
+ text_new = text_new.replace(replace_in, replace_out)
170
+ if not dry_run:
171
+ if auto_modifier:
172
+ text_new = auto_modifier(text_new, old)
173
+ path.write_text(text_new)
174
+ change_count += 1
175
+ if change_count == 0:
176
+ logger.warning("no changes found")
177
+ return
178
+ logger.info(f"changed in total: {change_count} files")
179
+ resources_str = "\n".join(
180
+ f"- {r} 💥" if r in resources_breaking_changes else f"- {r}" for r in sorted(resources) if r
181
+ )
182
+ logger.info(f"resources changed: \n{resources_str}")
183
+ if dry_run:
184
+ logger.warning("dry-run, no changes to go.mod")
185
+ return
186
+ go_mod_parent = find_go_mod_dir(repo_path)
187
+ if not run_binary_command_is_ok("go", "mod tidy", cwd=go_mod_parent, logger=logger):
188
+ logger.critical(f"failed to run go mod tidy in {go_mod_parent}")
189
+ raise typer.Exit(1)
190
+
191
+
192
+ @app_command()
193
+ def pre_commit(
194
+ skip_build: bool = typer.Option(default=False),
195
+ skip_lint: bool = typer.Option(default=False),
196
+ max_issues: int = typer.Option(1000, "-m", "--max"),
197
+ ):
198
+ golang_ci_lint_args = f"--max-same-issues {max_issues} --max-issues-per-linter {max_issues}"
199
+ match current_repo():
200
+ case Repo.CFN:
201
+ repo_path, resource_path, r_name = find_paths()
202
+ build_cmd = f"cd {resource_path} && make build"
203
+ # TODO: understand why piping to grep doesn't work
204
+ # f"golangci-lint run --path-prefix=./cfn-resources | grep {r_name}"
205
+ format_cmd_str = (
206
+ f"cd cfn-resources && golangci-lint run --path-prefix=./cfn-resources {golang_ci_lint_args}"
207
+ )
208
+ case Repo.TF:
209
+ repo_path = current_repo_path()
210
+ build_cmd = "make build"
211
+ format_cmd_str = f"golangci-lint run {golang_ci_lint_args}"
212
+ case _:
213
+ raise NotImplementedError
214
+ if skip_build:
215
+ logger.warning("skipping build")
216
+ else:
217
+ run_command_exit_on_failure(build_cmd, cwd=repo_path, logger=logger)
218
+ if skip_lint:
219
+ logger.warning("skipping formatting")
220
+ else:
221
+ run_command_exit_on_failure(format_cmd_str, cwd=repo_path, logger=logger)
222
+
223
+
224
+ @app_command()
225
+ def repo_dump():
226
+ code_root = Path.home() / "code"
227
+ path_urls = {}
228
+ for repo_git_path in iter_paths(code_root, ".git", exclude_folder_names=[".terraform"]):
229
+ repo_path = repo_git_path.parent
230
+ logger.info(f"repo: {repo_path}")
231
+ url = run_command_receive_result("git remote get-url origin", cwd=repo_path, logger=logger, can_fail=True)
232
+ if url.startswith("FAIL:"):
233
+ continue
234
+ path_urls[str(repo_path)] = url
235
+ out_path = code_root / "repos.json"
236
+ repos_json = dump(path_urls, "pretty_json")
237
+ out_path.write_text(repos_json)
238
+
239
+
240
+ @app_command()
241
+ def repo_clone():
242
+ repos_file = Path.home() / "code" / "repos.json"
243
+ repo_path_json: dict[str, str] = parse_payload(repos_file) # type: ignore
244
+ for repo_path_str, url in repo_path_json.items():
245
+ logger.info(f"cloning {url} @ {repo_path_str}")
246
+ repo_path = Path(repo_path_str)
247
+ parent_dir = repo_path.parent
248
+ parent_dir.mkdir(parents=True, exist_ok=True)
249
+ if repo_path.exists():
250
+ logger.warning(f"skipping {repo_path}, already exists")
251
+ continue
252
+ run_command_exit_on_failure(f"git clone {url} {repo_path.name}", cwd=parent_dir, logger=logger)
253
+
254
+
255
+ def typer_main():
256
+ extra_root_commands()
257
+ app()
258
+
259
+
260
+ if __name__ == "__main__":
261
+ typer_main()
@@ -0,0 +1,16 @@
1
+ from typing import Any
2
+
3
+ import typer
4
+ from model_lib import parse_payload
5
+ from zero_3rdparty.iter_utils import key_equal_value_to_dict
6
+
7
+ option_sdk_repo_path = typer.Option("", "-sdk", "--sdk-repo-path", help="the path to the sdk repo")
8
+
9
+
10
+ def parse_key_values(params: list[str]) -> dict[str, str]:
11
+ return key_equal_value_to_dict(params)
12
+
13
+
14
+ def parse_key_values_any(params: list[str]) -> dict[str, Any]:
15
+ str_dict = parse_key_values(params)
16
+ return {k: parse_payload(v) if v.startswith(("{", "[")) else v for k, v in str_dict.items()}
File without changes