stoobly-agent 1.0.14__py3-none-any.whl → 1.1.0__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/constants.py +7 -1
- stoobly_agent/app/cli/scaffold/docker/workflow/builder.py +6 -6
- stoobly_agent/app/cli/scaffold/hosts_file_reader.py +65 -0
- stoobly_agent/app/cli/scaffold/service_delete_command.py +35 -0
- stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py +37 -20
- stoobly_agent/app/cli/scaffold/templates/app/.Makefile +19 -1
- stoobly_agent/app/cli/scaffold/templates/app/gateway/.docker-compose.base.yml +3 -3
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.logs +10 -0
- stoobly_agent/app/cli/scaffold/workflow_command.py +1 -5
- stoobly_agent/app/cli/scaffold/workflow_log_command.py +30 -5
- stoobly_agent/app/cli/scaffold/workflow_run_command.py +0 -1
- stoobly_agent/app/cli/scaffold_cli.py +53 -23
- stoobly_agent/app/proxy/replay/multipart.py +3 -0
- stoobly_agent/test/app/cli/scaffold/cli_invoker.py +134 -0
- stoobly_agent/test/app/cli/scaffold/cli_test.py +128 -0
- stoobly_agent/test/app/cli/scaffold/e2e_test.py +19 -143
- stoobly_agent/test/app/cli/scaffold/hosts_file_reader_test.py +79 -0
- stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
- {stoobly_agent-1.0.14.dist-info → stoobly_agent-1.1.0.dist-info}/METADATA +9 -10
- {stoobly_agent-1.0.14.dist-info → stoobly_agent-1.1.0.dist-info}/RECORD +24 -18
- {stoobly_agent-1.0.14.dist-info → stoobly_agent-1.1.0.dist-info}/WHEEL +1 -1
- {stoobly_agent-1.0.14.dist-info → stoobly_agent-1.1.0.dist-info}/LICENSE +0 -0
- {stoobly_agent-1.0.14.dist-info → stoobly_agent-1.1.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
import pathlib
|
2
|
+
import pdb
|
3
|
+
|
4
|
+
from click.testing import CliRunner
|
5
|
+
|
6
|
+
from stoobly_agent.app.cli import scaffold
|
7
|
+
from stoobly_agent.config.data_dir import DATA_DIR_NAME
|
8
|
+
|
9
|
+
|
10
|
+
class ScaffoldCliInvoker():
|
11
|
+
|
12
|
+
@staticmethod
|
13
|
+
def cli_app_create(runner: CliRunner, app_dir_path: str, app_name: str):
|
14
|
+
pathlib.Path(f"{app_dir_path}/{DATA_DIR_NAME}").mkdir(parents=True, exist_ok=True)
|
15
|
+
|
16
|
+
result = runner.invoke(scaffold, ['app', 'create',
|
17
|
+
'--app-dir-path', app_dir_path,
|
18
|
+
'--force',
|
19
|
+
app_name
|
20
|
+
])
|
21
|
+
|
22
|
+
assert result.exit_code == 0
|
23
|
+
output = result.stdout
|
24
|
+
assert not output
|
25
|
+
|
26
|
+
@staticmethod
|
27
|
+
def cli_app_mkcert(runner: CliRunner, app_dir_path: str):
|
28
|
+
result = runner.invoke(scaffold, ['app', 'mkcert',
|
29
|
+
'--app-dir-path', app_dir_path,
|
30
|
+
'--context-dir-path', app_dir_path,
|
31
|
+
])
|
32
|
+
|
33
|
+
assert result.exit_code == 0
|
34
|
+
output = result.stdout
|
35
|
+
assert not output
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def cli_service_create(runner: CliRunner, app_dir_path: str, hostname: str, service_name: str, https: bool):
|
39
|
+
scheme = 'http'
|
40
|
+
port = '80'
|
41
|
+
if https == True:
|
42
|
+
scheme = 'https'
|
43
|
+
port = '443'
|
44
|
+
|
45
|
+
result = runner.invoke(scaffold, ['service', 'create',
|
46
|
+
'--app-dir-path', app_dir_path,
|
47
|
+
'--env', 'TEST',
|
48
|
+
'--force',
|
49
|
+
'--hostname', hostname,
|
50
|
+
'--scheme', scheme,
|
51
|
+
'--port', port,
|
52
|
+
'--workflow', 'mock',
|
53
|
+
'--workflow', 'record',
|
54
|
+
'--workflow', 'test',
|
55
|
+
service_name
|
56
|
+
])
|
57
|
+
assert result.exit_code == 0
|
58
|
+
output = result.stdout
|
59
|
+
assert not output
|
60
|
+
|
61
|
+
# Specific flags for assets
|
62
|
+
@staticmethod
|
63
|
+
def cli_service_create_assets(runner: CliRunner, app_dir_path: str, hostname: str, service_name: str, https: bool):
|
64
|
+
scheme = 'http'
|
65
|
+
port = '80'
|
66
|
+
if https == True:
|
67
|
+
scheme = 'https'
|
68
|
+
port = '443'
|
69
|
+
proxy_mode_reverse_spec = f"reverse:{scheme}://{hostname}:8080"
|
70
|
+
|
71
|
+
result = runner.invoke(scaffold, ['service', 'create',
|
72
|
+
'--app-dir-path', app_dir_path,
|
73
|
+
'--force',
|
74
|
+
'--hostname', hostname,
|
75
|
+
'--scheme', scheme,
|
76
|
+
'--port', port,
|
77
|
+
'--proxy-mode', proxy_mode_reverse_spec,
|
78
|
+
'--detached',
|
79
|
+
'--workflow', 'test',
|
80
|
+
service_name
|
81
|
+
])
|
82
|
+
assert result.exit_code == 0
|
83
|
+
output = result.stdout
|
84
|
+
assert not output
|
85
|
+
|
86
|
+
@staticmethod
|
87
|
+
def cli_service_delete(runner: CliRunner, app_dir_path: str, service_name: str):
|
88
|
+
result = runner.invoke(scaffold, ['service', 'delete',
|
89
|
+
'--app-dir-path', app_dir_path,
|
90
|
+
service_name
|
91
|
+
])
|
92
|
+
assert result.exit_code == 0
|
93
|
+
output = result.stdout
|
94
|
+
assert 'error' not in output.lower()
|
95
|
+
|
96
|
+
@staticmethod
|
97
|
+
def cli_workflow_create(runner: CliRunner, app_dir_path: str, service_name: str):
|
98
|
+
result = runner.invoke(scaffold, ['workflow', 'create',
|
99
|
+
'--app-dir-path', app_dir_path,
|
100
|
+
'--service', service_name,
|
101
|
+
'--template', 'mock',
|
102
|
+
'ci',
|
103
|
+
])
|
104
|
+
|
105
|
+
assert result.exit_code == 0
|
106
|
+
output = result.stdout
|
107
|
+
assert not output
|
108
|
+
|
109
|
+
@staticmethod
|
110
|
+
def cli_workflow_run(runner: CliRunner, app_dir_path: str, target_workflow_name: str):
|
111
|
+
command = ['workflow', 'run',
|
112
|
+
'--app-dir-path', app_dir_path,
|
113
|
+
'--context-dir-path', app_dir_path,
|
114
|
+
target_workflow_name,
|
115
|
+
]
|
116
|
+
result = runner.invoke(scaffold, command)
|
117
|
+
|
118
|
+
assert result.exit_code == 0
|
119
|
+
output = result.stdout
|
120
|
+
assert output
|
121
|
+
|
122
|
+
@staticmethod
|
123
|
+
def cli_workflow_stop(runner: CliRunner, app_dir_path: str, target_workflow_name: str):
|
124
|
+
command = ['workflow', 'stop',
|
125
|
+
'--app-dir-path', app_dir_path,
|
126
|
+
'--context-dir-path', app_dir_path,
|
127
|
+
target_workflow_name,
|
128
|
+
]
|
129
|
+
result = runner.invoke(scaffold, command)
|
130
|
+
|
131
|
+
assert result.exit_code == 0
|
132
|
+
output = result.stdout
|
133
|
+
assert output
|
134
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
import os
|
2
|
+
import pdb
|
3
|
+
import shutil
|
4
|
+
|
5
|
+
from click.testing import CliRunner
|
6
|
+
import pytest
|
7
|
+
|
8
|
+
from stoobly_agent.app.cli.scaffold.app import App
|
9
|
+
from stoobly_agent.app.cli.scaffold.constants import (
|
10
|
+
DOCKER_NAMESPACE,
|
11
|
+
WORKFLOW_RECORD_TYPE,
|
12
|
+
)
|
13
|
+
from stoobly_agent.app.cli.scaffold.service_docker_compose import ServiceDockerCompose
|
14
|
+
from stoobly_agent.config.data_dir import DataDir
|
15
|
+
from stoobly_agent.test.app.cli.scaffold.e2e_test import ScaffoldCliInvoker
|
16
|
+
from stoobly_agent.test.test_helper import reset
|
17
|
+
|
18
|
+
|
19
|
+
class TestScaffoldCli():
|
20
|
+
|
21
|
+
@pytest.fixture(scope='module', autouse=True)
|
22
|
+
def settings(self):
|
23
|
+
return reset()
|
24
|
+
|
25
|
+
@pytest.fixture(scope='module')
|
26
|
+
def runner(self):
|
27
|
+
yield CliRunner()
|
28
|
+
|
29
|
+
@pytest.fixture(scope='class')
|
30
|
+
def app_name(self):
|
31
|
+
yield "0.0.1"
|
32
|
+
|
33
|
+
@pytest.fixture(scope='class', autouse=True)
|
34
|
+
def temp_dir(self):
|
35
|
+
data_dir_path = DataDir.instance().path
|
36
|
+
tmp_path = data_dir_path[:data_dir_path.rfind('/')]
|
37
|
+
|
38
|
+
yield tmp_path
|
39
|
+
|
40
|
+
@pytest.fixture(scope='class', autouse=True)
|
41
|
+
def app_dir_path(self, temp_dir, app_name):
|
42
|
+
yield temp_dir
|
43
|
+
|
44
|
+
@pytest.fixture(scope='class')
|
45
|
+
def hostname(self):
|
46
|
+
yield "http.badssl.com"
|
47
|
+
|
48
|
+
@pytest.fixture(scope='class')
|
49
|
+
def https_service_hostname(self):
|
50
|
+
yield "example.com"
|
51
|
+
|
52
|
+
@pytest.fixture(scope='class')
|
53
|
+
def external_service_name(self):
|
54
|
+
yield "external-service"
|
55
|
+
|
56
|
+
@pytest.fixture(scope='class')
|
57
|
+
def external_https_service_name(self):
|
58
|
+
yield "external-https-service"
|
59
|
+
|
60
|
+
class TestServiceDelete():
|
61
|
+
@pytest.fixture(scope='class', autouse=True)
|
62
|
+
def target_workflow_name(self):
|
63
|
+
yield WORKFLOW_RECORD_TYPE
|
64
|
+
|
65
|
+
@pytest.fixture(scope='class')
|
66
|
+
def external_service_docker_compose(self, app_dir_path, target_workflow_name, external_service_name, hostname):
|
67
|
+
yield ServiceDockerCompose(app_dir_path=app_dir_path, target_workflow_name=target_workflow_name, service_name=external_service_name, hostname=hostname)
|
68
|
+
|
69
|
+
@pytest.fixture(scope='class')
|
70
|
+
def external_https_service_docker_compose(self, app_dir_path, target_workflow_name, external_https_service_name, https_service_hostname):
|
71
|
+
yield ServiceDockerCompose(app_dir_path=app_dir_path, target_workflow_name=target_workflow_name, service_name=external_https_service_name, hostname=https_service_hostname)
|
72
|
+
|
73
|
+
@pytest.fixture(scope="class", autouse=True)
|
74
|
+
def create_setup(self, runner, app_dir_path, app_name, external_service_docker_compose, external_https_service_docker_compose):
|
75
|
+
|
76
|
+
ScaffoldCliInvoker.cli_app_create(runner, app_dir_path, app_name)
|
77
|
+
|
78
|
+
# Create external user defined services
|
79
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, external_service_docker_compose.hostname, external_service_docker_compose.service_name, False)
|
80
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, external_https_service_docker_compose.hostname, external_https_service_docker_compose.service_name, True)
|
81
|
+
|
82
|
+
# Generate certs
|
83
|
+
ScaffoldCliInvoker.cli_app_mkcert(runner, app_dir_path)
|
84
|
+
|
85
|
+
@pytest.fixture(scope="class", autouse=True)
|
86
|
+
def cleanup_after_all(self, runner, app_dir_path, target_workflow_name):
|
87
|
+
yield
|
88
|
+
ScaffoldCliInvoker.cli_workflow_stop(runner, app_dir_path, target_workflow_name)
|
89
|
+
shutil.rmtree(app_dir_path)
|
90
|
+
|
91
|
+
|
92
|
+
def test_service_delete(self, runner, app_dir_path, external_service_docker_compose):
|
93
|
+
app = App(app_dir_path, DOCKER_NAMESPACE)
|
94
|
+
service_name = external_service_docker_compose.service_name
|
95
|
+
|
96
|
+
ScaffoldCliInvoker.cli_service_delete(runner, app_dir_path, service_name)
|
97
|
+
|
98
|
+
found = False
|
99
|
+
service_paths = app.service_paths
|
100
|
+
for service_path in service_paths:
|
101
|
+
if service_name in service_path:
|
102
|
+
found = True
|
103
|
+
break
|
104
|
+
if found:
|
105
|
+
assert False
|
106
|
+
|
107
|
+
def test_service_delete_https(self, runner, app_dir_path, external_https_service_docker_compose):
|
108
|
+
app = App(app_dir_path, DOCKER_NAMESPACE)
|
109
|
+
service_name = external_https_service_docker_compose.service_name
|
110
|
+
hostname = external_https_service_docker_compose.hostname
|
111
|
+
|
112
|
+
ScaffoldCliInvoker.cli_service_delete(runner, app_dir_path, service_name)
|
113
|
+
|
114
|
+
found = False
|
115
|
+
service_paths = app.service_paths
|
116
|
+
for service_path in service_paths:
|
117
|
+
if service_name in service_path:
|
118
|
+
found = True
|
119
|
+
break
|
120
|
+
if found:
|
121
|
+
assert False
|
122
|
+
|
123
|
+
# Certs should be deleted
|
124
|
+
certs_dir_path = os.listdir(app.certs_dir_path)
|
125
|
+
for cert_file in certs_dir_path:
|
126
|
+
if hostname in cert_file:
|
127
|
+
assert False
|
128
|
+
|
@@ -1,19 +1,16 @@
|
|
1
1
|
from pathlib import Path
|
2
|
-
import pathlib
|
3
2
|
import pdb
|
4
3
|
import shutil
|
5
4
|
|
6
5
|
from click.testing import CliRunner
|
7
|
-
import docker
|
8
6
|
import pytest
|
9
7
|
|
10
|
-
from stoobly_agent.app.cli import scaffold
|
11
8
|
from stoobly_agent.app.cli.scaffold.app import App
|
12
9
|
from stoobly_agent.app.cli.scaffold.constants import (
|
10
|
+
DOCKER_NAMESPACE,
|
13
11
|
WORKFLOW_RECORD_TYPE,
|
14
12
|
WORKFLOW_TEST_TYPE,
|
15
13
|
)
|
16
|
-
from stoobly_agent.app.cli.scaffold.constants import DOCKER_NAMESPACE
|
17
14
|
from stoobly_agent.app.cli.scaffold.managed_services_docker_compose import (
|
18
15
|
ManagedServicesDockerCompose,
|
19
16
|
)
|
@@ -24,7 +21,8 @@ from stoobly_agent.app.cli.scaffold.service_workflow_validate_command import (
|
|
24
21
|
from stoobly_agent.app.cli.scaffold.workflow_validate_command import (
|
25
22
|
WorkflowValidateCommand,
|
26
23
|
)
|
27
|
-
from stoobly_agent.config.data_dir import
|
24
|
+
from stoobly_agent.config.data_dir import DataDir
|
25
|
+
from stoobly_agent.test.app.cli.scaffold.cli_invoker import ScaffoldCliInvoker
|
28
26
|
from stoobly_agent.test.test_helper import reset
|
29
27
|
|
30
28
|
|
@@ -39,10 +37,6 @@ class TestScaffoldE2e():
|
|
39
37
|
def runner(self):
|
40
38
|
yield CliRunner()
|
41
39
|
|
42
|
-
@pytest.fixture(scope='class')
|
43
|
-
def docker_client(self):
|
44
|
-
yield docker.from_env()
|
45
|
-
|
46
40
|
@pytest.fixture(scope='class')
|
47
41
|
def app_name(self):
|
48
42
|
yield "0.0.1"
|
@@ -113,22 +107,16 @@ class TestScaffoldE2e():
|
|
113
107
|
def local_service_docker_compose(self, app_dir_path, target_workflow_name, local_service_name, local_hostname):
|
114
108
|
yield ServiceDockerCompose(app_dir_path=app_dir_path, target_workflow_name=target_workflow_name, service_name=local_service_name, hostname=local_hostname)
|
115
109
|
|
116
|
-
@pytest.fixture(scope='class', autouse=True)
|
117
|
-
def setup_docker_composes(self, managed_services_docker_compose, external_service_docker_compose, local_service_docker_compose):
|
118
|
-
self.managed_services_docker_compose = managed_services_docker_compose
|
119
|
-
self.external_service_docker_compose = external_service_docker_compose
|
120
|
-
self.local_service_docker_compose = local_service_docker_compose
|
121
|
-
|
122
110
|
@pytest.fixture(scope="class", autouse=True)
|
123
111
|
def create_scaffold_setup(self, runner, app_dir_path, app_name, target_workflow_name, external_service_docker_compose, external_https_service_docker_compose, local_service_docker_compose, local_service_mock_docker_compose_path):
|
124
|
-
|
112
|
+
ScaffoldCliInvoker.cli_app_create(runner, app_dir_path, app_name)
|
125
113
|
|
126
114
|
# Create external user defined service
|
127
|
-
|
128
|
-
|
115
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, external_service_docker_compose.hostname, external_service_docker_compose.service_name, False)
|
116
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, external_https_service_docker_compose.hostname, external_https_service_docker_compose.service_name, True)
|
129
117
|
|
130
118
|
# Create local user defined service
|
131
|
-
|
119
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, local_service_docker_compose.hostname, local_service_docker_compose.service_name, False)
|
132
120
|
|
133
121
|
# Validate docker-compose path exists
|
134
122
|
destination_path = Path(local_service_docker_compose.docker_compose_path)
|
@@ -139,14 +127,15 @@ class TestScaffoldE2e():
|
|
139
127
|
# Record workflow doesn't have a fixtures folder
|
140
128
|
|
141
129
|
# Generate certs
|
142
|
-
|
130
|
+
ScaffoldCliInvoker.cli_app_mkcert(runner, app_dir_path)
|
143
131
|
|
144
|
-
|
132
|
+
ScaffoldCliInvoker.cli_workflow_run(runner, app_dir_path, target_workflow_name)
|
145
133
|
|
146
134
|
@pytest.fixture(scope="class", autouse=True)
|
147
135
|
def cleanup_after_all(self, runner, app_dir_path, target_workflow_name):
|
148
136
|
yield
|
149
|
-
|
137
|
+
ScaffoldCliInvoker.cli_workflow_stop(runner, app_dir_path, target_workflow_name)
|
138
|
+
shutil.rmtree(app_dir_path)
|
150
139
|
|
151
140
|
def test_core_components(self, app_dir_path, target_workflow_name):
|
152
141
|
app = App(app_dir_path, DOCKER_NAMESPACE)
|
@@ -228,13 +217,13 @@ class TestScaffoldE2e():
|
|
228
217
|
@pytest.fixture(scope="class", autouse=True)
|
229
218
|
def create_scaffold_setup(self, runner, app_name, app_dir_path, target_workflow_name, external_service_docker_compose, local_service_docker_compose, assets_service_docker_compose, mock_data_directory_path, assets_service_mock_docker_compose_path):
|
230
219
|
|
231
|
-
|
220
|
+
ScaffoldCliInvoker.cli_app_create(runner, app_dir_path, app_name)
|
232
221
|
|
233
222
|
# Create external user defined service
|
234
|
-
|
223
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, external_service_docker_compose.hostname, external_service_docker_compose.service_name, False)
|
235
224
|
# Create local user defined services
|
236
|
-
|
237
|
-
|
225
|
+
ScaffoldCliInvoker.cli_service_create(runner, app_dir_path, local_service_docker_compose.hostname, local_service_docker_compose.service_name, False)
|
226
|
+
ScaffoldCliInvoker.cli_service_create_assets(runner, app_dir_path, assets_service_docker_compose.hostname, assets_service_docker_compose.service_name, False)
|
238
227
|
|
239
228
|
# Don't run the local user defined service in the 'test' workflow
|
240
229
|
# So don't copy the Docker Compose file over
|
@@ -244,7 +233,7 @@ class TestScaffoldE2e():
|
|
244
233
|
assert destination_path.is_file()
|
245
234
|
shutil.copyfile(assets_service_mock_docker_compose_path, destination_path)
|
246
235
|
|
247
|
-
|
236
|
+
ScaffoldCliInvoker.cli_service_create_assets(runner, app_dir_path, assets_service_docker_compose.hostname, assets_service_docker_compose.service_name, False)
|
248
237
|
|
249
238
|
# Add assets for assets service
|
250
239
|
data_dir_path = DataDir.instance().path
|
@@ -263,12 +252,13 @@ class TestScaffoldE2e():
|
|
263
252
|
with open(f"{command.fixtures_dir_path}/shared_file.txt", 'w') as file:
|
264
253
|
file.write('this is a shared file')
|
265
254
|
|
266
|
-
|
255
|
+
ScaffoldCliInvoker.cli_workflow_run(runner, app_dir_path, target_workflow_name=target_workflow_name)
|
267
256
|
|
268
257
|
@pytest.fixture(scope="class", autouse=True)
|
269
258
|
def cleanup_after_all(self, runner, app_dir_path, target_workflow_name):
|
270
259
|
yield
|
271
|
-
|
260
|
+
ScaffoldCliInvoker.cli_workflow_stop(runner, app_dir_path, target_workflow_name)
|
261
|
+
shutil.rmtree(app_dir_path)
|
272
262
|
|
273
263
|
def test_no_core_components(self, app_dir_path, target_workflow_name):
|
274
264
|
app = App(app_dir_path, DOCKER_NAMESPACE)
|
@@ -312,117 +302,3 @@ class TestScaffoldE2e():
|
|
312
302
|
command = ServiceWorkflowValidateCommand(app, **config)
|
313
303
|
command.validate()
|
314
304
|
|
315
|
-
@staticmethod
|
316
|
-
def cli_app_create(runner: CliRunner, app_dir_path: str, app_name: str):
|
317
|
-
pathlib.Path(f"{app_dir_path}/{DATA_DIR_NAME}").mkdir(parents=True, exist_ok=True)
|
318
|
-
|
319
|
-
result = runner.invoke(scaffold, ['app', 'create',
|
320
|
-
'--app-dir-path', app_dir_path,
|
321
|
-
'--force',
|
322
|
-
app_name
|
323
|
-
])
|
324
|
-
|
325
|
-
assert result.exit_code == 0
|
326
|
-
output = result.stdout
|
327
|
-
assert not output
|
328
|
-
|
329
|
-
@staticmethod
|
330
|
-
def cli_app_mkcert(runner: CliRunner, app_dir_path: str):
|
331
|
-
result = runner.invoke(scaffold, ['app', 'mkcert',
|
332
|
-
'--app-dir-path', app_dir_path,
|
333
|
-
'--context-dir-path', app_dir_path,
|
334
|
-
])
|
335
|
-
|
336
|
-
assert result.exit_code == 0
|
337
|
-
output = result.stdout
|
338
|
-
assert not output
|
339
|
-
|
340
|
-
|
341
|
-
@staticmethod
|
342
|
-
def cli_service_create(runner: CliRunner, app_dir_path: str, hostname: str, service_name: str, https: bool):
|
343
|
-
scheme = 'http'
|
344
|
-
port = '80'
|
345
|
-
if https == True:
|
346
|
-
scheme = 'https'
|
347
|
-
port = '443'
|
348
|
-
|
349
|
-
result = runner.invoke(scaffold, ['service', 'create',
|
350
|
-
'--app-dir-path', app_dir_path,
|
351
|
-
'--env', 'TEST',
|
352
|
-
'--force',
|
353
|
-
'--hostname', hostname,
|
354
|
-
'--scheme', scheme,
|
355
|
-
'--port', port,
|
356
|
-
'--workflow', 'mock',
|
357
|
-
'--workflow', 'record',
|
358
|
-
'--workflow', 'test',
|
359
|
-
service_name
|
360
|
-
])
|
361
|
-
assert result.exit_code == 0
|
362
|
-
output = result.stdout
|
363
|
-
assert not output
|
364
|
-
|
365
|
-
# Specific flags for assets
|
366
|
-
@staticmethod
|
367
|
-
def cli_service_create_assets(runner: CliRunner, app_dir_path: str, hostname: str, service_name: str, https: bool):
|
368
|
-
scheme = 'http'
|
369
|
-
port = '80'
|
370
|
-
if https == True:
|
371
|
-
scheme = 'https'
|
372
|
-
port = '443'
|
373
|
-
proxy_mode_reverse_spec = f"reverse:{scheme}://{hostname}:8080"
|
374
|
-
|
375
|
-
result = runner.invoke(scaffold, ['service', 'create',
|
376
|
-
'--app-dir-path', app_dir_path,
|
377
|
-
'--force',
|
378
|
-
'--hostname', hostname,
|
379
|
-
'--scheme', scheme,
|
380
|
-
'--port', port,
|
381
|
-
'--proxy-mode', proxy_mode_reverse_spec,
|
382
|
-
'--detached',
|
383
|
-
'--workflow', 'test',
|
384
|
-
service_name
|
385
|
-
])
|
386
|
-
assert result.exit_code == 0
|
387
|
-
output = result.stdout
|
388
|
-
assert not output
|
389
|
-
|
390
|
-
@staticmethod
|
391
|
-
def cli_workflow_create(runner: CliRunner, app_dir_path: str, service_name: str):
|
392
|
-
result = runner.invoke(scaffold, ['workflow', 'create',
|
393
|
-
'--app-dir-path', app_dir_path,
|
394
|
-
'--service', service_name,
|
395
|
-
'--template', 'mock',
|
396
|
-
'ci',
|
397
|
-
])
|
398
|
-
|
399
|
-
assert result.exit_code == 0
|
400
|
-
output = result.stdout
|
401
|
-
assert not output
|
402
|
-
|
403
|
-
@staticmethod
|
404
|
-
def cli_workflow_run(runner: CliRunner, app_dir_path: str, target_workflow_name: str):
|
405
|
-
command = ['workflow', 'run',
|
406
|
-
'--app-dir-path', app_dir_path,
|
407
|
-
'--context-dir-path', app_dir_path,
|
408
|
-
target_workflow_name,
|
409
|
-
]
|
410
|
-
result = runner.invoke(scaffold, command)
|
411
|
-
|
412
|
-
assert result.exit_code == 0
|
413
|
-
output = result.stdout
|
414
|
-
assert output
|
415
|
-
|
416
|
-
@staticmethod
|
417
|
-
def cli_workflow_stop(runner: CliRunner, app_dir_path: str, target_workflow_name: str):
|
418
|
-
command = ['workflow', 'stop',
|
419
|
-
'--app-dir-path', app_dir_path,
|
420
|
-
'--context-dir-path', app_dir_path,
|
421
|
-
target_workflow_name,
|
422
|
-
]
|
423
|
-
result = runner.invoke(scaffold, command)
|
424
|
-
|
425
|
-
assert result.exit_code == 0
|
426
|
-
output = result.stdout
|
427
|
-
assert output
|
428
|
-
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import pdb
|
2
|
+
import pytest
|
3
|
+
|
4
|
+
from stoobly_agent.app.cli.scaffold.hosts_file_reader import HostsFileReader
|
5
|
+
|
6
|
+
|
7
|
+
class TestHostsFileReader():
|
8
|
+
|
9
|
+
@pytest.fixture
|
10
|
+
def hosts_file_reader(self):
|
11
|
+
yield HostsFileReader()
|
12
|
+
|
13
|
+
def test_get_hosts_file_path(self, hosts_file_reader):
|
14
|
+
hosts_file_path = hosts_file_reader._HostsFileReader__get_hosts_file_path()
|
15
|
+
|
16
|
+
# Test runners are all Linux distros for now
|
17
|
+
assert hosts_file_path == '/etc/hosts'
|
18
|
+
|
19
|
+
def test_get_hosts(self, hosts_file_reader):
|
20
|
+
hosts = hosts_file_reader.get_hosts()
|
21
|
+
|
22
|
+
assert hosts
|
23
|
+
assert len(hosts) > 1
|
24
|
+
|
25
|
+
localhost_found = False
|
26
|
+
for host in hosts:
|
27
|
+
if host.ip_address == '127.0.0.1' and 'localhost' in host.hostnames:
|
28
|
+
localhost_found = True
|
29
|
+
break
|
30
|
+
assert localhost_found
|
31
|
+
|
32
|
+
def test_find_host(self, hosts_file_reader):
|
33
|
+
url = 'localhost'
|
34
|
+
|
35
|
+
host = hosts_file_reader.find_host(url)
|
36
|
+
|
37
|
+
assert host
|
38
|
+
assert host.ip_address == '127.0.0.1'
|
39
|
+
assert 'localhost' in host.hostnames
|
40
|
+
|
41
|
+
|
42
|
+
class TestsSplitHostsLine():
|
43
|
+
def test_basic(self, hosts_file_reader):
|
44
|
+
line = '0.0.0.0 example.com'
|
45
|
+
split = hosts_file_reader._HostsFileReader__split_hosts_line(line)
|
46
|
+
|
47
|
+
assert split[0] == '0.0.0.0'
|
48
|
+
assert split[1] == 'example.com'
|
49
|
+
|
50
|
+
def test_tabs(self, hosts_file_reader):
|
51
|
+
line = '0.0.0.0\texample.com'
|
52
|
+
split = hosts_file_reader._HostsFileReader__split_hosts_line(line)
|
53
|
+
|
54
|
+
assert split[0] == '0.0.0.0'
|
55
|
+
assert split[1] == 'example.com'
|
56
|
+
|
57
|
+
def test_comment(self, hosts_file_reader):
|
58
|
+
line = '# 0.0.0.0 example.com'
|
59
|
+
split = hosts_file_reader._HostsFileReader__split_hosts_line(line)
|
60
|
+
|
61
|
+
assert len(split) == 0
|
62
|
+
|
63
|
+
def test_inline_comment(self, hosts_file_reader):
|
64
|
+
line = '0.0.0.0\texample.com # Comment'
|
65
|
+
split = hosts_file_reader._HostsFileReader__split_hosts_line(line)
|
66
|
+
|
67
|
+
assert split[0] == '0.0.0.0'
|
68
|
+
assert split[1] == 'example.com'
|
69
|
+
|
70
|
+
def test_multiple_hostnames(self, hosts_file_reader):
|
71
|
+
line = '0.0.0.0\texample.com example2.com example3.com # Comment'
|
72
|
+
split = hosts_file_reader._HostsFileReader__split_hosts_line(line)
|
73
|
+
|
74
|
+
assert split[0] == '0.0.0.0'
|
75
|
+
assert split[1] == 'example.com'
|
76
|
+
assert split[2] == 'example2.com'
|
77
|
+
assert split[3] == 'example3.com'
|
78
|
+
|
79
|
+
|
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.14
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: stoobly-agent
|
3
|
-
Version: 1.0
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: Record, mock, and test HTTP(s) requests. CLI agent for Stoobly
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: Matt Le
|
@@ -13,24 +13,23 @@ Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
14
14
|
Classifier: Programming Language :: Python :: 3.13
|
15
15
|
Requires-Dist: click (>=8.1.0,<9.0.0)
|
16
|
-
Requires-Dist: diff-match-patch (>=
|
17
|
-
Requires-Dist: distro (>=1.
|
18
|
-
Requires-Dist: dnspython (>=2.
|
16
|
+
Requires-Dist: diff-match-patch (>=v20241021,<20241022)
|
17
|
+
Requires-Dist: distro (>=1.9.0,<1.10)
|
18
|
+
Requires-Dist: dnspython (>=2.7.0,<2.8)
|
19
19
|
Requires-Dist: docker (>=7.1.0,<8.0)
|
20
20
|
Requires-Dist: httptools (>=0.4.0)
|
21
21
|
Requires-Dist: jmespath (>=1.0.0)
|
22
|
-
Requires-Dist: mergedeep (>=1.3
|
23
|
-
Requires-Dist: mitmproxy (>=
|
24
|
-
Requires-Dist: multipart (>=
|
22
|
+
Requires-Dist: mergedeep (>=1.3,<1.4)
|
23
|
+
Requires-Dist: mitmproxy (>=11.0.2,<11.1.0)
|
24
|
+
Requires-Dist: multipart (>=1.2.1,<1.3)
|
25
25
|
Requires-Dist: openapi-core (>=0.19.0,<0.20.0)
|
26
26
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
27
27
|
Requires-Dist: pyyaml (>=6.0.1)
|
28
28
|
Requires-Dist: requests (>=2.31.0)
|
29
29
|
Requires-Dist: stoobly_orator (>=0.9.12)
|
30
30
|
Requires-Dist: tabulate (>=0.8.8)
|
31
|
-
Requires-Dist: watchdog (>=
|
32
|
-
Requires-Dist:
|
33
|
-
Requires-Dist: yamale (>=4.0.0,<=4.0.2)
|
31
|
+
Requires-Dist: watchdog (>=6.0.0,<=6.1.0)
|
32
|
+
Requires-Dist: yamale (>=6.0.0,<=7.0.0)
|
34
33
|
Project-URL: Homepage, https://github.com/Stoobly/stoobly-agent
|
35
34
|
Description-Content-Type: text/markdown
|
36
35
|
|