zrb 0.0.45__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/__init__.py +1 -1
- zrb/action/runner.py +2 -3
- zrb/builtin/__init__.py +2 -0
- zrb/builtin/_group.py +1 -1
- zrb/builtin/env.py +0 -2
- zrb/builtin/generator/_common.py +15 -16
- 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 +17 -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 +14 -5
- 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 +24 -6
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/Dockerfile +3 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/template.env +1 -1
- zrb/builtin/generator/fastapp_module/add.py +266 -83
- zrb/builtin/generator/project/template/README.md +19 -3
- zrb/builtin/generator/project_task/add.py +12 -13
- zrb/builtin/generator/project_task/task_factory.py +12 -14
- 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 +5 -4
- zrb/builtin/project.py +32 -0
- zrb/helper/docker_compose/file.py +22 -0
- zrb/helper/env_map/fetch.py +68 -0
- zrb/helper/file/copy_tree.py +6 -7
- zrb/helper/file/text.py +20 -0
- zrb/helper/string/jinja.py +11 -0
- zrb/task/base_task.py +457 -4
- zrb/task/cmd_task.py +1 -2
- zrb/task/decorator.py +1 -1
- zrb/task/docker_compose_task.py +3 -4
- zrb/task/http_checker.py +1 -2
- zrb/task/installer/factory.py +6 -4
- zrb/task/path_checker.py +3 -4
- zrb/task/port_checker.py +1 -2
- zrb/task/resource_maker.py +2 -3
- zrb/task_env/env.py +4 -3
- {zrb-0.0.45.dist-info → zrb-0.0.47.dist-info}/METADATA +3 -1
- {zrb-0.0.45.dist-info → zrb-0.0.47.dist-info}/RECORD +52 -51
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module_disabled.env +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module_enabled.env +0 -0
- zrb/helper/dockercompose/read.py +0 -9
- zrb/task/base_model.py +0 -456
- zrb/task_group/group.py +0 -36
- /zrb/builtin/generator/fastapp/template/{_automate/snake_app_name/config/module_disabled.env → src/kebab-app-name/all-module-disabled.env} +0 -0
- /zrb/builtin/generator/fastapp/template/{_automate/snake_app_name/config/module_enabled.env → src/kebab-app-name/all-module-enabled.env} +0 -0
- /zrb/helper/{dockercompose → docker_compose}/fetch_external_env.py +0 -0
- /zrb/{task_group → helper/env_map}/__init__.py +0 -0
- {zrb-0.0.45.dist-info → zrb-0.0.47.dist-info}/LICENSE +0 -0
- {zrb-0.0.45.dist-info → zrb-0.0.47.dist-info}/WHEEL +0 -0
- {zrb-0.0.45.dist-info → zrb-0.0.47.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
from typing import Any, List
|
2
|
+
from dotenv import dotenv_values
|
2
3
|
from ..._group import project_add_group
|
3
4
|
from ....task.task import Task
|
4
5
|
from ....task.decorator import python_task
|
@@ -12,11 +13,15 @@ from .._common import (
|
|
12
13
|
from ....helper import util
|
13
14
|
from ....helper.codemod.add_import_module import add_import_module
|
14
15
|
from ....helper.codemod.add_function_call import add_function_call
|
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
|
+
)
|
15
20
|
|
21
|
+
import asyncio
|
16
22
|
import os
|
17
23
|
import jsons
|
18
24
|
|
19
|
-
|
20
25
|
current_dir = os.path.dirname(__file__)
|
21
26
|
|
22
27
|
|
@@ -66,120 +71,298 @@ copy_resource = ResourceMaker(
|
|
66
71
|
|
67
72
|
|
68
73
|
@python_task(
|
69
|
-
name='
|
70
|
-
|
71
|
-
upstreams=[copy_resource]
|
74
|
+
name='fastapp-module',
|
75
|
+
group=project_add_group,
|
76
|
+
upstreams=[copy_resource],
|
77
|
+
runner=runner
|
72
78
|
)
|
73
|
-
def
|
79
|
+
async def add_fastapp_module(*args: Any, **kwargs: Any):
|
74
80
|
task: Task = kwargs.get('_task')
|
75
81
|
project_dir = kwargs.get('project_dir', '.')
|
76
82
|
app_name = kwargs.get('app_name')
|
77
83
|
module_name = kwargs.get('module_name')
|
78
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)
|
79
87
|
snake_module_name = util.to_snake_case(module_name)
|
80
|
-
|
81
|
-
|
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
|
+
)),
|
82
111
|
])
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
86
116
|
)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
92
122
|
)
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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
|
+
}
|
97
206
|
)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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'
|
103
245
|
)
|
104
|
-
task.print_out(f'Write modified code to: {main_file_path}')
|
105
|
-
with open(main_file_path, 'w') as f:
|
106
|
-
f.write(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
|
-
|
132
|
-
code = f.read()
|
272
|
+
code = await read_text_file_async(config_file_path)
|
133
273
|
code += '\n' + config_code
|
134
274
|
task.print_out(f'Write config to: {config_file_path}')
|
135
|
-
|
136
|
-
f.write(code)
|
275
|
+
await write_text_file_async(config_file_path, code)
|
137
276
|
|
138
277
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
)
|
144
|
-
def create_automation_config(*args: Any, **kwargs: Any):
|
145
|
-
task: Task = kwargs.get('_task')
|
146
|
-
project_dir = kwargs.get('project_dir', '.')
|
147
|
-
app_name = kwargs.get('app_name')
|
148
|
-
module_name = kwargs.get('module_name')
|
149
|
-
snake_app_name = util.to_snake_case(app_name)
|
150
|
-
snake_module_name = util.to_snake_case(module_name)
|
151
|
-
json_modules_file_path = os.path.join(
|
152
|
-
project_dir, '_automate', snake_app_name, 'config', 'modules.json'
|
153
|
-
)
|
278
|
+
async def create_automation_json_config(
|
279
|
+
task: Task,
|
280
|
+
json_modules_file_path: str,
|
281
|
+
snake_module_name: str,
|
282
|
+
):
|
154
283
|
task.print_out(f'Read json config from: {json_modules_file_path}')
|
155
|
-
|
156
|
-
json_str = f.read()
|
284
|
+
json_str = await read_text_file_async(json_modules_file_path)
|
157
285
|
task.print_out(f'Add "{snake_module_name}" to json config')
|
158
286
|
modules: List[str] = jsons.loads(json_str)
|
159
287
|
modules.append(snake_module_name)
|
160
288
|
json_str = jsons.dumps(modules)
|
161
289
|
task.print_out(f'Write new json config to: {json_modules_file_path}')
|
162
|
-
|
163
|
-
|
290
|
+
await write_text_file_async(json_modules_file_path, json_str)
|
291
|
+
return modules
|
164
292
|
|
165
293
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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)
|
171
319
|
|
172
320
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
)
|
183
|
-
|
184
|
-
|
185
|
-
|
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(
|
341
|
+
project_dir, '_automate', snake_app_name, 'config', 'modules.json'
|
342
|
+
)
|
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(
|
354
|
+
project_dir, 'src', kebab_app_name, 'src', 'template.env'
|
355
|
+
)
|
356
|
+
|
357
|
+
|
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
|
+
)
|
362
|
+
|
363
|
+
|
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
|
+
|
@@ -33,8 +33,7 @@ pip freeze
|
|
33
33
|
pip freeze | grep dbt
|
34
34
|
```
|
35
35
|
|
36
|
-
|
37
|
-
# How to Start PascalProjectName
|
36
|
+
# Activating PascalProjectName
|
38
37
|
|
39
38
|
```bash
|
40
39
|
source ./project.sh
|
@@ -58,4 +57,21 @@ To reload your configurations, you can invoke the following command:
|
|
58
57
|
reload
|
59
58
|
```
|
60
59
|
|
61
|
-
Please note that PascalProjectName's virtual environment has to be activated first.
|
60
|
+
Please note that PascalProjectName's virtual environment has to be activated first.
|
61
|
+
|
62
|
+
# Getting task environments
|
63
|
+
|
64
|
+
To get task environments, you can invoke the following command:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
zrb project get-default-env
|
68
|
+
```
|
69
|
+
|
70
|
+
It is expected to use the command for informational purposes only.
|
71
|
+
You should only override necessary environment variables to keep track of what you need to change.
|
72
|
+
|
73
|
+
Being said so, you can also add the default task environments to `.env` by invoking the following command:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
zrb project get-default-env >> .env
|
77
|
+
```
|
@@ -1,29 +1,28 @@
|
|
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
|
-
|
21
|
-
|
22
|
-
code
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
with open(zrb_init_path, 'w') as f:
|
29
|
-
f.write(code)
|
20
|
+
code = await read_text_file_async(zrb_init_path)
|
21
|
+
import_alias = project_task_module_path.split('.')[-1]
|
22
|
+
code = add_import_module(
|
23
|
+
code=code,
|
24
|
+
module_path=project_task_module_path,
|
25
|
+
alias=import_alias
|
26
|
+
)
|
27
|
+
code = add_assert_resource(code, import_alias)
|
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,17 +185,14 @@ 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
|
-
|
189
|
-
code
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
code
|
195
|
-
|
196
|
-
|
197
|
-
with open(project_automation_path, 'w') as f:
|
198
|
-
f.write(code)
|
199
|
-
|
188
|
+
code = await read_text_file_async(project_automation_path)
|
189
|
+
code = add_import_module(
|
190
|
+
code=code,
|
191
|
+
module_path=upstream_module_path,
|
192
|
+
resource=upstream_task_var
|
193
|
+
)
|
194
|
+
code = add_upstream_to_task(
|
195
|
+
code, project_automation_task_name, upstream_task_var
|
196
|
+
)
|
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 =
|
52
|
-
|
53
|
-
|
51
|
+
async with aiofiles.open(file_path, mode='rb') as file:
|
52
|
+
contents = await file.read()
|
53
|
+
hashed_text = hashlib.md5(contents).hexdigest()
|
54
|
+
return hashed_text
|
zrb/builtin/project.py
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
from typing import Any, Mapping
|
2
|
+
from ._group import project_group
|
3
|
+
from ..task.decorator import python_task
|
4
|
+
from ..task_input.bool_input import BoolInput
|
5
|
+
from ..runner import runner
|
6
|
+
from ..helper.env_map.fetch import fetch_env_map_from_group
|
7
|
+
|
8
|
+
|
9
|
+
@python_task(
|
10
|
+
name='get-default-env',
|
11
|
+
description='Get default values for project environments',
|
12
|
+
inputs=[
|
13
|
+
BoolInput(
|
14
|
+
name='export',
|
15
|
+
shortcut='e',
|
16
|
+
description='Whether add export statement or not',
|
17
|
+
default=True
|
18
|
+
)
|
19
|
+
],
|
20
|
+
group=project_group,
|
21
|
+
runner=runner
|
22
|
+
)
|
23
|
+
async def get_default_env(*args: Any, **kwargs: Any) -> str:
|
24
|
+
env_map: Mapping[str, str] = {}
|
25
|
+
env_map = fetch_env_map_from_group(env_map, project_group)
|
26
|
+
env_keys = list(env_map.keys())
|
27
|
+
env_keys.sort()
|
28
|
+
should_export = kwargs.get('export', True)
|
29
|
+
export_prefix = 'export ' if should_export else ''
|
30
|
+
return '\n'.join([
|
31
|
+
f'{export_prefix}{key}={env_map[key]}' for key in env_keys
|
32
|
+
])
|
@@ -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)
|