stoobly-agent 1.4.0__py3-none-any.whl → 1.4.2__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.
- stoobly_agent/__init__.py +1 -1
- stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +2 -2
- stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py +2 -2
- stoobly_agent/app/cli/scaffold/hosts_file_manager.py +97 -24
- stoobly_agent/app/cli/scaffold/service_config.py +16 -2
- stoobly_agent/app/cli/scaffold/templates/app/.Makefile +15 -8
- stoobly_agent/app/cli/scaffold_cli.py +75 -48
- stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
- {stoobly_agent-1.4.0.dist-info → stoobly_agent-1.4.2.dist-info}/METADATA +1 -1
- {stoobly_agent-1.4.0.dist-info → stoobly_agent-1.4.2.dist-info}/RECORD +13 -13
- {stoobly_agent-1.4.0.dist-info → stoobly_agent-1.4.2.dist-info}/LICENSE +0 -0
- {stoobly_agent-1.4.0.dist-info → stoobly_agent-1.4.2.dist-info}/WHEEL +0 -0
- {stoobly_agent-1.4.0.dist-info → stoobly_agent-1.4.2.dist-info}/entry_points.txt +0 -0
stoobly_agent/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
COMMAND = 'stoobly-agent'
|
2
|
-
VERSION = '1.4.
|
2
|
+
VERSION = '1.4.2'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
import pdb
|
3
3
|
|
4
|
-
from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, STOOBLY_CERTS_DIR
|
4
|
+
from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, SERVICE_PROXY_MODE, STOOBLY_CERTS_DIR
|
5
5
|
from .builder import WorkflowBuilder
|
6
6
|
|
7
7
|
class MockDecorator():
|
@@ -24,7 +24,7 @@ class MockDecorator():
|
|
24
24
|
'--headless',
|
25
25
|
'--intercept',
|
26
26
|
'--lifecycle-hooks-path', 'lifecycle_hooks.py',
|
27
|
-
'--proxy-mode',
|
27
|
+
'--proxy-mode', SERVICE_PROXY_MODE,
|
28
28
|
'--proxy-port', f"{SERVICE_PORT}",
|
29
29
|
'--response-fixtures-path', 'fixtures.yml',
|
30
30
|
'--ssl-insecure'
|
@@ -3,7 +3,7 @@ import pdb
|
|
3
3
|
|
4
4
|
from urllib.parse import urlparse
|
5
5
|
|
6
|
-
from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, STOOBLY_CERTS_DIR
|
6
|
+
from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, SERVICE_PROXY_MODE, STOOBLY_CERTS_DIR
|
7
7
|
from .builder import WorkflowBuilder
|
8
8
|
|
9
9
|
class ReverseProxyDecorator():
|
@@ -25,7 +25,7 @@ class ReverseProxyDecorator():
|
|
25
25
|
command = [
|
26
26
|
'--headless',
|
27
27
|
'--lifecycle-hooks-path', 'lifecycle_hooks.py',
|
28
|
-
'--proxy-mode',
|
28
|
+
'--proxy-mode', SERVICE_PROXY_MODE,
|
29
29
|
'--proxy-port', f"{SERVICE_PORT}",
|
30
30
|
'--ssl-insecure'
|
31
31
|
]
|
@@ -66,47 +66,120 @@ class HostsFileManager():
|
|
66
66
|
def install_hostnames(self, hostnames: list[str]) -> None:
|
67
67
|
hosts_file_path = self.__get_hosts_file_path()
|
68
68
|
|
69
|
-
self.
|
70
|
-
hosts_file_path, SCAFFOLD_HOSTS_DELIMITTER_BEGIN, SCAFFOLD_HOSTS_DELIMITTER_END
|
69
|
+
self.__add_lines_between_markers(
|
70
|
+
hosts_file_path, SCAFFOLD_HOSTS_DELIMITTER_BEGIN, SCAFFOLD_HOSTS_DELIMITTER_END, hostnames
|
71
71
|
)
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
def uninstall_hostnames(self, hostnames: list[str] = []) -> None:
|
74
|
+
hosts_file_path = self.__get_hosts_file_path()
|
75
|
+
|
76
|
+
self.__remove_lines_between_markers(
|
77
|
+
hosts_file_path, SCAFFOLD_HOSTS_DELIMITTER_BEGIN, SCAFFOLD_HOSTS_DELIMITTER_END, hostnames
|
78
|
+
)
|
79
|
+
|
80
|
+
def __remove_lines_between_markers(self, file_path, start_marker, end_marker, hostnames = []):
|
81
|
+
with open(file_path, "r") as file:
|
82
|
+
lines = file.readlines()
|
83
|
+
|
84
|
+
filtered_lines = []
|
85
|
+
index = 0
|
76
86
|
|
87
|
+
# Continue until we reach start_marker
|
88
|
+
for line in lines:
|
89
|
+
index += 1
|
90
|
+
|
91
|
+
if start_marker in line:
|
92
|
+
break
|
93
|
+
|
94
|
+
filtered_lines.append(line)
|
95
|
+
|
96
|
+
# Continue until we reach end_marker
|
97
|
+
found_hostnames = {}
|
98
|
+
section = []
|
99
|
+
for line in lines[index:]:
|
100
|
+
index += 1
|
101
|
+
|
102
|
+
if end_marker in line:
|
103
|
+
break
|
104
|
+
|
105
|
+
found = False
|
77
106
|
for hostname in hostnames:
|
78
|
-
|
79
|
-
|
80
|
-
|
107
|
+
if hostname in line:
|
108
|
+
if hostname not in found_hostnames:
|
109
|
+
print(f"Removing hostname {hostname}")
|
81
110
|
|
82
|
-
|
83
|
-
|
111
|
+
found_hostnames[hostname] = True
|
112
|
+
found = True
|
84
113
|
|
85
|
-
|
86
|
-
|
114
|
+
if not found:
|
115
|
+
section.append(line)
|
87
116
|
|
88
|
-
|
89
|
-
|
90
|
-
|
117
|
+
# If there are still lines in the section
|
118
|
+
if len(section):
|
119
|
+
filtered_lines.append(start_marker)
|
120
|
+
section.append(end_marker)
|
121
|
+
filtered_lines += section
|
122
|
+
|
123
|
+
for line in lines[index:]:
|
124
|
+
filtered_lines.append(line)
|
91
125
|
|
92
|
-
|
126
|
+
with open(file_path, "w") as file:
|
127
|
+
file.writelines(filtered_lines)
|
93
128
|
|
94
|
-
def
|
129
|
+
def __add_lines_between_markers(self, file_path, start_marker, end_marker, hostnames = []):
|
95
130
|
with open(file_path, "r") as file:
|
96
131
|
lines = file.readlines()
|
97
|
-
|
98
|
-
inside_block = False
|
132
|
+
|
99
133
|
filtered_lines = []
|
134
|
+
index = 0
|
100
135
|
|
136
|
+
# Continue until we reach start_marker
|
101
137
|
for line in lines:
|
138
|
+
index += 1
|
102
139
|
if start_marker in line:
|
103
|
-
|
104
|
-
|
140
|
+
break
|
141
|
+
|
142
|
+
filtered_lines.append(line)
|
143
|
+
|
144
|
+
# If no empty line before start_marker, add one
|
145
|
+
if len(filtered_lines):
|
146
|
+
last_line = filtered_lines[-1]
|
147
|
+
|
148
|
+
if last_line != "\n":
|
149
|
+
filtered_lines.append("\n")
|
150
|
+
|
151
|
+
filtered_lines.append(start_marker)
|
152
|
+
|
153
|
+
# Continue until we reach end_marker
|
154
|
+
found_hostnames = {}
|
155
|
+
for line in lines[index:]:
|
156
|
+
index += 1
|
157
|
+
|
105
158
|
if end_marker in line:
|
106
|
-
|
107
|
-
|
108
|
-
|
159
|
+
break
|
160
|
+
|
161
|
+
found = False
|
162
|
+
for hostname in hostnames:
|
163
|
+
if hostname in line:
|
164
|
+
filtered_lines.append(line)
|
165
|
+
found_hostnames[hostname] = True
|
166
|
+
found = True
|
167
|
+
|
168
|
+
if not found:
|
109
169
|
filtered_lines.append(line)
|
170
|
+
|
171
|
+
for hostname in hostnames:
|
172
|
+
if hostname in found_hostnames:
|
173
|
+
continue
|
174
|
+
|
175
|
+
print(f"Installing hostname {hostname}")
|
176
|
+
filtered_lines.append(f"127.0.0.1 {hostname}\n")
|
177
|
+
filtered_lines.append(f"::1 {hostname}\n")
|
178
|
+
|
179
|
+
filtered_lines.append(end_marker)
|
180
|
+
|
181
|
+
for line in lines[index:]:
|
182
|
+
filtered_lines.append(line)
|
110
183
|
|
111
184
|
with open(file_path, "w") as file:
|
112
185
|
file.writelines(filtered_lines)
|
@@ -92,7 +92,21 @@ class ServiceConfig(Config):
|
|
92
92
|
if self.__proxy_mode:
|
93
93
|
return (self.__proxy_mode or '').strip()
|
94
94
|
|
95
|
-
|
95
|
+
if not self.hostname:
|
96
|
+
return ''
|
97
|
+
|
98
|
+
_proxy_mode = f"reverse:{self.scheme}://{self.hostname}"
|
99
|
+
|
100
|
+
if not self.port:
|
101
|
+
return _proxy_mode
|
102
|
+
|
103
|
+
if self.scheme == 'http' and self.port == '80':
|
104
|
+
return _proxy_mode
|
105
|
+
|
106
|
+
if self.scheme == 'https' and self.port == '443':
|
107
|
+
return _proxy_mode
|
108
|
+
|
109
|
+
return f"{_proxy_mode}:{self.port}"
|
96
110
|
|
97
111
|
@proxy_mode.setter
|
98
112
|
def proxy_mode(self, v):
|
@@ -123,7 +137,7 @@ class ServiceConfig(Config):
|
|
123
137
|
'port': self.port,
|
124
138
|
'priority': self.priority,
|
125
139
|
'proxy_mode': self.proxy_mode,
|
126
|
-
'scheme': self.scheme,
|
140
|
+
'scheme': self.scheme if self.hostname else '',
|
127
141
|
}
|
128
142
|
|
129
143
|
def write(self):
|
@@ -61,8 +61,15 @@ stoobly_exec_run_env=$(source_env) && $(exec_env) && export CONTEXT_DIR="$(app_d
|
|
61
61
|
workflow_run=$(source_env) && bash "$(workflow_run_script)"
|
62
62
|
|
63
63
|
ca-cert/install: stoobly/install
|
64
|
-
@
|
65
|
-
|
64
|
+
@if [ ! -d "$$HOME/.mitmproxy" ]; then \
|
65
|
+
read -p "Installing CA certificate is required for $(WORKFLOW)ing requests, continue? (y/N) " confirm && \
|
66
|
+
if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \
|
67
|
+
echo "Running stoobly-agent ca-cert install..."; \
|
68
|
+
stoobly-agent ca-cert install; \
|
69
|
+
else \
|
70
|
+
echo "You can install the CA certificate later by running: stoobly-agent ca-cert install"; \
|
71
|
+
fi \
|
72
|
+
fi
|
66
73
|
certs:
|
67
74
|
@export EXEC_COMMAND=bin/.mkcert && \
|
68
75
|
$(stoobly_exec)
|
@@ -89,7 +96,7 @@ intercept/enable:
|
|
89
96
|
@export EXEC_COMMAND=bin/.enable && \
|
90
97
|
export EXEC_ARGS=$(scenario_key) && \
|
91
98
|
$(stoobly_exec)
|
92
|
-
mock: workflow/mock workflow/hostname/install nameservers workflow/up
|
99
|
+
mock: workflow/mock ca-cert/install workflow/hostname/install nameservers workflow/up
|
93
100
|
mock/services: workflow/mock workflow/services
|
94
101
|
mock/logs: workflow/mock workflow/logs
|
95
102
|
mock/down: workflow/mock workflow/down workflow/hostname/uninstall
|
@@ -103,7 +110,7 @@ python/validate:
|
|
103
110
|
echo "Error: Python 3.10, 3.11, or 3.12 is required."; \
|
104
111
|
exit 1; \
|
105
112
|
fi
|
106
|
-
record: workflow/record workflow/hostname/install nameservers workflow/up
|
113
|
+
record: workflow/record ca-cert/install workflow/hostname/install nameservers workflow/up
|
107
114
|
record/down: workflow/record workflow/down workflow/hostname/uninstall
|
108
115
|
record/services: workflow/record workflow/services
|
109
116
|
record/logs: workflow/record workflow/logs
|
@@ -139,7 +146,7 @@ scenario/snapshot:
|
|
139
146
|
stoobly/install: python/validate pipx/install
|
140
147
|
@if ! pipx list 2> /dev/null | grep -q 'stoobly-agent'; then \
|
141
148
|
echo "stoobly-agent not found. Installing..."; \
|
142
|
-
pipx install stoobly-agent; \
|
149
|
+
pipx install stoobly-agent || { echo "Failed to install stoobly-agent"; exit 1; }; \
|
143
150
|
fi
|
144
151
|
test: workflow/test workflow/up
|
145
152
|
test/services: workflow/test workflow/services
|
@@ -158,12 +165,12 @@ workflow/hostname: stoobly/install
|
|
158
165
|
if [ "$$confirm" = "y" ] || [ "$$confirm" = "Y" ]; then \
|
159
166
|
CURRENT_VERSION=$$(stoobly-agent --version); \
|
160
167
|
REQUIRED_VERSION="1.4.0"; \
|
161
|
-
if [ "$$(printf '%s\n' "$$REQUIRED_VERSION" "$$CURRENT_VERSION" | sort -V |
|
168
|
+
if [ "$$(printf '%s\n' "$$REQUIRED_VERSION" "$$CURRENT_VERSION" | sort -V | head -n 1)" != "$$REQUIRED_VERSION" ]; then \
|
162
169
|
echo "stoobly-agent version $$REQUIRED_VERSION required. Please run: pipx upgrade stoobly-agent"; \
|
163
170
|
exit 1; \
|
164
171
|
fi; \
|
165
|
-
echo "Running stoobly-agent scaffold hostname $(COMMAND)
|
166
|
-
stoobly-agent scaffold hostname $(COMMAND) --app-dir-path $(app_dir) --workflow $(WORKFLOW); \
|
172
|
+
echo "Running stoobly-agent scaffold hostname $(COMMAND) $(workflow_service_options)"; \
|
173
|
+
stoobly-agent scaffold hostname $(COMMAND) --app-dir-path $(app_dir) --workflow $(WORKFLOW) $(workflow_service_options); \
|
167
174
|
fi
|
168
175
|
workflow/hostname/install: command/install workflow/hostname
|
169
176
|
workflow/hostname/uninstall: command/uninstall workflow/hostname
|
@@ -108,14 +108,19 @@ def create(**kwargs):
|
|
108
108
|
@click.option('--certs-dir-path', help='Path to certs directory. Defaults to the certs dir of the context.')
|
109
109
|
@click.option('--context-dir-path', default=data_dir.context_dir_path, help='Path to Stoobly data directory.')
|
110
110
|
@click.option('--service', multiple=True, help='Select which services to run. Defaults to all.')
|
111
|
+
@click.option('--workflow', multiple=True, help='Specify services by workflow(s). Defaults to all.')
|
111
112
|
def mkcert(**kwargs):
|
112
113
|
app = App(kwargs['app_dir_path'], DOCKER_NAMESPACE, **kwargs)
|
113
114
|
__validate_app(app)
|
114
115
|
|
115
|
-
services = __get_services(
|
116
|
+
services = __get_services(
|
117
|
+
app, service=kwargs['service'], without_core=True, workflow=kwargs['workflow']
|
118
|
+
)
|
116
119
|
|
117
120
|
for service_name in services:
|
118
121
|
service = Service(service_name, app)
|
122
|
+
__validate_service_dir(service.dir_path)
|
123
|
+
|
119
124
|
service_config = ServiceConfig(service.dir_path)
|
120
125
|
|
121
126
|
if service_config.scheme != 'https':
|
@@ -170,19 +175,23 @@ def create(**kwargs):
|
|
170
175
|
@click.option('--select', multiple=True, help='Select column(s) to display.')
|
171
176
|
@click.option('--service', multiple=True, help='Select specific services.')
|
172
177
|
@click.option('--without-headers', is_flag=True, default=False, help='Disable printing column headers.')
|
173
|
-
@click.option('--workflow', multiple=True, help='Specify workflow(s) to filter the services by.')
|
178
|
+
@click.option('--workflow', multiple=True, help='Specify workflow(s) to filter the services by. Defaults to all.')
|
174
179
|
def _list(**kwargs):
|
175
|
-
__validate_app_dir(kwargs['app_dir_path'])
|
176
|
-
|
177
180
|
app = App(kwargs['app_dir_path'], DOCKER_NAMESPACE)
|
178
181
|
__validate_app(app)
|
179
182
|
|
183
|
+
services = __get_services(app, service=kwargs['service'], workflow=kwargs['workflow'])
|
184
|
+
|
180
185
|
rows = []
|
181
|
-
for service_name in
|
186
|
+
for service_name in services:
|
182
187
|
service = Service(service_name, app)
|
183
188
|
__validate_service_dir(service.dir_path)
|
189
|
+
|
184
190
|
service_config = ServiceConfig(service.dir_path)
|
185
|
-
rows.append(
|
191
|
+
rows.append({
|
192
|
+
'name': service_name,
|
193
|
+
**service_config.to_dict()
|
194
|
+
})
|
186
195
|
|
187
196
|
print_services(rows, **select_print_options(kwargs))
|
188
197
|
|
@@ -192,9 +201,9 @@ def _list(**kwargs):
|
|
192
201
|
@click.option('--app-dir-path', default=current_working_dir, help='Path to application directory.')
|
193
202
|
@click.argument('service_name')
|
194
203
|
def delete(**kwargs):
|
195
|
-
__validate_app_dir(kwargs['app_dir_path'])
|
196
|
-
|
197
204
|
app = App(kwargs['app_dir_path'], DOCKER_NAMESPACE)
|
205
|
+
__validate_app(app)
|
206
|
+
|
198
207
|
service = Service(kwargs['service_name'], app)
|
199
208
|
|
200
209
|
if not os.path.exists(service.dir_path):
|
@@ -211,9 +220,9 @@ def delete(**kwargs):
|
|
211
220
|
@click.option('--priority', help='Determines the service run order.')
|
212
221
|
@click.argument('service_name')
|
213
222
|
def update(**kwargs):
|
214
|
-
__validate_app_dir(kwargs['app_dir_path'])
|
215
|
-
|
216
223
|
app = App(kwargs['app_dir_path'], DOCKER_NAMESPACE)
|
224
|
+
__validate_app(app)
|
225
|
+
|
217
226
|
service = Service(kwargs['service_name'], app)
|
218
227
|
|
219
228
|
__validate_service_dir(service.dir_path)
|
@@ -304,8 +313,9 @@ def down(**kwargs):
|
|
304
313
|
if kwargs['namespace'] and not kwargs['network']:
|
305
314
|
kwargs['network'] = kwargs['namespace']
|
306
315
|
|
307
|
-
|
308
|
-
|
316
|
+
services = __get_services(
|
317
|
+
app, service=kwargs['service'], workflow=[kwargs['workflow_name']]
|
318
|
+
)
|
309
319
|
|
310
320
|
commands: List[WorkflowRunCommand] = []
|
311
321
|
for service in services:
|
@@ -379,8 +389,9 @@ def logs(**kwargs):
|
|
379
389
|
if len(kwargs['container']) == 0:
|
380
390
|
kwargs['container'] = [WORKFLOW_CONTAINER_PROXY]
|
381
391
|
|
382
|
-
|
383
|
-
|
392
|
+
services = __get_services(
|
393
|
+
app, service=kwargs['service'], without_core=True, workflow=[kwargs['workflow_name']]
|
394
|
+
)
|
384
395
|
|
385
396
|
commands: List[WorkflowLogCommand] = []
|
386
397
|
for service in services:
|
@@ -445,10 +456,12 @@ def up(**kwargs):
|
|
445
456
|
if kwargs['namespace'] and not kwargs['network']:
|
446
457
|
kwargs['network'] = kwargs['namespace']
|
447
458
|
|
448
|
-
|
449
|
-
|
459
|
+
services = __get_services(
|
460
|
+
app, service=kwargs['service'], workflow=[kwargs['workflow_name']]
|
461
|
+
)
|
450
462
|
|
451
463
|
# Gateway ports are dynamically set depending on the workflow run
|
464
|
+
workflow = Workflow(kwargs['workflow_name'], app)
|
452
465
|
set_gateway_ports(workflow.service_paths_from_services(services))
|
453
466
|
|
454
467
|
commands: List[WorkflowRunCommand] = []
|
@@ -541,13 +554,15 @@ def validate(**kwargs):
|
|
541
554
|
help="Update the system hosts file for all scaffold service hostnames"
|
542
555
|
)
|
543
556
|
@click.option('--app-dir-path', default=current_working_dir, help='Path to application directory.')
|
544
|
-
@click.option('--service', multiple=True, help='Select specific services.')
|
545
|
-
@click.option('--workflow', multiple=True, help='Specify services by workflow(s).')
|
557
|
+
@click.option('--service', multiple=True, help='Select specific services. Defaults to all.')
|
558
|
+
@click.option('--workflow', multiple=True, help='Specify services by workflow(s). Defaults to all.')
|
546
559
|
def install(**kwargs):
|
547
560
|
app = App(kwargs['app_dir_path'], DOCKER_NAMESPACE)
|
548
561
|
__validate_app(app)
|
549
562
|
|
550
|
-
services =
|
563
|
+
services = __get_services(
|
564
|
+
app, service=kwargs['service'], without_core=True, workflow=kwargs['workflow']
|
565
|
+
)
|
551
566
|
|
552
567
|
hostnames = []
|
553
568
|
for service_name in services:
|
@@ -565,25 +580,39 @@ def install(**kwargs):
|
|
565
580
|
hosts_file_manager.install_hostnames(hostnames)
|
566
581
|
except PermissionError:
|
567
582
|
print("Permission denied. Please run this command with sudo.", file=sys.stderr)
|
583
|
+
sys.exit(1)
|
568
584
|
|
569
585
|
@hostname.command(
|
570
586
|
help="Delete from the system hosts file all scaffold service hostnames"
|
571
587
|
)
|
572
588
|
@click.option('--app-dir-path', default=current_working_dir, help='Path to application directory.')
|
589
|
+
@click.option('--service', multiple=True, help='Select specific services. Defaults to all.')
|
590
|
+
@click.option('--workflow', multiple=True, help='Specify services by workflow(s). Defaults to all.')
|
573
591
|
def uninstall(**kwargs):
|
574
592
|
app = App(kwargs['app_dir_path'], DOCKER_NAMESPACE)
|
575
593
|
__validate_app(app)
|
576
594
|
|
595
|
+
services = __get_services(
|
596
|
+
app, service=kwargs['service'], without_core=True, workflow=kwargs['workflow']
|
597
|
+
)
|
598
|
+
|
599
|
+
hostnames = []
|
600
|
+
for service_name in services:
|
601
|
+
service = Service(service_name, app)
|
602
|
+
__validate_service_dir(service.dir_path)
|
603
|
+
|
604
|
+
service_config = ServiceConfig(service.dir_path)
|
605
|
+
if service_config.hostname:
|
606
|
+
hostnames.append(service_config.hostname)
|
607
|
+
|
577
608
|
__elevate_sudo()
|
578
609
|
|
579
610
|
try:
|
580
611
|
hosts_file_manager = HostsFileManager()
|
581
|
-
hosts_file_manager.uninstall_hostnames()
|
582
|
-
except
|
583
|
-
|
584
|
-
|
585
|
-
else:
|
586
|
-
print(f"An unexpected error occurred: {e}", file=sys.stderr)
|
612
|
+
hosts_file_manager.uninstall_hostnames(hostnames)
|
613
|
+
except PermissionError:
|
614
|
+
print("Permission denied. Please run this command with sudo.", file=sys.stderr)
|
615
|
+
sys.exit(1)
|
587
616
|
|
588
617
|
scaffold.add_command(app)
|
589
618
|
scaffold.add_command(service)
|
@@ -597,39 +626,37 @@ def __elevate_sudo():
|
|
597
626
|
subprocess.run(["sudo", sys.executable] + sys.argv)
|
598
627
|
sys.exit(0)
|
599
628
|
|
600
|
-
def __get_services(
|
629
|
+
def __get_services(app: App, **kwargs):
|
601
630
|
selected_services = list(kwargs['service'])
|
602
631
|
|
603
|
-
|
604
|
-
|
605
|
-
|
632
|
+
if not selected_services:
|
633
|
+
selected_services = app.services
|
634
|
+
else:
|
635
|
+
selected_services += CORE_SERVICES
|
636
|
+
missing_services = [service for service in selected_services if service not in app.services]
|
606
637
|
|
607
|
-
# Remove services that don't exist
|
608
638
|
if missing_services:
|
639
|
+
# Warn if an invalid service is provided
|
609
640
|
Logger.instance(LOG_ID).warn(f"Service(s) {','.join(missing_services)} are not found")
|
610
|
-
selected_services = list(set(selected_services) - set(missing_services))
|
611
641
|
|
612
|
-
services
|
642
|
+
# Remove services that don't exist
|
643
|
+
selected_services = list(set(selected_services) - set(missing_services))
|
613
644
|
|
614
|
-
|
645
|
+
# If without_score is set, filter out CORE_SERVICES
|
646
|
+
if kwargs.get('without_core'):
|
647
|
+
selected_services = list(set(selected_services) - set(CORE_SERVICES))
|
615
648
|
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
continue
|
620
|
-
services_index[service] = True
|
621
|
-
|
622
|
-
return services_index.keys()
|
623
|
-
|
624
|
-
def __get_workflow_services(app: App, **kwargs):
|
625
|
-
selected_services = []
|
626
|
-
if not kwargs['workflow']:
|
627
|
-
selected_services += __get_services(app.services, service=kwargs['service'], without_core=True)
|
628
|
-
else:
|
649
|
+
# If workflow is set, keep only services in the workflow
|
650
|
+
if kwargs.get('workflow'):
|
651
|
+
workflow_services = []
|
629
652
|
for workflow_name in kwargs['workflow']:
|
630
653
|
workflow = Workflow(workflow_name, app)
|
631
|
-
|
632
|
-
|
654
|
+
workflow_services += workflow.services
|
655
|
+
|
656
|
+
# Intersection
|
657
|
+
selected_services = list(filter(lambda x: x in workflow_services, selected_services))
|
658
|
+
|
659
|
+
return list(set(selected_services))
|
633
660
|
|
634
661
|
def __print_header(text: str):
|
635
662
|
Logger.instance(LOG_ID).info(f"{bcolors.OKBLUE}{text}{bcolors.ENDC}")
|
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.1
|
@@ -1,4 +1,4 @@
|
|
1
|
-
stoobly_agent/__init__.py,sha256=
|
1
|
+
stoobly_agent/__init__.py,sha256=fihCDP2FvrNTuWxSlgwYRREc1dhd8hCm3TlzVPcHgx4,44
|
2
2
|
stoobly_agent/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
stoobly_agent/app/api/__init__.py,sha256=ctkB8KR-eXO0SFhj602huHiyvQ3PslFWd8fkcufgrAI,1000
|
4
4
|
stoobly_agent/app/api/application_http_request_handler.py,sha256=ZgCfmdr5um-OFAiuRHdBxFqPIeph9WqYkVg-oVQWw-E,5543
|
@@ -88,14 +88,14 @@ stoobly_agent/app/cli/scaffold/docker/workflow/build_decorator.py,sha256=vbmME0c
|
|
88
88
|
stoobly_agent/app/cli/scaffold/docker/workflow/builder.py,sha256=G9zyw_jS0HEHtzl0EvoDQ9MlpTavlyWz0xFpgEZoyVc,6844
|
89
89
|
stoobly_agent/app/cli/scaffold/docker/workflow/decorators_factory.py,sha256=oi0Hkii2W9338IeG7BG2medQxqZUbBp71Cvj-qDunII,987
|
90
90
|
stoobly_agent/app/cli/scaffold/docker/workflow/development_decorator.py,sha256=cs00Cc2DuOYrGD8W9849PjHz6k2xyx0fSizqJlM7yR8,946
|
91
|
-
stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py,sha256=
|
92
|
-
stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py,sha256=
|
91
|
+
stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py,sha256=A0MvgT3nTB2SjBVwcpq1_AggWb8gU9HHD64E9JbhpDc,1218
|
92
|
+
stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py,sha256=eeB1Y7L6xYlD9w7oO7a4Ou0Gvfvvd2znnqrZQQz6IlQ,1825
|
93
93
|
stoobly_agent/app/cli/scaffold/env.py,sha256=e-Ve4p3RUgzFx22B3SIYttvJ_yLuDtA27oDACZ8n-6E,1140
|
94
|
-
stoobly_agent/app/cli/scaffold/hosts_file_manager.py,sha256=
|
94
|
+
stoobly_agent/app/cli/scaffold/hosts_file_manager.py,sha256=FiX1hYEWN4cJiCOV4h6wOOlY7t71uwIwe6t2upS65aQ,5006
|
95
95
|
stoobly_agent/app/cli/scaffold/managed_services_docker_compose.py,sha256=-wLBXUi7DCWsfm5KzZzd_kdJKOTl1NT924XR7dyjbSY,574
|
96
96
|
stoobly_agent/app/cli/scaffold/service.py,sha256=L9K6QE0k5KSEC8_fSwtdwwTSO_DsIpqSPW-AG7Bg76o,501
|
97
97
|
stoobly_agent/app/cli/scaffold/service_command.py,sha256=9kIKiFC5Jo425VWYD4NDvUOdMP-pNyq2D5Ip1ZAPj3A,1054
|
98
|
-
stoobly_agent/app/cli/scaffold/service_config.py,sha256=
|
98
|
+
stoobly_agent/app/cli/scaffold/service_config.py,sha256=NwJL4gwWQ_9B0fHrit1QekR6rSMg40m1CDizWxUNWCM,3598
|
99
99
|
stoobly_agent/app/cli/scaffold/service_create_command.py,sha256=bmLGgx9qnh-X_i2_XfdWSQIer0gGkaQx6lXZSIzy-LI,2793
|
100
100
|
stoobly_agent/app/cli/scaffold/service_delete_command.py,sha256=_nBDQjm8eL62MQpzSCxgUHlW04ZXKG8MDlN1BXxlqww,986
|
101
101
|
stoobly_agent/app/cli/scaffold/service_docker_compose.py,sha256=OMUN1-ujQYIZXxDvS4XBf5C9wGalQULkwOiBBQPZbHY,820
|
@@ -103,7 +103,7 @@ stoobly_agent/app/cli/scaffold/service_workflow.py,sha256=sQ_Edy_wGHKMXpD0DmhnOW
|
|
103
103
|
stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py,sha256=hF3c6cFRaKH01BfwdrCJdX8SEbsfD5CCG8W_yZU4FK4,9948
|
104
104
|
stoobly_agent/app/cli/scaffold/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
105
105
|
stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context,sha256=PRNYTWYYcLfcyrZ5h5u2I7dAJdeFmmxRFpAj_8243Bw,158
|
106
|
-
stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=
|
106
|
+
stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=F1OIlNw87Vw3HZqWeW908PVEnUtuIWC2gb6Bmivkr5A,8069
|
107
107
|
stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml,sha256=YblNDTUPndYNxupgZ3X8RP6NS4c0u_QwLklyWrpq_qs,295
|
108
108
|
stoobly_agent/app/cli/scaffold/templates/app/Makefile,sha256=TEmPG7Bf0KZOnmfsgdzza3UdwcVMmM5Lj1YdLc4cgjA,79
|
109
109
|
stoobly_agent/app/cli/scaffold/templates/app/build/.config.yml,sha256=8Wt8ZZ5irvBYYS44xGrR_EWlZDuXH9kyWmquzsh7s8g,19
|
@@ -195,7 +195,7 @@ stoobly_agent/app/cli/scaffold/workflow_env.py,sha256=x8V5pJmIiklD3f2q2-qq-CORf4
|
|
195
195
|
stoobly_agent/app/cli/scaffold/workflow_log_command.py,sha256=Bke4lMOMxuDUFuAx9nlXHbKgYMO4KAg9ASHvjz4aVWc,1372
|
196
196
|
stoobly_agent/app/cli/scaffold/workflow_run_command.py,sha256=DJNyhPrvvZgOwFnPKi5Z3VdrAWfaZW_XbGfgFcnh5QM,9608
|
197
197
|
stoobly_agent/app/cli/scaffold/workflow_validate_command.py,sha256=fhHciJXg_u32Wmh8us8LhgQj8D1SxkBADtuBBF4K0FM,4377
|
198
|
-
stoobly_agent/app/cli/scaffold_cli.py,sha256=
|
198
|
+
stoobly_agent/app/cli/scaffold_cli.py,sha256=1AjgMhHfjt9HEdShmYLVFhruJ0f2VZyUSvpJycTtGdM,26307
|
199
199
|
stoobly_agent/app/cli/scenario_cli.py,sha256=3J1EiJOvunkfWrEkOsanw-XrKkOk78ij_GjBlE9p7CE,8229
|
200
200
|
stoobly_agent/app/cli/snapshot_cli.py,sha256=cpCjxFYBuVwLuq_b2lIUu-5zWqupRlrp4xWgDytirSM,10047
|
201
201
|
stoobly_agent/app/cli/trace_cli.py,sha256=K7E-vx3JUcqEDSWOdIOi_AieKNQz7dBfmRrVvKDkzFI,4605
|
@@ -693,7 +693,7 @@ stoobly_agent/test/app/models/factories/resource/local_db/helpers/log_test.py,sh
|
|
693
693
|
stoobly_agent/test/app/models/factories/resource/local_db/helpers/tiebreak_scenario_request_test.py,sha256=5IFGVGn3ogvRT0fzZgXzhrYlSfSlr8IR1p_XExaegMQ,3399
|
694
694
|
stoobly_agent/test/app/models/factories/resource/local_db/request_adapter_test.py,sha256=Pzq1cBPnP9oSWG-p0c-VoymoHxgp483QmNwmV1b78RA,8453
|
695
695
|
stoobly_agent/test/app/models/factories/resource/local_db/response_adapter_test.py,sha256=9P95EKH5rZGOrmRkRIDlQZqtiLJHk9735og18Ffwpfw,2204
|
696
|
-
stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION,sha256=
|
696
|
+
stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION,sha256=8LZyMhqJSE9NqFn_x0G7_otbaT04f34F-Exd5iWhzGE,5
|
697
697
|
stoobly_agent/test/app/models/schemas/.stoobly/db/stoobly_agent.sqlite3,sha256=ch8gNx6zIelLKQx65gwFx_LRNqUD3EC5xcHZ0ukIQiU,188416
|
698
698
|
stoobly_agent/test/app/models/schemas/.stoobly/settings.yml,sha256=vLwMjweKOdod6tSLtIlyBefPQuNXq9wio4kBaODKtAU,726
|
699
699
|
stoobly_agent/test/app/models/schemas/.stoobly/tmp/options.json,sha256=OTRzarwus48CTrItedXCrgQttJHSEZonEYc7R_knvYg,2212
|
@@ -730,8 +730,8 @@ stoobly_agent/test/mock_data/scaffold/docker-compose-local-service.yml,sha256=x7
|
|
730
730
|
stoobly_agent/test/mock_data/scaffold/index.html,sha256=qJwuYajKZ4ihWZrJQ3BNObV5kf1VGnnm_vqlPJzdqLE,258
|
731
731
|
stoobly_agent/test/mock_data/uspto.yaml,sha256=6U5se7C3o-86J4m9xpOk9Npias399f5CbfWzR87WKwE,7835
|
732
732
|
stoobly_agent/test/test_helper.py,sha256=m_oAI7tmRYCNZdKfNqISWhMv3e44tjeYViQ3nTUfnos,1007
|
733
|
-
stoobly_agent-1.4.
|
734
|
-
stoobly_agent-1.4.
|
735
|
-
stoobly_agent-1.4.
|
736
|
-
stoobly_agent-1.4.
|
737
|
-
stoobly_agent-1.4.
|
733
|
+
stoobly_agent-1.4.2.dist-info/LICENSE,sha256=8QKGyy45eN76Zk52h8gu1DKX2B_gbWgZ3nzDLofEbaE,548
|
734
|
+
stoobly_agent-1.4.2.dist-info/METADATA,sha256=s7d8HJFX_n4hI7qcFJ3pFkoF-tmRNMIyOAq-CI59vKQ,3384
|
735
|
+
stoobly_agent-1.4.2.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
736
|
+
stoobly_agent-1.4.2.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
|
737
|
+
stoobly_agent-1.4.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|