zrb 0.0.46__py3-none-any.whl → 0.0.47__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/action/runner.py +1 -1
- zrb/builtin/generator/_common.py +7 -8
- zrb/builtin/generator/docker_compose_task/template/src/kebab-task-name/docker-compose.yml +7 -1
- zrb/builtin/generator/docker_compose_task/template/src/kebab-task-name/image/Dockerfile +3 -1
- zrb/builtin/generator/docker_compose_task/template/src/kebab-task-name/image/main.py +0 -5
- zrb/builtin/generator/fastapp/add.py +3 -3
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/_common.py +11 -7
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/config/docker-compose.env +3 -0
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/container.py +4 -2
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/image.py +1 -1
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/local.py +1 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/docker-compose.yml +19 -6
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/template.env +1 -1
- zrb/builtin/generator/fastapp_module/add.py +259 -106
- zrb/builtin/generator/project_task/add.py +5 -6
- zrb/builtin/generator/project_task/task_factory.py +4 -6
- zrb/builtin/generator/simple_python_app/add.py +3 -3
- zrb/builtin/generator/simple_python_app/template/src/kebab-app-name/docker-compose.yml +7 -1
- zrb/builtin/generator/simple_python_app/template/src/kebab-app-name/src/Dockerfile +3 -1
- zrb/builtin/generator/simple_python_app/template/src/kebab-app-name/src/main.py +0 -5
- zrb/builtin/md5.py +3 -2
- zrb/builtin/project.py +2 -60
- zrb/helper/docker_compose/file.py +22 -0
- zrb/helper/env_map/__init__.py +0 -0
- zrb/helper/env_map/fetch.py +68 -0
- zrb/helper/file/copy_tree.py +6 -7
- zrb/helper/file/text.py +12 -4
- zrb/task/base_task.py +10 -10
- zrb/task/docker_compose_task.py +2 -2
- zrb/task/installer/factory.py +6 -5
- zrb/task/path_checker.py +2 -2
- zrb/task/resource_maker.py +1 -1
- zrb/task_env/env.py +4 -3
- {zrb-0.0.46.dist-info → zrb-0.0.47.dist-info}/METADATA +1 -1
- {zrb-0.0.46.dist-info → zrb-0.0.47.dist-info}/RECORD +41 -38
- zrb/helper/dockercompose/read.py +0 -9
- /zrb/builtin/generator/fastapp/template/src/kebab-app-name/{src/module_disabled.env → all-module-disabled.env} +0 -0
- /zrb/builtin/generator/fastapp/template/src/kebab-app-name/{src/module_enabled.env → all-module-enabled.env} +0 -0
- /zrb/helper/{dockercompose → docker_compose}/fetch_external_env.py +0 -0
- {zrb-0.0.46.dist-info → zrb-0.0.47.dist-info}/LICENSE +0 -0
- {zrb-0.0.46.dist-info → zrb-0.0.47.dist-info}/WHEEL +0 -0
- {zrb-0.0.46.dist-info → zrb-0.0.47.dist-info}/entry_points.txt +0 -0
@@ -13,12 +13,15 @@ from .._common import (
|
|
13
13
|
from ....helper import util
|
14
14
|
from ....helper.codemod.add_import_module import add_import_module
|
15
15
|
from ....helper.codemod.add_function_call import add_function_call
|
16
|
-
from ....helper.file
|
16
|
+
from ....helper.docker_compose.file import add_services
|
17
|
+
from ....helper.file.text import (
|
18
|
+
read_text_file_async, write_text_file_async, append_text_file_async
|
19
|
+
)
|
17
20
|
|
21
|
+
import asyncio
|
18
22
|
import os
|
19
23
|
import jsons
|
20
24
|
|
21
|
-
|
22
25
|
current_dir = os.path.dirname(__file__)
|
23
26
|
|
24
27
|
|
@@ -68,148 +71,298 @@ copy_resource = ResourceMaker(
|
|
68
71
|
|
69
72
|
|
70
73
|
@python_task(
|
71
|
-
name='
|
72
|
-
|
73
|
-
upstreams=[copy_resource]
|
74
|
+
name='fastapp-module',
|
75
|
+
group=project_add_group,
|
76
|
+
upstreams=[copy_resource],
|
77
|
+
runner=runner
|
74
78
|
)
|
75
|
-
async def
|
79
|
+
async def add_fastapp_module(*args: Any, **kwargs: Any):
|
76
80
|
task: Task = kwargs.get('_task')
|
77
81
|
project_dir = kwargs.get('project_dir', '.')
|
78
82
|
app_name = kwargs.get('app_name')
|
79
83
|
module_name = kwargs.get('module_name')
|
80
84
|
kebab_app_name = util.to_kebab_case(app_name)
|
85
|
+
snake_app_name = util.to_snake_case(app_name)
|
86
|
+
kebab_module_name = util.to_kebab_case(module_name)
|
81
87
|
snake_module_name = util.to_snake_case(module_name)
|
82
|
-
|
83
|
-
|
88
|
+
upper_snake_module_name = snake_module_name.upper()
|
89
|
+
app_main_file = get_app_main_file(project_dir, kebab_app_name)
|
90
|
+
app_config_file = get_app_config_file(project_dir, kebab_app_name)
|
91
|
+
json_modules_file = get_json_modules_file(project_dir, snake_app_name)
|
92
|
+
enabled_env_file = get_all_enabled_env_file(project_dir, kebab_app_name)
|
93
|
+
disabled_env_file = get_all_disabled_env_file(project_dir, kebab_app_name)
|
94
|
+
docker_compose_file = get_docker_compose_file(project_dir, kebab_app_name)
|
95
|
+
results = await asyncio.gather(*[
|
96
|
+
asyncio.create_task(create_automation_json_config(
|
97
|
+
task, json_modules_file, snake_module_name
|
98
|
+
)),
|
99
|
+
asyncio.create_task(register_module(
|
100
|
+
task, app_main_file, snake_module_name
|
101
|
+
)),
|
102
|
+
asyncio.create_task(create_app_config(
|
103
|
+
task, app_config_file, snake_module_name, upper_snake_module_name
|
104
|
+
)),
|
105
|
+
asyncio.create_task(append_all_enabled_env(
|
106
|
+
task, enabled_env_file, upper_snake_module_name
|
107
|
+
)),
|
108
|
+
asyncio.create_task(append_all_disabled_env(
|
109
|
+
task, disabled_env_file, upper_snake_module_name
|
110
|
+
)),
|
84
111
|
])
|
85
|
-
|
86
|
-
|
87
|
-
|
112
|
+
modules = results[0] # return value of `create_automation_json_config`
|
113
|
+
module_port = 8080 + len(modules)
|
114
|
+
src_template_env_path = get_src_template_env_file(
|
115
|
+
project_dir, kebab_app_name
|
88
116
|
)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
117
|
+
src_template_env_map = dotenv_values(src_template_env_path)
|
118
|
+
app_port = int(src_template_env_map.get('APP_PORT', '8080'))
|
119
|
+
module_app_port = app_port + len(modules)
|
120
|
+
compose_env_path = get_compose_env_file(
|
121
|
+
project_dir, snake_app_name
|
93
122
|
)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
123
|
+
compose_env_map = dotenv_values(compose_env_path)
|
124
|
+
host_port = int(compose_env_map.get('APP_GATEWAY_HOST_PORT', '8080'))
|
125
|
+
module_host_port = host_port + len(modules)
|
126
|
+
await asyncio.gather(*[
|
127
|
+
asyncio.create_task(add_docker_compose_service(
|
128
|
+
task, module_port, docker_compose_file, kebab_app_name,
|
129
|
+
snake_app_name, kebab_module_name, snake_module_name,
|
130
|
+
upper_snake_module_name
|
131
|
+
)),
|
132
|
+
asyncio.create_task(append_src_template_env(
|
133
|
+
task, module_app_port, src_template_env_path,
|
134
|
+
upper_snake_module_name
|
135
|
+
)),
|
136
|
+
asyncio.create_task(append_compose_env(
|
137
|
+
task, module_host_port, compose_env_path,
|
138
|
+
upper_snake_module_name
|
139
|
+
))
|
140
|
+
])
|
141
|
+
# TODO: create runner for local microservices
|
142
|
+
# TODO: create deployment for local microservices
|
143
|
+
task.print_out('Success')
|
144
|
+
|
145
|
+
|
146
|
+
async def add_docker_compose_service(
|
147
|
+
task: Task,
|
148
|
+
module_app_port: int,
|
149
|
+
docker_compose_file_path: str,
|
150
|
+
kebab_app_name: str,
|
151
|
+
snake_app_name: str,
|
152
|
+
kebab_module_name: str,
|
153
|
+
snake_module_name: str,
|
154
|
+
upper_snake_module_name: str
|
155
|
+
):
|
156
|
+
module_app_port_str = str(module_app_port)
|
157
|
+
app_container_port_env_name = f'APP_{upper_snake_module_name}_MODULE_PORT'
|
158
|
+
app_container_port_env = '${' + app_container_port_env_name + ':-' + module_app_port_str + '}' # noqa
|
159
|
+
app_host_port_env_name = f'APP_{upper_snake_module_name}_HOST_MODULE_PORT'
|
160
|
+
app_host_port_env = '${' + app_host_port_env_name + ':-' + module_app_port_str + '}' # noqa
|
161
|
+
task.print_out(f'Add service at: {docker_compose_file_path}')
|
162
|
+
add_services(
|
163
|
+
file_name=docker_compose_file_path,
|
164
|
+
new_services={
|
165
|
+
f'{kebab_app_name}-{kebab_module_name}-module': {
|
166
|
+
'build': {
|
167
|
+
'dockerfile': 'Dockerfile',
|
168
|
+
'context': './src'
|
169
|
+
},
|
170
|
+
'image': '${IMAGE:-' + kebab_app_name + '}',
|
171
|
+
'container_name': f'{snake_app_name}_{snake_module_name}',
|
172
|
+
'hostname': f'snake_app_name_{snake_module_name}',
|
173
|
+
'env_file': [
|
174
|
+
'src/template.env',
|
175
|
+
'all-module-disabled.env'
|
176
|
+
],
|
177
|
+
'environment': {
|
178
|
+
'APP_NAME': '${APP_NAME:-' + kebab_app_name + '}-' + f'{kebab_module_name}-module', # noqa
|
179
|
+
'APP_PORT': app_container_port_env, # noqa
|
180
|
+
'APP_RMQ_CONNECTION': '${APP_CONTAINER_RMQ_CONNECTION:-amqp://guest:guest@rabbitmq/}', # noqa
|
181
|
+
'APP_KAFKA_BOOTSTRAP_SERVERS': '${APP_CONTAINER_KAFKA_BOOTSTRAP_SERVERS:-redpanda:9092}', # noqa
|
182
|
+
'APP_ENABLE_MESSAGE_CONSUMER': 'true',
|
183
|
+
'APP_ENABLE_RPC_SERVER': 'true',
|
184
|
+
'APP_ENABLE_API': 'false',
|
185
|
+
'APP_ENABLE_FRONTEND': 'false',
|
186
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE': 'true',
|
187
|
+
},
|
188
|
+
'ports': [
|
189
|
+
f'{app_host_port_env}:{app_container_port_env}'
|
190
|
+
],
|
191
|
+
'restart': 'on-failure',
|
192
|
+
'profiles': [
|
193
|
+
'microservices'
|
194
|
+
],
|
195
|
+
'healthcheck': {
|
196
|
+
'test': [
|
197
|
+
"CMD-SHELL",
|
198
|
+
"curl --fail http://localhost:${APP_PORT:-8080}/ || exit 1" # noqa
|
199
|
+
],
|
200
|
+
'interval': '5s',
|
201
|
+
'timeout': '1s',
|
202
|
+
'retries': 30
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
98
206
|
)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
207
|
+
|
208
|
+
|
209
|
+
async def append_compose_env(
|
210
|
+
task: Task,
|
211
|
+
module_app_port: int,
|
212
|
+
compose_template_env_path: str,
|
213
|
+
upper_snake_module_name: str
|
214
|
+
):
|
215
|
+
new_env_str = '\n'.join([
|
216
|
+
f'APP_{upper_snake_module_name}_HOST_MODULE_PORT={module_app_port}',
|
217
|
+
f'APP_{upper_snake_module_name}_MODULE_PORT={module_app_port}',
|
218
|
+
])
|
219
|
+
task.print_out(f'Add new environment to: {compose_template_env_path}')
|
220
|
+
await append_text_file_async(compose_template_env_path, new_env_str)
|
221
|
+
|
222
|
+
|
223
|
+
async def append_src_template_env(
|
224
|
+
task: Task,
|
225
|
+
module_app_port: int,
|
226
|
+
src_template_env_path: str,
|
227
|
+
upper_snake_module_name: str
|
228
|
+
):
|
229
|
+
new_env_str = '\n'.join([
|
230
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true',
|
231
|
+
])
|
232
|
+
task.print_out(f'Add new environment to: {src_template_env_path}')
|
233
|
+
await append_text_file_async(src_template_env_path, new_env_str)
|
234
|
+
|
235
|
+
|
236
|
+
async def append_all_enabled_env(
|
237
|
+
task: Task,
|
238
|
+
all_enabled_env_path: str,
|
239
|
+
upper_snake_module_name: str
|
240
|
+
):
|
241
|
+
task.print_out(f'Add new environment to: {all_enabled_env_path}')
|
242
|
+
await append_text_file_async(
|
243
|
+
all_enabled_env_path,
|
244
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true'
|
104
245
|
)
|
105
|
-
task.print_out(f'Write modified code to: {main_file_path}')
|
106
|
-
await write_text_file(main_file_path, code)
|
107
246
|
|
108
247
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
)
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
module_name = kwargs.get('module_name')
|
119
|
-
kebab_app_name = util.to_kebab_case(app_name)
|
120
|
-
snake_module_name = util.to_snake_case(module_name)
|
121
|
-
upper_snake_module_name = snake_module_name.upper()
|
122
|
-
config_file_path = os.path.join(
|
123
|
-
project_dir, 'src', kebab_app_name, 'src', 'config.py'
|
248
|
+
async def append_all_disabled_env(
|
249
|
+
task: Task,
|
250
|
+
all_disabled_env_path: str,
|
251
|
+
upper_snake_module_name: str
|
252
|
+
):
|
253
|
+
task.print_out(f'Add new environment to: {all_disabled_env_path}')
|
254
|
+
await append_text_file_async(
|
255
|
+
all_disabled_env_path,
|
256
|
+
f'APP_ENABLE_{upper_snake_module_name}_MODULE=false'
|
124
257
|
)
|
258
|
+
|
259
|
+
|
260
|
+
async def create_app_config(
|
261
|
+
task: Task,
|
262
|
+
config_file_path: str,
|
263
|
+
snake_module_name: str,
|
264
|
+
upper_snake_module_name: str
|
265
|
+
):
|
125
266
|
config_code = '\n'.join([
|
126
267
|
f'app_enable_{snake_module_name}_module = str_to_boolean(os.environ.get(', # noqa
|
127
268
|
f" 'APP_{upper_snake_module_name}', 'true'"
|
128
269
|
'))'
|
129
270
|
])
|
130
271
|
task.print_out(f'Read config from: {config_file_path}')
|
131
|
-
code = await
|
272
|
+
code = await read_text_file_async(config_file_path)
|
132
273
|
code += '\n' + config_code
|
133
274
|
task.print_out(f'Write config to: {config_file_path}')
|
134
|
-
await
|
275
|
+
await write_text_file_async(config_file_path, code)
|
135
276
|
|
136
277
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
)
|
142
|
-
async def create_automation_config(*args: Any, **kwargs: Any):
|
143
|
-
task: Task = kwargs.get('_task')
|
144
|
-
project_dir = kwargs.get('project_dir', '.')
|
145
|
-
app_name = kwargs.get('app_name')
|
146
|
-
module_name = kwargs.get('module_name')
|
147
|
-
snake_app_name = util.to_snake_case(app_name)
|
148
|
-
snake_module_name = util.to_snake_case(module_name)
|
149
|
-
json_modules_file_path = os.path.join(
|
150
|
-
project_dir, '_automate', snake_app_name, 'config', 'modules.json'
|
151
|
-
)
|
278
|
+
async def create_automation_json_config(
|
279
|
+
task: Task,
|
280
|
+
json_modules_file_path: str,
|
281
|
+
snake_module_name: str,
|
282
|
+
):
|
152
283
|
task.print_out(f'Read json config from: {json_modules_file_path}')
|
153
|
-
json_str = await
|
284
|
+
json_str = await read_text_file_async(json_modules_file_path)
|
154
285
|
task.print_out(f'Add "{snake_module_name}" to json config')
|
155
286
|
modules: List[str] = jsons.loads(json_str)
|
156
287
|
modules.append(snake_module_name)
|
157
288
|
json_str = jsons.dumps(modules)
|
158
289
|
task.print_out(f'Write new json config to: {json_modules_file_path}')
|
159
|
-
await
|
290
|
+
await write_text_file_async(json_modules_file_path, json_str)
|
291
|
+
return modules
|
160
292
|
|
161
293
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
)
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
294
|
+
async def register_module(
|
295
|
+
task: Task,
|
296
|
+
app_main_file_path: str,
|
297
|
+
snake_module_name: str
|
298
|
+
):
|
299
|
+
import_module_path = '.'.join(['module', snake_module_name])
|
300
|
+
function_name = f'register_{snake_module_name}'
|
301
|
+
task.print_out(f'Read code from: {app_main_file_path}')
|
302
|
+
code = await read_text_file_async(app_main_file_path)
|
303
|
+
task.print_out(
|
304
|
+
f'Add import "{function_name}" from "{import_module_path}" to the code'
|
305
|
+
)
|
306
|
+
code = add_import_module(
|
307
|
+
code=code,
|
308
|
+
module_path=import_module_path,
|
309
|
+
resource=function_name
|
310
|
+
)
|
311
|
+
task.print_out(f'Add "{function_name}" call to the code')
|
312
|
+
code = add_function_call(
|
313
|
+
code=code,
|
314
|
+
function_name=function_name,
|
315
|
+
parameters=[]
|
316
|
+
)
|
317
|
+
task.print_out(f'Write modified code to: {app_main_file_path}')
|
318
|
+
await write_text_file_async(app_main_file_path, code)
|
319
|
+
|
320
|
+
|
321
|
+
def get_docker_compose_file(project_dir: str, kebab_app_name: str):
|
322
|
+
return os.path.join(
|
323
|
+
project_dir, 'src', kebab_app_name, 'docker-compose.yml'
|
324
|
+
)
|
325
|
+
|
326
|
+
|
327
|
+
def get_app_main_file(project_dir: str, kebab_app_name: str):
|
328
|
+
return os.path.join(
|
329
|
+
project_dir, 'src', kebab_app_name, 'src', 'main.py'
|
330
|
+
)
|
331
|
+
|
332
|
+
|
333
|
+
def get_app_config_file(project_dir: str, kebab_app_name: str):
|
334
|
+
return os.path.join(
|
335
|
+
project_dir, 'src', kebab_app_name, 'src', 'config.py'
|
336
|
+
)
|
337
|
+
|
338
|
+
|
339
|
+
def get_json_modules_file(project_dir: str, snake_app_name: str):
|
340
|
+
return os.path.join(
|
177
341
|
project_dir, '_automate', snake_app_name, 'config', 'modules.json'
|
178
342
|
)
|
179
|
-
|
343
|
+
|
344
|
+
|
345
|
+
def get_compose_env_file(project_dir: str, snake_app_name: str):
|
346
|
+
return os.path.join(
|
347
|
+
project_dir, '_automate', snake_app_name, 'config',
|
348
|
+
'docker-compose.env'
|
349
|
+
)
|
350
|
+
|
351
|
+
|
352
|
+
def get_src_template_env_file(project_dir: str, kebab_app_name: str):
|
353
|
+
return os.path.join(
|
180
354
|
project_dir, 'src', kebab_app_name, 'src', 'template.env'
|
181
355
|
)
|
182
|
-
template_env_map = dotenv_values(template_env_path)
|
183
|
-
app_port = int(template_env_map.get('APP_PORT', '8080'))
|
184
|
-
task.print_out(f'Read json config from: {json_modules_file_path}')
|
185
|
-
json_str = await read_text_file(json_modules_file_path)
|
186
|
-
modules: List[str] = jsons.loads(json_str)
|
187
|
-
module_app_port = app_port + len(modules)
|
188
|
-
template_env_str = await read_text_file(template_env_path)
|
189
|
-
template_env_str += '\n' + '\n'.join([
|
190
|
-
f'APP_ENABLE_{upper_snake_module_name}_MODULE=true',
|
191
|
-
f'APP_{upper_snake_module_name}_MODULE_PORT={module_app_port}',
|
192
|
-
])
|
193
|
-
await write_text_file(template_env_path, template_env_str)
|
194
356
|
|
195
357
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
358
|
+
def get_all_enabled_env_file(project_dir: str, kebab_app_name: str):
|
359
|
+
return os.path.join(
|
360
|
+
project_dir, 'src', kebab_app_name, 'all-module-enabled.env'
|
361
|
+
)
|
200
362
|
|
201
363
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
create_app_config,
|
208
|
-
create_automation_config,
|
209
|
-
append_template_env,
|
210
|
-
],
|
211
|
-
runner=runner
|
212
|
-
)
|
213
|
-
async def add_fastapp_module(*args: Any, **kwargs: Any):
|
214
|
-
task: Task = kwargs.get('_task')
|
215
|
-
task.print_out('Success')
|
364
|
+
def get_all_disabled_env_file(project_dir: str, kebab_app_name: str):
|
365
|
+
return os.path.join(
|
366
|
+
project_dir, 'src', kebab_app_name, 'all-module-disabled.env'
|
367
|
+
)
|
368
|
+
|
@@ -1,23 +1,23 @@
|
|
1
1
|
from ....helper.file.copy_tree import copy_tree
|
2
2
|
from ....helper.codemod.add_assert_resource import add_assert_resource
|
3
3
|
from ....helper.codemod.add_import_module import add_import_module
|
4
|
+
from ....helper.file.text import read_text_file_async, write_text_file_async
|
4
5
|
|
5
6
|
import os
|
6
7
|
|
7
8
|
current_dir = os.path.dirname(__file__)
|
8
9
|
|
9
10
|
|
10
|
-
def add_project_automation(project_dir: str):
|
11
|
+
async def add_project_automation(project_dir: str):
|
11
12
|
if os.path.exists(os.path.join(project_dir, '_automate', '_project')):
|
12
13
|
return
|
13
|
-
copy_tree(
|
14
|
+
await copy_tree(
|
14
15
|
src=os.path.join(current_dir, 'template'),
|
15
16
|
dst=project_dir
|
16
17
|
)
|
17
18
|
project_task_module_path = '_automate._project'
|
18
19
|
zrb_init_path = os.path.join(project_dir, 'zrb_init.py')
|
19
|
-
|
20
|
-
code = f.read()
|
20
|
+
code = await read_text_file_async(zrb_init_path)
|
21
21
|
import_alias = project_task_module_path.split('.')[-1]
|
22
22
|
code = add_import_module(
|
23
23
|
code=code,
|
@@ -25,5 +25,4 @@ def add_project_automation(project_dir: str):
|
|
25
25
|
alias=import_alias
|
26
26
|
)
|
27
27
|
code = add_assert_resource(code, import_alias)
|
28
|
-
|
29
|
-
f.write(code)
|
28
|
+
await write_text_file_async(zrb_init_path, code)
|
@@ -5,6 +5,7 @@ from ....task.task import Task
|
|
5
5
|
from ....helper import util
|
6
6
|
from ....helper.codemod.add_import_module import add_import_module
|
7
7
|
from ....helper.codemod.add_upstream_to_task import add_upstream_to_task
|
8
|
+
from ....helper.file.text import read_text_file_async, write_text_file_async
|
8
9
|
from .add import add_project_automation
|
9
10
|
from .task_factory_helper import (
|
10
11
|
_get_app_local_task_file, _get_app_container_task_file,
|
@@ -29,7 +30,7 @@ def create_add_project_automation(
|
|
29
30
|
task: Task = kwargs.get('_task')
|
30
31
|
project_dir = kwargs.get('project_dir', '.')
|
31
32
|
task.print_out('Create project automation modules if not exist')
|
32
|
-
add_project_automation(project_dir)
|
33
|
+
await add_project_automation(project_dir)
|
33
34
|
return _task
|
34
35
|
|
35
36
|
|
@@ -184,8 +185,7 @@ def _create_register_app_task(
|
|
184
185
|
# turn into module path
|
185
186
|
upstream_module_path = '.'.join(upstream_module_parts)
|
186
187
|
task.print_out(f'Add {upstream_task_var} to project automation')
|
187
|
-
|
188
|
-
code = f.read()
|
188
|
+
code = await read_text_file_async(project_automation_path)
|
189
189
|
code = add_import_module(
|
190
190
|
code=code,
|
191
191
|
module_path=upstream_module_path,
|
@@ -194,7 +194,5 @@ def _create_register_app_task(
|
|
194
194
|
code = add_upstream_to_task(
|
195
195
|
code, project_automation_task_name, upstream_task_var
|
196
196
|
)
|
197
|
-
|
198
|
-
f.write(code)
|
199
|
-
|
197
|
+
await write_text_file_async(project_automation_path, code)
|
200
198
|
return _task
|
@@ -66,15 +66,15 @@ register_local_app_module = create_register_local_app_module(
|
|
66
66
|
)
|
67
67
|
|
68
68
|
register_container_app_module = create_register_container_app_module(
|
69
|
-
upstreams=[
|
69
|
+
upstreams=[register_local_app_module]
|
70
70
|
)
|
71
71
|
|
72
72
|
register_image_app_module = create_register_image_app_module(
|
73
|
-
upstreams=[
|
73
|
+
upstreams=[register_container_app_module]
|
74
74
|
)
|
75
75
|
|
76
76
|
register_deployment_app_module = create_register_deployment_app_module(
|
77
|
-
upstreams=[
|
77
|
+
upstreams=[register_image_app_module]
|
78
78
|
)
|
79
79
|
|
80
80
|
add_project_task = create_add_project_automation(
|
@@ -9,4 +9,10 @@ services:
|
|
9
9
|
environment:
|
10
10
|
APP_PORT: ${APP_PORT:-8080}
|
11
11
|
ports:
|
12
|
-
- "${HOST_PORT:-8080}:${APP_PORT:-8080}"
|
12
|
+
- "${HOST_PORT:-8080}:${APP_PORT:-8080}"
|
13
|
+
restart: on-failure
|
14
|
+
healthcheck:
|
15
|
+
test: ["CMD-SHELL", "curl --fail http://localhost:${APP_PORT:-8080}/ || exit 1"]
|
16
|
+
interval: 5s
|
17
|
+
timeout: 1s
|
18
|
+
retries: 30
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import uvicorn
|
2
1
|
import os
|
3
2
|
|
4
3
|
MESSAGE = os.getenv('APP_MESSAGE', 'Hello, world!')
|
@@ -19,7 +18,3 @@ async def app(scope, receive, send):
|
|
19
18
|
'type': 'http.response.body',
|
20
19
|
'body': bytes(MESSAGE, 'utf-8'),
|
21
20
|
})
|
22
|
-
|
23
|
-
|
24
|
-
if __name__ == "__main__":
|
25
|
-
uvicorn.run("main:app", host='0.0.0.0', port=PORT, log_level="info")
|
zrb/builtin/md5.py
CHANGED
@@ -4,6 +4,7 @@ from ..task.decorator import python_task
|
|
4
4
|
from ..task_input.str_input import StrInput
|
5
5
|
from ..runner import runner
|
6
6
|
|
7
|
+
import aiofiles
|
7
8
|
import hashlib
|
8
9
|
|
9
10
|
# Common definitions
|
@@ -47,7 +48,7 @@ async def hash_text(*args: str, **kwargs: Any):
|
|
47
48
|
)
|
48
49
|
async def sum_file(*args: str, **kwargs: Any):
|
49
50
|
file_path: str = kwargs.get('file', '')
|
50
|
-
with open(file_path,
|
51
|
-
contents =
|
51
|
+
async with aiofiles.open(file_path, mode='rb') as file:
|
52
|
+
contents = await file.read()
|
52
53
|
hashed_text = hashlib.md5(contents).hexdigest()
|
53
54
|
return hashed_text
|
zrb/builtin/project.py
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
from typing import Any,
|
1
|
+
from typing import Any, Mapping
|
2
2
|
from ._group import project_group
|
3
3
|
from ..task.decorator import python_task
|
4
|
-
from ..task.base_task import Group, BaseTask
|
5
|
-
from ..task_env.env import Env
|
6
4
|
from ..task_input.bool_input import BoolInput
|
7
5
|
from ..runner import runner
|
8
|
-
from ..helper.
|
6
|
+
from ..helper.env_map.fetch import fetch_env_map_from_group
|
9
7
|
|
10
8
|
|
11
9
|
@python_task(
|
@@ -32,59 +30,3 @@ async def get_default_env(*args: Any, **kwargs: Any) -> str:
|
|
32
30
|
return '\n'.join([
|
33
31
|
f'{export_prefix}{key}={env_map[key]}' for key in env_keys
|
34
32
|
])
|
35
|
-
|
36
|
-
|
37
|
-
def fetch_env_map_from_group(
|
38
|
-
env_map: Mapping[str, str], group: Group
|
39
|
-
) -> Mapping[str, str]:
|
40
|
-
for task in group.tasks:
|
41
|
-
env_map = fetch_env_map_from_task(env_map, task)
|
42
|
-
for sub_group in group.children:
|
43
|
-
sub_env_map: Mapping[str, str] = fetch_env_map_from_group(
|
44
|
-
env_map, sub_group
|
45
|
-
)
|
46
|
-
env_map = cascade_env_map(env_map, sub_env_map)
|
47
|
-
return env_map
|
48
|
-
|
49
|
-
|
50
|
-
def fetch_env_map_from_task(
|
51
|
-
env_map: Mapping[str, str], task: BaseTask
|
52
|
-
):
|
53
|
-
task_env_map: Mapping[str, str] = {}
|
54
|
-
for env_file in task.env_files:
|
55
|
-
envs = env_file.get_envs()
|
56
|
-
task_env_map = add_envs_to_env_map(task_env_map, envs)
|
57
|
-
task_env_map = add_envs_to_env_map(task_env_map, task.envs)
|
58
|
-
env_map = cascade_env_map(env_map, task_env_map)
|
59
|
-
for upstream in task.upstreams:
|
60
|
-
task_env_map = fetch_env_map_from_task(env_map, upstream)
|
61
|
-
for checker in task.checkers:
|
62
|
-
task_env_map = fetch_env_map_from_task(env_map, checker)
|
63
|
-
return env_map
|
64
|
-
|
65
|
-
|
66
|
-
def add_envs_to_env_map(
|
67
|
-
env_map: Mapping[str, str], envs: List[Env]
|
68
|
-
) -> Mapping[str, str]:
|
69
|
-
for env in envs:
|
70
|
-
if (
|
71
|
-
env.os_name == '' or
|
72
|
-
env.default == '' or
|
73
|
-
is_probably_jinja(env.default)
|
74
|
-
):
|
75
|
-
if env.name.startswith('FASTAPP'):
|
76
|
-
print(env)
|
77
|
-
continue
|
78
|
-
env_map[env.os_name] = env.default
|
79
|
-
return env_map
|
80
|
-
|
81
|
-
|
82
|
-
def cascade_env_map(
|
83
|
-
env_map: Mapping[str, str],
|
84
|
-
other_env_map: Mapping[str, str]
|
85
|
-
) -> Mapping[str, str]:
|
86
|
-
for key, value in other_env_map.items():
|
87
|
-
if key in env_map:
|
88
|
-
continue
|
89
|
-
env_map[key] = value
|
90
|
-
return env_map
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from typing import Any, Mapping
|
2
|
+
from ruamel.yaml import YAML, composer, CommentedMap
|
3
|
+
|
4
|
+
|
5
|
+
def read_compose_file(file_name: str) -> Any:
|
6
|
+
yaml = YAML()
|
7
|
+
with open(file_name, 'r') as file:
|
8
|
+
data = yaml.load(file)
|
9
|
+
return data
|
10
|
+
|
11
|
+
|
12
|
+
def add_services(file_name: str, new_services: Mapping[str, str]):
|
13
|
+
yaml = YAML()
|
14
|
+
with open(file_name, 'r') as f:
|
15
|
+
data = yaml.load(f)
|
16
|
+
# data = round_trip_load(f, preserve_quotes=True)
|
17
|
+
data = CommentedMap(data)
|
18
|
+
data['services'].update(CommentedMap(new_services))
|
19
|
+
# Write the modified data structure back to the file
|
20
|
+
with open(file_name, 'w') as f:
|
21
|
+
yaml.dump(data, f)
|
22
|
+
# round_trip_dump(data, f)
|
File without changes
|