zrb 0.0.86__py3-none-any.whl → 0.0.87__py3-none-any.whl
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.
- zrb/__init__.py +3 -1
- zrb/action/runner.py +7 -3
- zrb/builtin/__init__.py +1 -1
- zrb/builtin/base64.py +1 -1
- zrb/builtin/devtool/devtool_install.py +3 -1
- zrb/builtin/env.py +6 -3
- zrb/builtin/explain.py +3 -1
- zrb/builtin/generator/__init__.py +4 -8
- zrb/builtin/generator/app_generator/add.py +6 -6
- zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/add.py +60 -50
- zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/container.py +1 -1
- zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/deployment.py +2 -2
- zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/image.py +1 -1
- zrb/builtin/generator/app_generator/template/_automate/snake_zrb_meta_template_name/template/_automate/snake_zrb_app_name/local.py +4 -2
- zrb/builtin/generator/cmd_task/add.py +6 -6
- zrb/builtin/generator/cmd_task/template/_automate/snake_zrb_task_name.py +1 -1
- zrb/builtin/generator/{_common → common}/helper.py +6 -0
- zrb/builtin/generator/{_common → common}/task_factory.py +9 -5
- zrb/builtin/generator/docker_compose_task/add.py +8 -8
- zrb/builtin/generator/docker_compose_task/template/_automate/snake_zrb_task_name.py +1 -1
- zrb/builtin/generator/fastapp/add.py +24 -24
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/_common.py +2 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/container.py +1 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/deployment.py +1 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/frontend.py +1 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/image.py +1 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/load_test.py +3 -2
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/local.py +1 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_zrb_app_name/test.py +2 -4
- zrb/builtin/generator/fastapp_crud/add.py +8 -121
- zrb/builtin/generator/fastapp_crud/helper.py +115 -0
- zrb/builtin/generator/fastapp_crud/{add_navigation.py → task_factory.py} +5 -3
- zrb/builtin/generator/fastapp_field/add.py +8 -280
- zrb/builtin/generator/fastapp_field/helper.py +283 -0
- zrb/builtin/generator/fastapp_module/add.py +19 -328
- zrb/builtin/generator/fastapp_module/helper.py +326 -0
- zrb/builtin/generator/pip_package/add.py +8 -8
- zrb/builtin/generator/pip_package/template/_automate/snake_zrb_package_name/local.py +1 -1
- zrb/builtin/generator/project/create.py +5 -3
- zrb/builtin/generator/project_task/task_factory.py +33 -21
- zrb/builtin/generator/project_task/template/_automate/_project/build_project_images.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/deploy_project.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/destroy_project.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/push_project_images.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/remove_project_containers.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/start_project.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/start_project_containers.py +1 -1
- zrb/builtin/generator/project_task/template/_automate/_project/stop_project_containers.py +1 -1
- zrb/builtin/generator/python_task/add.py +6 -6
- zrb/builtin/generator/python_task/template/_automate/snake_zrb_task_name.py +1 -1
- zrb/builtin/generator/simple_python_app/add.py +28 -30
- zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/container.py +1 -1
- zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/deployment.py +1 -1
- zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/image.py +1 -1
- zrb/builtin/generator/simple_python_app/template/_automate/snake_zrb_app_name/local.py +1 -1
- zrb/builtin/git.py +1 -1
- zrb/builtin/md5.py +1 -1
- zrb/builtin/project.py +1 -1
- zrb/builtin/ubuntu.py +1 -1
- zrb/config/config.py +8 -6
- zrb/helper/accessories/color.py +5 -1
- zrb/helper/accessories/icon.py +2 -0
- zrb/helper/accessories/name.py +2 -0
- zrb/helper/advertisement.py +1 -0
- zrb/helper/cli.py +5 -1
- zrb/helper/codemod/add_argument_to_function.py +3 -0
- zrb/helper/codemod/add_argument_to_function_call.py +3 -0
- zrb/helper/codemod/add_assert_resource.py +2 -0
- zrb/helper/codemod/add_function_call.py +2 -0
- zrb/helper/codemod/add_import_module.py +3 -0
- zrb/helper/codemod/add_key_value_to_dict.py +2 -0
- zrb/helper/codemod/add_property_to_class.py +3 -0
- zrb/helper/codemod/add_upstream_to_task.py +3 -0
- zrb/helper/codemod/append_code_to_function.py +3 -0
- zrb/helper/codemod/format_code.py +2 -0
- zrb/helper/default_env.py +2 -0
- zrb/helper/docker_compose/fetch_external_env.py +3 -0
- zrb/helper/docker_compose/file.py +4 -0
- zrb/helper/env_map/fetch.py +7 -0
- zrb/helper/file/text.py +4 -0
- zrb/helper/git/detect_changes.py +4 -0
- zrb/helper/loader/load_module.py +2 -0
- zrb/helper/map/conversion.py +2 -0
- zrb/helper/string/conversion.py +5 -0
- zrb/helper/string/double_quote.py +6 -2
- zrb/helper/string/jinja.py +2 -0
- zrb/helper/string/parse_replacement.py +2 -0
- zrb/helper/util.py +13 -0
- zrb/task/any_task.py +2 -2
- zrb/task/base_task.py +15 -15
- zrb/task/base_task_composite.py +3 -3
- zrb/task/cmd_task.py +2 -2
- zrb/task/decorator.py +2 -2
- zrb/task/docker_compose_task.py +2 -2
- zrb/task/flow_task.py +5 -5
- zrb/task/http_checker.py +2 -2
- zrb/task/path_checker.py +2 -2
- zrb/task/port_checker.py +2 -2
- zrb/task/resource_maker.py +3 -5
- zrb/task_input/any_input.py +23 -0
- zrb/task_input/base_input.py +46 -43
- zrb/task_input/float_input.py +0 -1
- {zrb-0.0.86.dist-info → zrb-0.0.87.dist-info}/METADATA +1 -1
- {zrb-0.0.86.dist-info → zrb-0.0.87.dist-info}/RECORD +111 -108
- zrb/config.toml +0 -0
- /zrb/builtin/generator/{_common → common}/__init__.py +0 -0
- /zrb/builtin/generator/{_common → common}/task_input.py +0 -0
- /zrb/builtin/{_group.py → group.py} +0 -0
- /zrb/task_input/{_constant.py → constant.py} +0 -0
- {zrb-0.0.86.dist-info → zrb-0.0.87.dist-info}/LICENSE +0 -0
- {zrb-0.0.86.dist-info → zrb-0.0.87.dist-info}/WHEEL +0 -0
- {zrb-0.0.86.dist-info → zrb-0.0.87.dist-info}/entry_points.txt +0 -0
@@ -1,27 +1,22 @@
|
|
1
|
-
from typing import Any
|
2
|
-
from
|
3
|
-
|
1
|
+
from typing import Any
|
2
|
+
from .helper import (
|
3
|
+
create_microservice_config, register_module, register_migration,
|
4
|
+
create_app_config, append_all_enabled_env, append_all_disabled_env,
|
5
|
+
append_src_template_env, append_deployment_template_env
|
6
|
+
)
|
7
|
+
from ..common.helper import validate_existing_project_dir
|
8
|
+
from ..common.task_input import (
|
9
|
+
project_dir_input, app_name_input, module_name_input
|
10
|
+
)
|
11
|
+
from ...group import project_add_group
|
4
12
|
from ....task.task import Task
|
5
13
|
from ....task.decorator import python_task
|
6
14
|
from ....task.resource_maker import ResourceMaker
|
7
15
|
from ....runner import runner
|
8
|
-
from .._common.task_input import (
|
9
|
-
project_dir_input, app_name_input,
|
10
|
-
module_name_input
|
11
|
-
)
|
12
|
-
from .._common.helper import validate_existing_project_dir
|
13
16
|
from ....helper import util
|
14
|
-
from ....helper.codemod.add_import_module import add_import_module
|
15
|
-
from ....helper.codemod.add_function_call import add_function_call
|
16
|
-
from ....helper.codemod.append_code_to_function import append_code_to_function
|
17
|
-
from ....helper.docker_compose.file import add_services
|
18
|
-
from ....helper.file.text import (
|
19
|
-
read_text_file_async, write_text_file_async, append_text_file_async
|
20
|
-
)
|
21
17
|
|
22
18
|
import asyncio
|
23
19
|
import os
|
24
|
-
import jsons
|
25
20
|
|
26
21
|
CURRENT_DIR = os.path.dirname(__file__)
|
27
22
|
|
@@ -95,335 +90,31 @@ async def add_fastapp_module(*args: Any, **kwargs: Any):
|
|
95
90
|
snake_module_name = util.to_snake_case(module_name)
|
96
91
|
upper_snake_module_name = snake_module_name.upper()
|
97
92
|
await asyncio.gather(
|
98
|
-
asyncio.create_task(
|
93
|
+
asyncio.create_task(create_microservice_config(
|
99
94
|
task, project_dir, kebab_app_name, snake_app_name,
|
100
95
|
kebab_module_name, snake_module_name, upper_snake_module_name
|
101
96
|
)),
|
102
|
-
asyncio.create_task(
|
97
|
+
asyncio.create_task(register_module(
|
103
98
|
task, project_dir, kebab_app_name, snake_module_name
|
104
99
|
)),
|
105
|
-
asyncio.create_task(
|
100
|
+
asyncio.create_task(register_migration(
|
106
101
|
task, project_dir, kebab_app_name, snake_module_name
|
107
102
|
)),
|
108
|
-
asyncio.create_task(
|
103
|
+
asyncio.create_task(create_app_config(
|
109
104
|
task, project_dir, kebab_app_name, snake_module_name,
|
110
105
|
upper_snake_module_name
|
111
106
|
)),
|
112
|
-
asyncio.create_task(
|
107
|
+
asyncio.create_task(append_all_enabled_env(
|
113
108
|
task, project_dir, kebab_app_name, upper_snake_module_name
|
114
109
|
)),
|
115
|
-
asyncio.create_task(
|
110
|
+
asyncio.create_task(append_all_disabled_env(
|
116
111
|
task, project_dir, kebab_app_name, upper_snake_module_name
|
117
112
|
)),
|
118
|
-
asyncio.create_task(
|
113
|
+
asyncio.create_task(append_src_template_env(
|
119
114
|
task, project_dir, kebab_app_name, upper_snake_module_name
|
120
115
|
)),
|
121
|
-
asyncio.create_task(
|
116
|
+
asyncio.create_task(append_deployment_template_env(
|
122
117
|
task, project_dir, kebab_app_name, upper_snake_module_name
|
123
118
|
)),
|
124
119
|
)
|
125
120
|
task.print_out('Success')
|
126
|
-
|
127
|
-
|
128
|
-
###############################################################################
|
129
|
-
# Helper Definitions
|
130
|
-
###############################################################################
|
131
|
-
|
132
|
-
|
133
|
-
async def _create_microservice_config(
|
134
|
-
task: Task,
|
135
|
-
project_dir: str,
|
136
|
-
kebab_app_name: str,
|
137
|
-
snake_app_name: str,
|
138
|
-
kebab_module_name: str,
|
139
|
-
snake_module_name: str,
|
140
|
-
upper_snake_module_name: str
|
141
|
-
):
|
142
|
-
modules = await _create_automation_json_config(
|
143
|
-
task, project_dir, snake_app_name, snake_module_name
|
144
|
-
)
|
145
|
-
return await asyncio.gather(
|
146
|
-
asyncio.create_task(_add_docker_compose_service(
|
147
|
-
task, modules, project_dir, kebab_app_name,
|
148
|
-
snake_app_name, kebab_module_name, snake_module_name,
|
149
|
-
upper_snake_module_name
|
150
|
-
)),
|
151
|
-
asyncio.create_task(_append_compose_env(
|
152
|
-
task, modules, project_dir, kebab_app_name, upper_snake_module_name
|
153
|
-
))
|
154
|
-
)
|
155
|
-
|
156
|
-
|
157
|
-
async def _add_docker_compose_service(
|
158
|
-
task: Task,
|
159
|
-
modules: List[str],
|
160
|
-
project_dir: str,
|
161
|
-
kebab_app_name: str,
|
162
|
-
snake_app_name: str,
|
163
|
-
kebab_module_name: str,
|
164
|
-
snake_module_name: str,
|
165
|
-
upper_snake_module_name: str
|
166
|
-
):
|
167
|
-
module_app_port = 8080 + len(modules)
|
168
|
-
module_app_port_str = str(module_app_port)
|
169
|
-
docker_compose_file_path = os.path.join(
|
170
|
-
project_dir, 'src', kebab_app_name, 'docker-compose.yml'
|
171
|
-
)
|
172
|
-
app_container_port_env_name = f'APP_{upper_snake_module_name}_MODULE_PORT'
|
173
|
-
app_container_port_env = '${' + app_container_port_env_name + ':-' + module_app_port_str + '}' # noqa
|
174
|
-
app_host_port_env_name = f'APP_{upper_snake_module_name}_HOST_MODULE_PORT'
|
175
|
-
app_host_port_env = '${' + app_host_port_env_name + ':-' + module_app_port_str + '}' # noqa
|
176
|
-
service_definition = _get_new_docker_compose_service_definition(
|
177
|
-
kebab_app_name, snake_app_name, kebab_module_name, snake_module_name,
|
178
|
-
upper_snake_module_name, app_host_port_env, app_container_port_env
|
179
|
-
)
|
180
|
-
task.print_out(f'Add service at: {docker_compose_file_path}')
|
181
|
-
add_services(
|
182
|
-
file_name=docker_compose_file_path,
|
183
|
-
new_services=service_definition,
|
184
|
-
)
|
185
|
-
|
186
|
-
|
187
|
-
def _get_new_docker_compose_service_definition(
|
188
|
-
kebab_app_name: str,
|
189
|
-
snake_app_name: str,
|
190
|
-
kebab_module_name: str,
|
191
|
-
snake_module_name: str,
|
192
|
-
upper_snake_module_name: str,
|
193
|
-
app_host_port_env: str,
|
194
|
-
app_container_port_env: str
|
195
|
-
) -> Mapping[str, Any]:
|
196
|
-
return {
|
197
|
-
f'{kebab_app_name}-{kebab_module_name}-service': {
|
198
|
-
'build': {
|
199
|
-
'dockerfile': 'Dockerfile',
|
200
|
-
'context': './src'
|
201
|
-
},
|
202
|
-
'image': '${IMAGE:-' + kebab_app_name + '}',
|
203
|
-
'container_name': '${CONTAINER_PREFIX:-my}-' + f'{kebab_app_name}-{kebab_module_name}-service', # noqa
|
204
|
-
'hostname': f'{kebab_app_name}-{kebab_module_name}-service',
|
205
|
-
'env_file': [
|
206
|
-
'src/template.env',
|
207
|
-
'all-module-disabled.env'
|
208
|
-
],
|
209
|
-
'environment': {
|
210
|
-
'APP_NAME': '${APP_NAME:-' + kebab_app_name + '}-' + f'{kebab_module_name}-service', # noqa
|
211
|
-
'APP_PORT': app_container_port_env,
|
212
|
-
'APP_ENABLE_EVENT_HANDLER': 'true',
|
213
|
-
'APP_ENABLE_RPC_SERVER': 'true',
|
214
|
-
'APP_ENABLE_API': 'false',
|
215
|
-
'APP_ENABLE_FRONTEND': 'false',
|
216
|
-
f'APP_ENABLE_{upper_snake_module_name}_MODULE': 'true',
|
217
|
-
},
|
218
|
-
'ports': [
|
219
|
-
f'{app_host_port_env}:{app_container_port_env}'
|
220
|
-
],
|
221
|
-
'restart': 'unless-stopped',
|
222
|
-
'profiles': [
|
223
|
-
'microservices'
|
224
|
-
],
|
225
|
-
'healthcheck': {
|
226
|
-
'test': [
|
227
|
-
'CMD-SHELL',
|
228
|
-
'curl --fail http://localhost:' + app_container_port_env + '/readiness || exit 1' # noqa
|
229
|
-
],
|
230
|
-
'interval': '5s',
|
231
|
-
'timeout': '3s',
|
232
|
-
'retries': 10
|
233
|
-
},
|
234
|
-
'networks': ['zrb']
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
|
239
|
-
async def _append_compose_env(
|
240
|
-
task: Task,
|
241
|
-
modules: List[str],
|
242
|
-
project_dir: str,
|
243
|
-
kebab_app_name: str,
|
244
|
-
upper_snake_module_name: str
|
245
|
-
):
|
246
|
-
compose_template_env_path = os.path.join(
|
247
|
-
project_dir, 'src', kebab_app_name, 'docker-compose.env'
|
248
|
-
)
|
249
|
-
compose_env_map = dotenv_values(compose_template_env_path)
|
250
|
-
host_port = int(compose_env_map.get('APP_GATEWAY_HOST_PORT', '8080'))
|
251
|
-
module_app_port = host_port + len(modules)
|
252
|
-
new_env_str = '\n'.join([
|
253
|
-
f'APP_{upper_snake_module_name}_HOST_MODULE_PORT={module_app_port}',
|
254
|
-
f'APP_{upper_snake_module_name}_MODULE_PORT={module_app_port}',
|
255
|
-
])
|
256
|
-
task.print_out(f'Add new environment to: {compose_template_env_path}')
|
257
|
-
await append_text_file_async(compose_template_env_path, new_env_str)
|
258
|
-
|
259
|
-
|
260
|
-
async def _append_src_template_env(
|
261
|
-
task: Task,
|
262
|
-
project_dir: str,
|
263
|
-
kebab_app_name: str,
|
264
|
-
upper_snake_module_name: str
|
265
|
-
):
|
266
|
-
src_template_env_path = os.path.join(
|
267
|
-
project_dir, 'src', kebab_app_name, 'src', 'template.env'
|
268
|
-
)
|
269
|
-
new_env_str = '\n'.join([
|
270
|
-
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true',
|
271
|
-
])
|
272
|
-
task.print_out(f'Add new environment to: {src_template_env_path}')
|
273
|
-
await append_text_file_async(src_template_env_path, new_env_str)
|
274
|
-
|
275
|
-
|
276
|
-
async def _append_deployment_template_env(
|
277
|
-
task: Task,
|
278
|
-
project_dir: str,
|
279
|
-
kebab_app_name: str,
|
280
|
-
upper_snake_module_name: str
|
281
|
-
):
|
282
|
-
deployment_template_env_path = os.path.join(
|
283
|
-
project_dir, 'src', kebab_app_name, 'deployment', 'template.env'
|
284
|
-
)
|
285
|
-
new_env_str = '\n'.join([
|
286
|
-
f'REPLICA_{upper_snake_module_name}_SERVICE=1',
|
287
|
-
])
|
288
|
-
task.print_out(f'Add new environment to: {deployment_template_env_path}')
|
289
|
-
await append_text_file_async(deployment_template_env_path, new_env_str)
|
290
|
-
|
291
|
-
|
292
|
-
async def _append_all_enabled_env(
|
293
|
-
task: Task,
|
294
|
-
project_dir: str,
|
295
|
-
kebab_app_name: str,
|
296
|
-
upper_snake_module_name: str
|
297
|
-
):
|
298
|
-
all_enabled_env_path = os.path.join(
|
299
|
-
project_dir, 'src', kebab_app_name, 'all-module-enabled.env'
|
300
|
-
)
|
301
|
-
task.print_out(f'Add new environment to: {all_enabled_env_path}')
|
302
|
-
await append_text_file_async(
|
303
|
-
all_enabled_env_path,
|
304
|
-
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true'
|
305
|
-
)
|
306
|
-
|
307
|
-
|
308
|
-
async def _append_all_disabled_env(
|
309
|
-
task: Task,
|
310
|
-
project_dir: str,
|
311
|
-
kebab_app_name: str,
|
312
|
-
upper_snake_module_name: str
|
313
|
-
):
|
314
|
-
all_disabled_env_path = os.path.join(
|
315
|
-
project_dir, 'src', kebab_app_name, 'all-module-disabled.env'
|
316
|
-
)
|
317
|
-
task.print_out(f'Add new environment to: {all_disabled_env_path}')
|
318
|
-
await append_text_file_async(
|
319
|
-
all_disabled_env_path,
|
320
|
-
f'APP_ENABLE_{upper_snake_module_name}_MODULE=false'
|
321
|
-
)
|
322
|
-
|
323
|
-
|
324
|
-
async def _create_app_config(
|
325
|
-
task: Task,
|
326
|
-
project_dir: str,
|
327
|
-
kebab_app_name: str,
|
328
|
-
snake_module_name: str,
|
329
|
-
upper_snake_module_name: str
|
330
|
-
):
|
331
|
-
config_file_path = os.path.join(
|
332
|
-
project_dir, 'src', kebab_app_name, 'src', 'config.py'
|
333
|
-
)
|
334
|
-
config_code = '\n'.join([
|
335
|
-
f'app_enable_{snake_module_name}_module = str_to_boolean(os.environ.get(', # noqa
|
336
|
-
f" 'APP_ENABLE_{upper_snake_module_name}_MODULE', 'true'"
|
337
|
-
'))'
|
338
|
-
])
|
339
|
-
task.print_out(f'Read config from: {config_file_path}')
|
340
|
-
code = await read_text_file_async(config_file_path)
|
341
|
-
code += '\n' + config_code
|
342
|
-
task.print_out(f'Write config to: {config_file_path}')
|
343
|
-
await write_text_file_async(config_file_path, code)
|
344
|
-
|
345
|
-
|
346
|
-
async def _create_automation_json_config(
|
347
|
-
task: Task,
|
348
|
-
project_dir: str,
|
349
|
-
snake_app_name: str,
|
350
|
-
snake_module_name: str,
|
351
|
-
):
|
352
|
-
json_modules_file_path = os.path.join(
|
353
|
-
project_dir, '_automate', snake_app_name, 'config', 'modules.json'
|
354
|
-
)
|
355
|
-
task.print_out(f'Read json config from: {json_modules_file_path}')
|
356
|
-
json_str = await read_text_file_async(json_modules_file_path)
|
357
|
-
task.print_out(f'Add "{snake_module_name}" to json config')
|
358
|
-
modules: List[str] = jsons.loads(json_str)
|
359
|
-
modules.append(snake_module_name)
|
360
|
-
json_str = jsons.dumps(modules)
|
361
|
-
task.print_out(f'Write new json config to: {json_modules_file_path}')
|
362
|
-
await write_text_file_async(json_modules_file_path, json_str)
|
363
|
-
return modules
|
364
|
-
|
365
|
-
|
366
|
-
async def _register_migration(
|
367
|
-
task: Task,
|
368
|
-
project_dir: str,
|
369
|
-
kebab_app_name: str,
|
370
|
-
snake_module_name: str
|
371
|
-
):
|
372
|
-
app_migration_file_path = os.path.join(
|
373
|
-
project_dir, 'src', kebab_app_name, 'src', 'migrate.py'
|
374
|
-
)
|
375
|
-
import_module_path = '.'.join([
|
376
|
-
'module', snake_module_name, 'migrate'
|
377
|
-
])
|
378
|
-
function_name = f'migrate_{snake_module_name}'
|
379
|
-
task.print_out(f'Read code from: {app_migration_file_path}')
|
380
|
-
code = await read_text_file_async(app_migration_file_path)
|
381
|
-
task.print_out(
|
382
|
-
f'Add import "{function_name}" from "{import_module_path}" to the code'
|
383
|
-
)
|
384
|
-
code = add_import_module(
|
385
|
-
code=code,
|
386
|
-
module_path=import_module_path,
|
387
|
-
resource=function_name
|
388
|
-
)
|
389
|
-
task.print_out(f'Add "{function_name}" call to the code')
|
390
|
-
code = append_code_to_function(
|
391
|
-
code=code,
|
392
|
-
function_name='migrate',
|
393
|
-
new_code=f'await {function_name}()'
|
394
|
-
)
|
395
|
-
task.print_out(f'Write modified code to: {app_migration_file_path}')
|
396
|
-
await write_text_file_async(app_migration_file_path, code)
|
397
|
-
|
398
|
-
|
399
|
-
async def _register_module(
|
400
|
-
task: Task,
|
401
|
-
project_dir: str,
|
402
|
-
kebab_app_name: str,
|
403
|
-
snake_module_name: str
|
404
|
-
):
|
405
|
-
app_main_file_path = os.path.join(
|
406
|
-
project_dir, 'src', kebab_app_name, 'src', 'main.py'
|
407
|
-
)
|
408
|
-
import_module_path = '.'.join([
|
409
|
-
'module', snake_module_name, 'register_module'
|
410
|
-
])
|
411
|
-
function_name = f'register_{snake_module_name}'
|
412
|
-
task.print_out(f'Read code from: {app_main_file_path}')
|
413
|
-
code = await read_text_file_async(app_main_file_path)
|
414
|
-
task.print_out(
|
415
|
-
f'Add import "{function_name}" from "{import_module_path}" to the code'
|
416
|
-
)
|
417
|
-
code = add_import_module(
|
418
|
-
code=code,
|
419
|
-
module_path=import_module_path,
|
420
|
-
resource=function_name
|
421
|
-
)
|
422
|
-
task.print_out(f'Add "{function_name}" call to the code')
|
423
|
-
code = add_function_call(
|
424
|
-
code=code,
|
425
|
-
function_name=function_name,
|
426
|
-
parameters=[]
|
427
|
-
)
|
428
|
-
task.print_out(f'Write modified code to: {app_main_file_path}')
|
429
|
-
await write_text_file_async(app_main_file_path, code)
|
@@ -0,0 +1,326 @@
|
|
1
|
+
from typeguard import typechecked
|
2
|
+
from typing import Any, List, Mapping
|
3
|
+
from dotenv import dotenv_values
|
4
|
+
from ....task.task import Task
|
5
|
+
from ....helper.codemod.add_import_module import add_import_module
|
6
|
+
from ....helper.codemod.add_function_call import add_function_call
|
7
|
+
from ....helper.codemod.append_code_to_function import append_code_to_function
|
8
|
+
from ....helper.docker_compose.file import add_services
|
9
|
+
from ....helper.file.text import (
|
10
|
+
read_text_file_async, write_text_file_async, append_text_file_async
|
11
|
+
)
|
12
|
+
|
13
|
+
import asyncio
|
14
|
+
import os
|
15
|
+
import jsons
|
16
|
+
|
17
|
+
|
18
|
+
@typechecked
|
19
|
+
async def create_microservice_config(
|
20
|
+
task: Task,
|
21
|
+
project_dir: str,
|
22
|
+
kebab_app_name: str,
|
23
|
+
snake_app_name: str,
|
24
|
+
kebab_module_name: str,
|
25
|
+
snake_module_name: str,
|
26
|
+
upper_snake_module_name: str
|
27
|
+
):
|
28
|
+
modules = await _create_automation_json_config(
|
29
|
+
task, project_dir, snake_app_name, snake_module_name
|
30
|
+
)
|
31
|
+
return await asyncio.gather(
|
32
|
+
asyncio.create_task(_add_docker_compose_service(
|
33
|
+
task, modules, project_dir, kebab_app_name,
|
34
|
+
snake_app_name, kebab_module_name, snake_module_name,
|
35
|
+
upper_snake_module_name
|
36
|
+
)),
|
37
|
+
asyncio.create_task(_append_compose_env(
|
38
|
+
task, modules, project_dir, kebab_app_name, upper_snake_module_name
|
39
|
+
))
|
40
|
+
)
|
41
|
+
|
42
|
+
|
43
|
+
@typechecked
|
44
|
+
async def _add_docker_compose_service(
|
45
|
+
task: Task,
|
46
|
+
modules: List[str],
|
47
|
+
project_dir: str,
|
48
|
+
kebab_app_name: str,
|
49
|
+
snake_app_name: str,
|
50
|
+
kebab_module_name: str,
|
51
|
+
snake_module_name: str,
|
52
|
+
upper_snake_module_name: str
|
53
|
+
):
|
54
|
+
module_app_port = 8080 + len(modules)
|
55
|
+
module_app_port_str = str(module_app_port)
|
56
|
+
docker_compose_file_path = os.path.join(
|
57
|
+
project_dir, 'src', kebab_app_name, 'docker-compose.yml'
|
58
|
+
)
|
59
|
+
app_container_port_env_name = f'APP_{upper_snake_module_name}_MODULE_PORT'
|
60
|
+
app_container_port_env = '${' + app_container_port_env_name + ':-' + module_app_port_str + '}' # noqa
|
61
|
+
app_host_port_env_name = f'APP_{upper_snake_module_name}_HOST_MODULE_PORT'
|
62
|
+
app_host_port_env = '${' + app_host_port_env_name + ':-' + module_app_port_str + '}' # noqa
|
63
|
+
service_definition = _get_new_docker_compose_service_definition(
|
64
|
+
kebab_app_name, snake_app_name, kebab_module_name, snake_module_name,
|
65
|
+
upper_snake_module_name, app_host_port_env, app_container_port_env
|
66
|
+
)
|
67
|
+
task.print_out(f'Add service at: {docker_compose_file_path}')
|
68
|
+
add_services(
|
69
|
+
file_name=docker_compose_file_path,
|
70
|
+
new_services=service_definition,
|
71
|
+
)
|
72
|
+
|
73
|
+
|
74
|
+
@typechecked
|
75
|
+
def _get_new_docker_compose_service_definition(
|
76
|
+
kebab_app_name: str,
|
77
|
+
snake_app_name: str,
|
78
|
+
kebab_module_name: str,
|
79
|
+
snake_module_name: str,
|
80
|
+
upper_snake_module_name: str,
|
81
|
+
app_host_port_env: str,
|
82
|
+
app_container_port_env: str
|
83
|
+
) -> Mapping[str, Any]:
|
84
|
+
return {
|
85
|
+
f'{kebab_app_name}-{kebab_module_name}-service': {
|
86
|
+
'build': {
|
87
|
+
'dockerfile': 'Dockerfile',
|
88
|
+
'context': './src'
|
89
|
+
},
|
90
|
+
'image': '${IMAGE:-' + kebab_app_name + '}',
|
91
|
+
'container_name': '${CONTAINER_PREFIX:-my}-' + f'{kebab_app_name}-{kebab_module_name}-service', # noqa
|
92
|
+
'hostname': f'{kebab_app_name}-{kebab_module_name}-service',
|
93
|
+
'env_file': [
|
94
|
+
'src/template.env',
|
95
|
+
'all-module-disabled.env'
|
96
|
+
],
|
97
|
+
'environment': {
|
98
|
+
'APP_NAME': '${APP_NAME:-' + kebab_app_name + '}-' + f'{kebab_module_name}-service', # noqa
|
99
|
+
'APP_PORT': app_container_port_env,
|
100
|
+
'APP_ENABLE_EVENT_HANDLER': 'true',
|
101
|
+
'APP_ENABLE_RPC_SERVER': 'true',
|
102
|
+
'APP_ENABLE_API': 'false',
|
103
|
+
'APP_ENABLE_FRONTEND': 'false',
|
104
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE': 'true',
|
105
|
+
},
|
106
|
+
'ports': [
|
107
|
+
f'{app_host_port_env}:{app_container_port_env}'
|
108
|
+
],
|
109
|
+
'restart': 'unless-stopped',
|
110
|
+
'profiles': [
|
111
|
+
'microservices'
|
112
|
+
],
|
113
|
+
'healthcheck': {
|
114
|
+
'test': [
|
115
|
+
'CMD-SHELL',
|
116
|
+
'curl --fail http://localhost:' + app_container_port_env + '/readiness || exit 1' # noqa
|
117
|
+
],
|
118
|
+
'interval': '5s',
|
119
|
+
'timeout': '3s',
|
120
|
+
'retries': 10
|
121
|
+
},
|
122
|
+
'networks': ['zrb']
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
@typechecked
|
128
|
+
async def _append_compose_env(
|
129
|
+
task: Task,
|
130
|
+
modules: List[str],
|
131
|
+
project_dir: str,
|
132
|
+
kebab_app_name: str,
|
133
|
+
upper_snake_module_name: str
|
134
|
+
):
|
135
|
+
compose_template_env_path = os.path.join(
|
136
|
+
project_dir, 'src', kebab_app_name, 'docker-compose.env'
|
137
|
+
)
|
138
|
+
compose_env_map = dotenv_values(compose_template_env_path)
|
139
|
+
host_port = int(compose_env_map.get('APP_GATEWAY_HOST_PORT', '8080'))
|
140
|
+
module_app_port = host_port + len(modules)
|
141
|
+
new_env_str = '\n'.join([
|
142
|
+
f'APP_{upper_snake_module_name}_HOST_MODULE_PORT={module_app_port}',
|
143
|
+
f'APP_{upper_snake_module_name}_MODULE_PORT={module_app_port}',
|
144
|
+
])
|
145
|
+
task.print_out(f'Add new environment to: {compose_template_env_path}')
|
146
|
+
await append_text_file_async(compose_template_env_path, new_env_str)
|
147
|
+
|
148
|
+
|
149
|
+
@typechecked
|
150
|
+
async def append_src_template_env(
|
151
|
+
task: Task,
|
152
|
+
project_dir: str,
|
153
|
+
kebab_app_name: str,
|
154
|
+
upper_snake_module_name: str
|
155
|
+
):
|
156
|
+
src_template_env_path = os.path.join(
|
157
|
+
project_dir, 'src', kebab_app_name, 'src', 'template.env'
|
158
|
+
)
|
159
|
+
new_env_str = '\n'.join([
|
160
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true',
|
161
|
+
])
|
162
|
+
task.print_out(f'Add new environment to: {src_template_env_path}')
|
163
|
+
await append_text_file_async(src_template_env_path, new_env_str)
|
164
|
+
|
165
|
+
|
166
|
+
@typechecked
|
167
|
+
async def append_deployment_template_env(
|
168
|
+
task: Task,
|
169
|
+
project_dir: str,
|
170
|
+
kebab_app_name: str,
|
171
|
+
upper_snake_module_name: str
|
172
|
+
):
|
173
|
+
deployment_template_env_path = os.path.join(
|
174
|
+
project_dir, 'src', kebab_app_name, 'deployment', 'template.env'
|
175
|
+
)
|
176
|
+
new_env_str = '\n'.join([
|
177
|
+
f'REPLICA_{upper_snake_module_name}_SERVICE=1',
|
178
|
+
])
|
179
|
+
task.print_out(f'Add new environment to: {deployment_template_env_path}')
|
180
|
+
await append_text_file_async(deployment_template_env_path, new_env_str)
|
181
|
+
|
182
|
+
|
183
|
+
@typechecked
|
184
|
+
async def append_all_enabled_env(
|
185
|
+
task: Task,
|
186
|
+
project_dir: str,
|
187
|
+
kebab_app_name: str,
|
188
|
+
upper_snake_module_name: str
|
189
|
+
):
|
190
|
+
all_enabled_env_path = os.path.join(
|
191
|
+
project_dir, 'src', kebab_app_name, 'all-module-enabled.env'
|
192
|
+
)
|
193
|
+
task.print_out(f'Add new environment to: {all_enabled_env_path}')
|
194
|
+
await append_text_file_async(
|
195
|
+
all_enabled_env_path,
|
196
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true'
|
197
|
+
)
|
198
|
+
|
199
|
+
|
200
|
+
@typechecked
|
201
|
+
async def append_all_disabled_env(
|
202
|
+
task: Task,
|
203
|
+
project_dir: str,
|
204
|
+
kebab_app_name: str,
|
205
|
+
upper_snake_module_name: str
|
206
|
+
):
|
207
|
+
all_disabled_env_path = os.path.join(
|
208
|
+
project_dir, 'src', kebab_app_name, 'all-module-disabled.env'
|
209
|
+
)
|
210
|
+
task.print_out(f'Add new environment to: {all_disabled_env_path}')
|
211
|
+
await append_text_file_async(
|
212
|
+
all_disabled_env_path,
|
213
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE=false'
|
214
|
+
)
|
215
|
+
|
216
|
+
|
217
|
+
@typechecked
|
218
|
+
async def create_app_config(
|
219
|
+
task: Task,
|
220
|
+
project_dir: str,
|
221
|
+
kebab_app_name: str,
|
222
|
+
snake_module_name: str,
|
223
|
+
upper_snake_module_name: str
|
224
|
+
):
|
225
|
+
config_file_path = os.path.join(
|
226
|
+
project_dir, 'src', kebab_app_name, 'src', 'config.py'
|
227
|
+
)
|
228
|
+
config_code = '\n'.join([
|
229
|
+
f'app_enable_{snake_module_name}_module = str_to_boolean(os.environ.get(', # noqa
|
230
|
+
f" 'APP_ENABLE_{upper_snake_module_name}_MODULE', 'true'"
|
231
|
+
'))'
|
232
|
+
])
|
233
|
+
task.print_out(f'Read config from: {config_file_path}')
|
234
|
+
code = await read_text_file_async(config_file_path)
|
235
|
+
code += '\n' + config_code
|
236
|
+
task.print_out(f'Write config to: {config_file_path}')
|
237
|
+
await write_text_file_async(config_file_path, code)
|
238
|
+
|
239
|
+
|
240
|
+
@typechecked
|
241
|
+
async def _create_automation_json_config(
|
242
|
+
task: Task,
|
243
|
+
project_dir: str,
|
244
|
+
snake_app_name: str,
|
245
|
+
snake_module_name: str,
|
246
|
+
):
|
247
|
+
json_modules_file_path = os.path.join(
|
248
|
+
project_dir, '_automate', snake_app_name, 'config', 'modules.json'
|
249
|
+
)
|
250
|
+
task.print_out(f'Read json config from: {json_modules_file_path}')
|
251
|
+
json_str = await read_text_file_async(json_modules_file_path)
|
252
|
+
task.print_out(f'Add "{snake_module_name}" to json config')
|
253
|
+
modules: List[str] = jsons.loads(json_str)
|
254
|
+
modules.append(snake_module_name)
|
255
|
+
json_str = jsons.dumps(modules)
|
256
|
+
task.print_out(f'Write new json config to: {json_modules_file_path}')
|
257
|
+
await write_text_file_async(json_modules_file_path, json_str)
|
258
|
+
return modules
|
259
|
+
|
260
|
+
|
261
|
+
@typechecked
|
262
|
+
async def register_migration(
|
263
|
+
task: Task,
|
264
|
+
project_dir: str,
|
265
|
+
kebab_app_name: str,
|
266
|
+
snake_module_name: str
|
267
|
+
):
|
268
|
+
app_migration_file_path = os.path.join(
|
269
|
+
project_dir, 'src', kebab_app_name, 'src', 'migrate.py'
|
270
|
+
)
|
271
|
+
import_module_path = '.'.join([
|
272
|
+
'module', snake_module_name, 'migrate'
|
273
|
+
])
|
274
|
+
function_name = f'migrate_{snake_module_name}'
|
275
|
+
task.print_out(f'Read code from: {app_migration_file_path}')
|
276
|
+
code = await read_text_file_async(app_migration_file_path)
|
277
|
+
task.print_out(
|
278
|
+
f'Add import "{function_name}" from "{import_module_path}" to the code'
|
279
|
+
)
|
280
|
+
code = add_import_module(
|
281
|
+
code=code,
|
282
|
+
module_path=import_module_path,
|
283
|
+
resource=function_name
|
284
|
+
)
|
285
|
+
task.print_out(f'Add "{function_name}" call to the code')
|
286
|
+
code = append_code_to_function(
|
287
|
+
code=code,
|
288
|
+
function_name='migrate',
|
289
|
+
new_code=f'await {function_name}()'
|
290
|
+
)
|
291
|
+
task.print_out(f'Write modified code to: {app_migration_file_path}')
|
292
|
+
await write_text_file_async(app_migration_file_path, code)
|
293
|
+
|
294
|
+
|
295
|
+
@typechecked
|
296
|
+
async def register_module(
|
297
|
+
task: Task,
|
298
|
+
project_dir: str,
|
299
|
+
kebab_app_name: str,
|
300
|
+
snake_module_name: str
|
301
|
+
):
|
302
|
+
app_main_file_path = os.path.join(
|
303
|
+
project_dir, 'src', kebab_app_name, 'src', 'main.py'
|
304
|
+
)
|
305
|
+
import_module_path = '.'.join([
|
306
|
+
'module', snake_module_name, 'register_module'
|
307
|
+
])
|
308
|
+
function_name = f'register_{snake_module_name}'
|
309
|
+
task.print_out(f'Read code from: {app_main_file_path}')
|
310
|
+
code = await read_text_file_async(app_main_file_path)
|
311
|
+
task.print_out(
|
312
|
+
f'Add import "{function_name}" from "{import_module_path}" to the code'
|
313
|
+
)
|
314
|
+
code = add_import_module(
|
315
|
+
code=code,
|
316
|
+
module_path=import_module_path,
|
317
|
+
resource=function_name
|
318
|
+
)
|
319
|
+
task.print_out(f'Add "{function_name}" call to the code')
|
320
|
+
code = add_function_call(
|
321
|
+
code=code,
|
322
|
+
function_name=function_name,
|
323
|
+
parameters=[]
|
324
|
+
)
|
325
|
+
task.print_out(f'Write modified code to: {app_main_file_path}')
|
326
|
+
await write_text_file_async(app_main_file_path, code)
|