stoobly-agent 0.34.13__py3-none-any.whl → 1.0.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/__init__.py +1 -0
- stoobly_agent/app/cli/helpers/openapi_endpoint_adapter.py +9 -7
- stoobly_agent/app/cli/helpers/shell.py +28 -0
- stoobly_agent/app/cli/main_group.py +1 -1
- stoobly_agent/app/cli/scaffold/__init__.py +0 -0
- stoobly_agent/app/cli/scaffold/app.py +106 -0
- stoobly_agent/app/cli/scaffold/app_command.py +82 -0
- stoobly_agent/app/cli/scaffold/app_config.py +32 -0
- stoobly_agent/app/cli/scaffold/app_create_command.py +24 -0
- stoobly_agent/app/cli/scaffold/command.py +15 -0
- stoobly_agent/app/cli/scaffold/config.py +35 -0
- stoobly_agent/app/cli/scaffold/constants.py +35 -0
- stoobly_agent/app/cli/scaffold/docker/__init__.py +0 -0
- stoobly_agent/app/cli/scaffold/docker/app_builder.py +26 -0
- stoobly_agent/app/cli/scaffold/docker/builder.py +117 -0
- stoobly_agent/app/cli/scaffold/docker/constants.py +7 -0
- stoobly_agent/app/cli/scaffold/docker/service/__init__.py +0 -0
- stoobly_agent/app/cli/scaffold/docker/service/build_decorator.py +37 -0
- stoobly_agent/app/cli/scaffold/docker/service/builder.py +117 -0
- stoobly_agent/app/cli/scaffold/docker/service/set_gateway_ports.py +47 -0
- stoobly_agent/app/cli/scaffold/docker/service/types.py +4 -0
- stoobly_agent/app/cli/scaffold/docker/workflow/__init__.py +0 -0
- stoobly_agent/app/cli/scaffold/docker/workflow/build_decorator.py +28 -0
- stoobly_agent/app/cli/scaffold/docker/workflow/builder.py +259 -0
- stoobly_agent/app/cli/scaffold/docker/workflow/decorators_factory.py +17 -0
- stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +40 -0
- stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py +51 -0
- stoobly_agent/app/cli/scaffold/env.py +49 -0
- stoobly_agent/app/cli/scaffold/service.py +25 -0
- stoobly_agent/app/cli/scaffold/service_command.py +50 -0
- stoobly_agent/app/cli/scaffold/service_config.py +207 -0
- stoobly_agent/app/cli/scaffold/service_create_command.py +77 -0
- stoobly_agent/app/cli/scaffold/service_workflow.py +18 -0
- stoobly_agent/app/cli/scaffold/templates/__init__.py +0 -0
- stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context +8 -0
- stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.proxy +35 -0
- stoobly_agent/app/cli/scaffold/templates/app/.Makefile +118 -0
- stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml +15 -0
- stoobly_agent/app/cli/scaffold/templates/app/Makefile +3 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/.config.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/.docker-compose.base.yml +11 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/mock/.docker-compose.mock.yml +22 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/.configure +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/.init +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/configure +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/init +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/record/.docker-compose.record.yml +22 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/.configure +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/.init +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/configure +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/init +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/test/.docker-compose.test.yml +22 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/.configure +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/.init +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/configure +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/init +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/.config.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/.docker-compose.base.yml +17 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/.docker-compose.mock.yml +31 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/.configure +10 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/.init +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/configure +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/init +4 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/docker-compose.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/.docker-compose.record.yml +31 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/.configure +10 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/.init +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/configure +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/init +4 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/docker-compose.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/.docker-compose.test.yml +31 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/.configure +10 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/.init +3 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/configure +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/init +4 -0
- stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/docker-compose.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/gateway/.config.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/gateway/.docker-compose.base.yml +11 -0
- stoobly_agent/app/cli/scaffold/templates/app/gateway/mock/.docker-compose.mock.yml +13 -0
- stoobly_agent/app/cli/scaffold/templates/app/gateway/record/.docker-compose.record.yml +13 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/.config.yml +1 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/.docker-compose.base.yml +5 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/.docker-compose.exec.yml +12 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.create +11 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.delete +12 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.disable +3 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.enable +10 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.reset +12 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.run +11 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.snapshot +12 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.stop +11 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/mock/.docker-compose.mock.yml +12 -0
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/record/.docker-compose.record.yml +13 -0
- stoobly_agent/app/cli/scaffold/templates/constants.py +63 -0
- stoobly_agent/app/cli/scaffold/templates/factory.py +46 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/.configure +3 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/.init +3 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/configure +18 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/init +4 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/fixtures/.keep +0 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/fixtures.yml +5 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/mock/lifecycle_hooks.py +12 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/.configure +3 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/.init +3 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/configure +29 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/init +4 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/record/lifecycle_hooks.py +12 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/.configure +3 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/.init +3 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/configure +18 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/init +4 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures/.keep +0 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures.yml +5 -0
- stoobly_agent/app/cli/scaffold/templates/workflow/test/lifecycle_hooks.py +12 -0
- stoobly_agent/app/cli/scaffold/workflow.py +49 -0
- stoobly_agent/app/cli/scaffold/workflow_command.py +137 -0
- stoobly_agent/app/cli/scaffold/workflow_copy_command.py +45 -0
- stoobly_agent/app/cli/scaffold/workflow_create_command.py +94 -0
- stoobly_agent/app/cli/scaffold/workflow_log_command.py +21 -0
- stoobly_agent/app/cli/scaffold/workflow_run_command.py +134 -0
- stoobly_agent/app/cli/scaffold_cli.py +392 -0
- stoobly_agent/cli.py +3 -2
- stoobly_agent/config/data_dir.py +40 -14
- stoobly_agent/lib/logger.py +3 -2
- stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
- stoobly_agent/test/config/data_dir_test.py +4 -4
- {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.0.dist-info}/METADATA +8 -7
- {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.0.dist-info}/RECORD +132 -14
- {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.0.dist-info}/WHEEL +1 -1
- {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.0.dist-info}/LICENSE +0 -0
- {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
# Wraps the .config.yml file in the service folder
|
2
|
+
|
3
|
+
import dns.resolver
|
4
|
+
import pdb
|
5
|
+
import subprocess
|
6
|
+
import re
|
7
|
+
|
8
|
+
from .config import Config
|
9
|
+
from .constants import (
|
10
|
+
SERVICE_DETACHED_ENV,
|
11
|
+
SERVICE_DOCKER_COMPOSE_PATH_ENV,
|
12
|
+
SERVICE_HOSTNAME_ENV,
|
13
|
+
SERVICE_DNS_ENV,
|
14
|
+
SERVICE_PRIORITY_ENV,
|
15
|
+
SERVICE_PORT_ENV,
|
16
|
+
SERVICE_PROXY_MODE_ENV,
|
17
|
+
SERVICE_SCHEME_ENV
|
18
|
+
)
|
19
|
+
|
20
|
+
class ServiceConfig(Config):
|
21
|
+
|
22
|
+
def __init__(self, dir: str, **kwargs):
|
23
|
+
super().__init__(dir)
|
24
|
+
|
25
|
+
self.__detached = None
|
26
|
+
self.__docker_compose_path = None
|
27
|
+
self.__hostname = None
|
28
|
+
self.__dns = None
|
29
|
+
self.__port = None
|
30
|
+
self.__priority = None
|
31
|
+
self.__proxy_mode = None
|
32
|
+
self.__scheme = None
|
33
|
+
|
34
|
+
self.load()
|
35
|
+
|
36
|
+
if 'detached' in kwargs:
|
37
|
+
self.__detached = bool(kwargs.get('detached'))
|
38
|
+
|
39
|
+
if 'hostname' in kwargs:
|
40
|
+
self.__hostname = kwargs.get('hostname')
|
41
|
+
|
42
|
+
if 'port' in kwargs:
|
43
|
+
self.__port = kwargs.get('port')
|
44
|
+
|
45
|
+
if 'priority' in kwargs:
|
46
|
+
self.__priority = kwargs.get('priority')
|
47
|
+
|
48
|
+
if 'proxy_mode' in kwargs:
|
49
|
+
self.__proxy_mode = kwargs.get('proxy_mode')
|
50
|
+
|
51
|
+
if 'scheme' in kwargs:
|
52
|
+
self.__scheme = kwargs.get('scheme')
|
53
|
+
|
54
|
+
@property
|
55
|
+
def detached(self):
|
56
|
+
return self.__detached
|
57
|
+
|
58
|
+
@detached.setter
|
59
|
+
def detached(self, v):
|
60
|
+
self.__detached = v
|
61
|
+
|
62
|
+
@property
|
63
|
+
def docker_compose_path(self):
|
64
|
+
return self.__docker_compose_path
|
65
|
+
|
66
|
+
@docker_compose_path.setter
|
67
|
+
def docker_compose_path(self, v):
|
68
|
+
self.__docker_compose_path = v
|
69
|
+
|
70
|
+
@property
|
71
|
+
def hostname(self):
|
72
|
+
return self.__hostname
|
73
|
+
|
74
|
+
@hostname.setter
|
75
|
+
def hostname(self, v):
|
76
|
+
self.__hostname = v
|
77
|
+
|
78
|
+
@property
|
79
|
+
def dns(self):
|
80
|
+
# If hostname is set then the service is external and we will need to configure the container's DNS.
|
81
|
+
# If we don't configure the container's DNS, then Docker's embedded DNS will potentially
|
82
|
+
# use configuration from the host's /etc/hosts file. The user may have configured their
|
83
|
+
# /etc/hosts file to resolve requests to localhost
|
84
|
+
#
|
85
|
+
# See:
|
86
|
+
# https://forums.docker.com/t/docker-127-0-0-11-resolver-should-use-host-etc-hosts-file/55157
|
87
|
+
# https://docs.docker.com/network/#dns-services
|
88
|
+
#
|
89
|
+
# TODO: ideally we want to know if the service is built locally, if so, then no need to set DNS
|
90
|
+
# since Docker's embedded DNS will resolve to it
|
91
|
+
if self.hostname and not self.__dns:
|
92
|
+
nameservers = self.__find_dns()
|
93
|
+
self.__dns = nameservers[0] if nameservers else None
|
94
|
+
return self.__dns
|
95
|
+
|
96
|
+
@dns.setter
|
97
|
+
def dns(self, v):
|
98
|
+
self.__dns = v
|
99
|
+
|
100
|
+
@property
|
101
|
+
def port(self):
|
102
|
+
return self.__port
|
103
|
+
|
104
|
+
@port.setter
|
105
|
+
def port(self, v):
|
106
|
+
self.__port = v
|
107
|
+
|
108
|
+
@property
|
109
|
+
def priority(self):
|
110
|
+
_priority = self.__priority
|
111
|
+
_priority = float('inf') if _priority == None else float(_priority)
|
112
|
+
|
113
|
+
if _priority == float('inf'):
|
114
|
+
return _priority
|
115
|
+
|
116
|
+
return float(_priority)
|
117
|
+
|
118
|
+
@priority.setter
|
119
|
+
def priority(self, v):
|
120
|
+
self.__priority = v
|
121
|
+
|
122
|
+
@property
|
123
|
+
def proxy_mode(self):
|
124
|
+
if self.__proxy_mode:
|
125
|
+
return self.__proxy_mode
|
126
|
+
|
127
|
+
return f"reverse:{self.scheme}://{self.hostname}"
|
128
|
+
|
129
|
+
@proxy_mode.setter
|
130
|
+
def proxy_mode(self, v):
|
131
|
+
self.__proxy_mode = v
|
132
|
+
|
133
|
+
@property
|
134
|
+
def scheme(self):
|
135
|
+
return self.__scheme or 'https'
|
136
|
+
|
137
|
+
@scheme.setter
|
138
|
+
def scheme(self, v):
|
139
|
+
self.__scheme = v
|
140
|
+
|
141
|
+
def load(self, config = None):
|
142
|
+
config = config or self.read()
|
143
|
+
|
144
|
+
# Do not load dns from config, have it dynamically determined
|
145
|
+
#self.dns = config.get(SERVICE_DNS_ENV)
|
146
|
+
|
147
|
+
self.detached = config.get(SERVICE_DETACHED_ENV)
|
148
|
+
self.docker_compose_path = config.get(SERVICE_DOCKER_COMPOSE_PATH_ENV)
|
149
|
+
self.hostname = config.get(SERVICE_HOSTNAME_ENV)
|
150
|
+
self.port = config.get(SERVICE_PORT_ENV)
|
151
|
+
self.priority = config.get(SERVICE_PRIORITY_ENV)
|
152
|
+
self.proxy_mode = config.get(SERVICE_PROXY_MODE_ENV)
|
153
|
+
self.scheme = config.get(SERVICE_SCHEME_ENV)
|
154
|
+
|
155
|
+
def write(self):
|
156
|
+
config = {}
|
157
|
+
|
158
|
+
if self.docker_compose_path:
|
159
|
+
config[SERVICE_DOCKER_COMPOSE_PATH_ENV] = self.docker_compose_path
|
160
|
+
|
161
|
+
if self.hostname:
|
162
|
+
config[SERVICE_HOSTNAME_ENV] = self.hostname
|
163
|
+
|
164
|
+
if self.dns:
|
165
|
+
config[SERVICE_DNS_ENV] = self.dns
|
166
|
+
|
167
|
+
if self.port:
|
168
|
+
config[SERVICE_PORT_ENV] = self.port
|
169
|
+
|
170
|
+
if self.priority:
|
171
|
+
config[SERVICE_PRIORITY_ENV] = self.priority
|
172
|
+
|
173
|
+
if self.scheme:
|
174
|
+
config[SERVICE_SCHEME_ENV] = self.scheme
|
175
|
+
|
176
|
+
config[SERVICE_DETACHED_ENV] = bool(self.detached)
|
177
|
+
|
178
|
+
config[SERVICE_PROXY_MODE_ENV] = self.proxy_mode
|
179
|
+
|
180
|
+
super().write(config)
|
181
|
+
|
182
|
+
def __find_dns(self):
|
183
|
+
dns_resolver = dns.resolver.Resolver()
|
184
|
+
nameservers = dns_resolver.nameservers
|
185
|
+
|
186
|
+
# If systemd-resolved is not used
|
187
|
+
if nameservers != ['127.0.0.53']:
|
188
|
+
return nameservers
|
189
|
+
|
190
|
+
# Run the `resolvectl status` command and capture its output
|
191
|
+
result = subprocess.run(['resolvectl', 'status'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
192
|
+
|
193
|
+
# Check if the command ran successfully
|
194
|
+
if result.returncode != 0:
|
195
|
+
return []
|
196
|
+
|
197
|
+
# Extract the DNS servers using a regular expression
|
198
|
+
#dns_servers = re.findall(r'DNS Servers: ([\d.]+(?:, [\d.]+)*)', result.stdout)
|
199
|
+
pattern = re.compile('DNS Servers:(.*?)DNS Domain', re.DOTALL)
|
200
|
+
match = re.findall(pattern, result.stdout)
|
201
|
+
|
202
|
+
if not match:
|
203
|
+
return []
|
204
|
+
|
205
|
+
# Split the DNS servers string into a list
|
206
|
+
dns_servers = match[0].strip().split("\n")
|
207
|
+
return list(map(lambda dns_server: dns_server.strip(), dns_servers))
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import os
|
2
|
+
import pdb
|
3
|
+
import shutil
|
4
|
+
|
5
|
+
from .app import App
|
6
|
+
from .constants import WORKFLOW_MOCK_TYPE, WORKFLOW_RECORD_TYPE, WORKFLOW_TEST_TYPE
|
7
|
+
from .docker.service.builder import ServiceBuilder
|
8
|
+
from .docker.workflow.decorators_factory import get_workflow_decorators
|
9
|
+
from .service_command import ServiceCommand
|
10
|
+
from .workflow_create_command import WorkflowCreateCommand
|
11
|
+
|
12
|
+
class ServiceCreateCommand(ServiceCommand):
|
13
|
+
|
14
|
+
def __init__(self, app: App, **kwargs):
|
15
|
+
super().__init__(app, **kwargs)
|
16
|
+
|
17
|
+
self.__env_vars = kwargs.get('env') or []
|
18
|
+
self.__workflows = kwargs.get('workflow') or []
|
19
|
+
|
20
|
+
@property
|
21
|
+
def env_vars(self):
|
22
|
+
return self.__env_vars
|
23
|
+
|
24
|
+
@property
|
25
|
+
def workflows(self):
|
26
|
+
return self.__workflows
|
27
|
+
|
28
|
+
def build(self):
|
29
|
+
service_builder = ServiceBuilder(self.service_config)
|
30
|
+
service_decorators = []
|
31
|
+
|
32
|
+
for service_decorator in service_decorators:
|
33
|
+
service_decorator(service_builder).decorate()
|
34
|
+
|
35
|
+
service_builder.write()
|
36
|
+
|
37
|
+
workflow_kwargs = {
|
38
|
+
'app_dir_path': self.app_dir_path,
|
39
|
+
'env': self.env_vars,
|
40
|
+
'namespace': self.namespace,
|
41
|
+
'service_name': self.service_name,
|
42
|
+
}
|
43
|
+
|
44
|
+
if WORKFLOW_MOCK_TYPE in self.workflows:
|
45
|
+
self.__build_with_mock_workflow(service_builder, **workflow_kwargs)
|
46
|
+
|
47
|
+
if WORKFLOW_RECORD_TYPE in self.workflows:
|
48
|
+
self.__build_with_record_workflow(service_builder, **workflow_kwargs)
|
49
|
+
|
50
|
+
if WORKFLOW_TEST_TYPE in self.workflows:
|
51
|
+
self.__build_with_test_workflow(service_builder, **workflow_kwargs)
|
52
|
+
|
53
|
+
self.service_config.write()
|
54
|
+
|
55
|
+
def reset(self):
|
56
|
+
dest = self.service_path
|
57
|
+
|
58
|
+
if os.path.exists(dest):
|
59
|
+
shutil.rmtree(dest)
|
60
|
+
|
61
|
+
def __build_with_mock_workflow(self, service_builder: ServiceBuilder, **kwargs):
|
62
|
+
mock_workflow = WorkflowCreateCommand(self.app, **{ **kwargs, **{ 'workflow_name': WORKFLOW_MOCK_TYPE }})
|
63
|
+
|
64
|
+
workflow_decorators = get_workflow_decorators(WORKFLOW_MOCK_TYPE, self.service_config)
|
65
|
+
mock_workflow.build(service_builder=service_builder, workflow_decorators=workflow_decorators)
|
66
|
+
|
67
|
+
def __build_with_record_workflow(self, service_builder: ServiceBuilder, **kwargs):
|
68
|
+
record_workflow = WorkflowCreateCommand(self.app, **{ **kwargs, **{ 'workflow_name': WORKFLOW_RECORD_TYPE }})
|
69
|
+
|
70
|
+
workflow_decorators = get_workflow_decorators(WORKFLOW_RECORD_TYPE, self.service_config)
|
71
|
+
record_workflow.build(service_builder=service_builder, workflow_decorators=workflow_decorators)
|
72
|
+
|
73
|
+
def __build_with_test_workflow(self, service_builder: ServiceBuilder, **kwargs):
|
74
|
+
mock_workflow = WorkflowCreateCommand(self.app, **{ **kwargs, **{ 'workflow_name': WORKFLOW_TEST_TYPE }})
|
75
|
+
|
76
|
+
workflow_decorators = get_workflow_decorators(WORKFLOW_TEST_TYPE, self.service_config)
|
77
|
+
mock_workflow.build(service_builder=service_builder, workflow_decorators=workflow_decorators)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from .app import App
|
4
|
+
from .workflow import Workflow
|
5
|
+
|
6
|
+
class ServiceWorkflow(Workflow):
|
7
|
+
|
8
|
+
def __init__(self, service_name: str, workflow_name: str, app: App):
|
9
|
+
super().__init__(workflow_name, app)
|
10
|
+
self._service_name = service_name
|
11
|
+
|
12
|
+
@property
|
13
|
+
def path(self):
|
14
|
+
return os.path.join(self.app.scaffold_namespace_path, self.service_name, self.workflow_name)
|
15
|
+
|
16
|
+
@property
|
17
|
+
def service_name(self):
|
18
|
+
return self._service_name
|
File without changes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
FROM ubuntu:23.10 AS build
|
2
|
+
|
3
|
+
WORKDIR /tmp
|
4
|
+
|
5
|
+
RUN apt-get update && apt-get install -y curl
|
6
|
+
RUN curl -JLO "https://dl.filippo.io/mkcert/v1.4.4?for=linux/amd64" && \
|
7
|
+
chmod +x mkcert-v1.4.4-linux-amd64
|
8
|
+
|
9
|
+
FROM ubuntu:23.10 AS cert
|
10
|
+
|
11
|
+
ARG SERVICE_HOSTNAME
|
12
|
+
|
13
|
+
COPY --from=build /tmp/mkcert-v1.4.4-linux-amd64 /bin/mkcert
|
14
|
+
|
15
|
+
RUN useradd -m mkcert
|
16
|
+
|
17
|
+
USER mkcert
|
18
|
+
WORKDIR /home/mkcert
|
19
|
+
|
20
|
+
RUN mkcert $SERVICE_HOSTNAME && mkcert -pkcs12 $SERVICE_HOSTNAME && cat $SERVICE_HOSTNAME.pem >> $SERVICE_HOSTNAME-joined.pem && cat $SERVICE_HOSTNAME-key.pem >> $SERVICE_HOSTNAME-joined.pem
|
21
|
+
|
22
|
+
FROM stoobly/agent:0.34
|
23
|
+
|
24
|
+
ARG USER_ID
|
25
|
+
ARG SERVICE_HOSTNAME
|
26
|
+
|
27
|
+
# Allow running stoobly on port 443
|
28
|
+
RUN apt-get update && apt-get install -y curl libcap2-bin
|
29
|
+
RUN setcap 'cap_net_bind_service=+ep' /usr/local/bin/python3.8
|
30
|
+
|
31
|
+
# Change user id of stoobly user to that of host's user id
|
32
|
+
RUN if [ -n "$USER_ID" ]; then groupmod -g $USER_ID stoobly; usermod -u $USER_ID stoobly; fi
|
33
|
+
|
34
|
+
COPY --chown=stoobly:stoobly . .
|
35
|
+
COPY --chown=stoobly:stoobly --from=cert /home/mkcert/$SERVICE_HOSTNAME-joined.pem .
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# Overridable Environment Variables
|
2
|
+
#
|
3
|
+
# STOOBLY_APP_DIR: path to the application source code directory
|
4
|
+
# STOOBLY_CONTEXT_DIR: path to the folder containing the .stoobly folder
|
5
|
+
# STOOBLY_CERTS_DIR: path to a folder to store certs
|
6
|
+
# STOOBLY_WORKFLOW_RUN_OPTIONS: extra options to pass to 'stoobly-agent scaffold workflow run' command
|
7
|
+
|
8
|
+
# Constants
|
9
|
+
DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
10
|
+
WORKFLOW_NAME := exec
|
11
|
+
|
12
|
+
CONTEXT_DIR_DEFAULT := $(realpath $(DIR)/../..)
|
13
|
+
|
14
|
+
# Configuration
|
15
|
+
app_dir=$$(realpath "$${STOOBLY_APP_DIR:-$(CONTEXT_DIR_DEFAULT)}")
|
16
|
+
certs_dir=$$(realpath "$${STOOBLY_CERTS_DIR:-$(app_data_dir)/certs}")
|
17
|
+
context_dir=$$(realpath "$${STOOBLY_CONTEXT_DIR:-$(CONTEXT_DIR_DEFAULT)}")
|
18
|
+
workflow_run_options=$${STOOBLY_WORKFLOW_RUN_OPTIONS:+$$STOOBLY_WORKFLOW_RUN_OPTIONS }
|
19
|
+
|
20
|
+
app_data_dir=$(app_dir)/.stoobly
|
21
|
+
data_dir=$(context_dir)/.stoobly
|
22
|
+
|
23
|
+
# Commands
|
24
|
+
docker_compose_command=docker compose
|
25
|
+
source_env=set -a; [ -f .env ] && source .env; set +a
|
26
|
+
|
27
|
+
docker_compose_file_path=$(app_data_dir)/docker/stoobly-ui/exec/.docker-compose.exec.yml
|
28
|
+
stoobly_exec_args=--profile $(WORKFLOW_NAME) -p $(WORKFLOW_NAME) up --build --remove-orphans
|
29
|
+
stoobly_exec_env=export CONTEXT_DIR=$(context_dir) && export USER_ID=$$UID
|
30
|
+
stoobly_exec=$(stoobly_exec_env) && $(source_env) && $(docker_compose_command) -f "$(docker_compose_file_path)" $(stoobly_exec_args)
|
31
|
+
|
32
|
+
# Because scaffold is stored in the APP_DIR, when running a scaffold command from within a container,
|
33
|
+
# it needs access to APP_DIR rather than CONTEXT_DIR
|
34
|
+
stoobly_exec_run_env=export USER_ID=$$UID
|
35
|
+
stoobly_exec_run=$(stoobly_exec_run_env) && $(source_env) && CONTEXT_DIR=$(app_dir) $(docker_compose_command) -f "$(docker_compose_file_path)" $(stoobly_exec_args)
|
36
|
+
|
37
|
+
run_script=$(app_data_dir)/tmp/run.sh
|
38
|
+
run_env=export APP_DIR="$(app_dir)" && export CERTS_DIR="$(certs_dir)" && export CONTEXT_DIR="$(context_dir)"
|
39
|
+
workflow_run=$(run_env) && $(source_env) && bash "$(run_script)"
|
40
|
+
|
41
|
+
cert:
|
42
|
+
if [ -z "$$(which mkcert)" ]; then \
|
43
|
+
echo "Error: missing mkcert command"; \
|
44
|
+
else \
|
45
|
+
mkdir -p "$(certs_dir)" && \
|
46
|
+
cd "$(certs_dir)" && \
|
47
|
+
mkcert --install && \
|
48
|
+
mkcert $(hostname) && \
|
49
|
+
cp $(hostname).pem $(hostname).crt && \
|
50
|
+
cp $(hostname)-key.pem $(hostname).key; \
|
51
|
+
fi
|
52
|
+
intercept/disable:
|
53
|
+
export EXEC_COMMAND=bin/.disable && \
|
54
|
+
$(stoobly_exec)
|
55
|
+
intercept/enable:
|
56
|
+
export EXEC_COMMAND=bin/.enable && \
|
57
|
+
export EXEC_ARGS=$(scenario_key) && \
|
58
|
+
$(stoobly_exec)
|
59
|
+
mock:
|
60
|
+
export EXEC_COMMAND=bin/.run && \
|
61
|
+
export EXEC_OPTIONS="$(workflow_run_options)$(options)" && \
|
62
|
+
export EXEC_ARGS="mock" && \
|
63
|
+
$(stoobly_exec_run) && \
|
64
|
+
$(workflow_run)
|
65
|
+
mock/stop:
|
66
|
+
export EXEC_COMMAND=bin/.stop && \
|
67
|
+
export EXEC_OPTIONS="$(options)" && \
|
68
|
+
export EXEC_ARGS="mock" && \
|
69
|
+
$(stoobly_exec_run) && \
|
70
|
+
$(workflow_run)
|
71
|
+
record:
|
72
|
+
export EXEC_COMMAND=bin/.run && \
|
73
|
+
export EXEC_OPTIONS="$(workflow_run_options)$(options)" && \
|
74
|
+
export EXEC_ARGS="record" && \
|
75
|
+
$(stoobly_exec_run) && \
|
76
|
+
$(workflow_run)
|
77
|
+
record/stop:
|
78
|
+
export EXEC_COMMAND=bin/.stop && \
|
79
|
+
export EXEC_OPTIONS="$(options)" && \
|
80
|
+
export EXEC_ARGS="record" && \
|
81
|
+
$(stoobly_exec_run) && \
|
82
|
+
$(workflow_run)
|
83
|
+
scenario/create:
|
84
|
+
# Create a scenario
|
85
|
+
export EXEC_COMMAND=bin/.create && \
|
86
|
+
export EXEC_OPTIONS="$(options)" && \
|
87
|
+
export EXEC_ARGS="$(name)" && \
|
88
|
+
$(stoobly_exec)
|
89
|
+
scenario/delete:
|
90
|
+
# Delete a scenario
|
91
|
+
export EXEC_COMMAND=bin/.delete && \
|
92
|
+
export EXEC_OPTIONS="$(options)" && \
|
93
|
+
export EXEC_ARGS="$(key)" && \
|
94
|
+
$(stoobly_exec)
|
95
|
+
scenario/reset:
|
96
|
+
# Resets a scenario to its last snapshot
|
97
|
+
export EXEC_COMMAND=bin/.reset && \:
|
98
|
+
export EXEC_OPTIONS="$(options)" && \
|
99
|
+
export EXEC_ARGS="$(key)" && \
|
100
|
+
$(stoobly_exec)
|
101
|
+
scenario/snapshot:
|
102
|
+
# Create committable files for a scenario
|
103
|
+
export EXEC_COMMAND=bin/.snapshot && \
|
104
|
+
export EXEC_OPTIONS="$(options)" && \
|
105
|
+
export EXEC_ARGS="$(key)" && \
|
106
|
+
$(stoobly_exec)
|
107
|
+
test:
|
108
|
+
export EXEC_COMMAND=bin/.run && \
|
109
|
+
export EXEC_OPTIONS="$(workflow_run_options)$(options)" && \
|
110
|
+
export EXEC_ARGS="test" && \
|
111
|
+
$(stoobly_exec_run) && \
|
112
|
+
$(workflow_run)
|
113
|
+
test/stop:
|
114
|
+
export EXEC_COMMAND=bin/.stop && \
|
115
|
+
export EXEC_OPTIONS="$(options)" && \
|
116
|
+
export EXEC_ARGS="test" && \
|
117
|
+
$(stoobly_exec_run) && \
|
118
|
+
$(workflow_run)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
services:
|
2
|
+
context_base:
|
3
|
+
build:
|
4
|
+
args:
|
5
|
+
USER_ID: ${USER_ID}
|
6
|
+
dockerfile: ./.Dockerfile.context
|
7
|
+
volumes:
|
8
|
+
- ${CONTEXT_DIR}/.stoobly:/home/stoobly/.stoobly
|
9
|
+
proxy_base:
|
10
|
+
build:
|
11
|
+
args:
|
12
|
+
USER_ID: ${USER_ID}
|
13
|
+
dockerfile: ./.Dockerfile.proxy
|
14
|
+
volumes:
|
15
|
+
- ${CONTEXT_DIR}/.stoobly:/home/stoobly/.stoobly
|
@@ -0,0 +1 @@
|
|
1
|
+
SERVICE_PRIORITY: 0
|
@@ -0,0 +1,22 @@
|
|
1
|
+
services:
|
2
|
+
build.init:
|
3
|
+
build:
|
4
|
+
context: ./
|
5
|
+
dockerfile: ../../.Dockerfile.context
|
6
|
+
extends:
|
7
|
+
file: ../.docker-compose.base.yml
|
8
|
+
service: build.init_base
|
9
|
+
profiles:
|
10
|
+
- mock
|
11
|
+
build.configure:
|
12
|
+
build:
|
13
|
+
context: ./
|
14
|
+
dockerfile: ../../.Dockerfile.context
|
15
|
+
depends_on:
|
16
|
+
build.init:
|
17
|
+
condition: service_completed_successfully
|
18
|
+
extends:
|
19
|
+
file: ../.docker-compose.base.yml
|
20
|
+
service: build.configure_base
|
21
|
+
profiles:
|
22
|
+
- mock
|
@@ -0,0 +1 @@
|
|
1
|
+
#!/bin/bash
|
@@ -0,0 +1 @@
|
|
1
|
+
#! /bin/bash
|
@@ -0,0 +1,22 @@
|
|
1
|
+
services:
|
2
|
+
build.init:
|
3
|
+
build:
|
4
|
+
context: ./
|
5
|
+
dockerfile: ../../.Dockerfile.context
|
6
|
+
extends:
|
7
|
+
file: ../.docker-compose.base.yml
|
8
|
+
service: build.init_base
|
9
|
+
profiles:
|
10
|
+
- record
|
11
|
+
build.configure:
|
12
|
+
build:
|
13
|
+
context: ./
|
14
|
+
dockerfile: ../../.Dockerfile.context
|
15
|
+
depends_on:
|
16
|
+
build.init:
|
17
|
+
condition: service_completed_successfully
|
18
|
+
extends:
|
19
|
+
file: ../.docker-compose.base.yml
|
20
|
+
service: build.configure_base
|
21
|
+
profiles:
|
22
|
+
- record
|
@@ -0,0 +1 @@
|
|
1
|
+
#!/bin/bash
|
@@ -0,0 +1 @@
|
|
1
|
+
#! /bin/bash
|
@@ -0,0 +1,22 @@
|
|
1
|
+
services:
|
2
|
+
build.init:
|
3
|
+
build:
|
4
|
+
context: ./
|
5
|
+
dockerfile: ../../.Dockerfile.context
|
6
|
+
extends:
|
7
|
+
file: ../.docker-compose.base.yml
|
8
|
+
service: build.init_base
|
9
|
+
profiles:
|
10
|
+
- test
|
11
|
+
build.configure:
|
12
|
+
build:
|
13
|
+
context: ./
|
14
|
+
dockerfile: ../../.Dockerfile.context
|
15
|
+
depends_on:
|
16
|
+
build.init:
|
17
|
+
condition: service_completed_successfully
|
18
|
+
extends:
|
19
|
+
file: ../.docker-compose.base.yml
|
20
|
+
service: build.configure_base
|
21
|
+
profiles:
|
22
|
+
- test
|
@@ -0,0 +1 @@
|
|
1
|
+
#!/bin/bash
|
@@ -0,0 +1 @@
|
|
1
|
+
#! /bin/bash
|
@@ -0,0 +1 @@
|
|
1
|
+
SERVICE_PRIORITY: 10.0
|
@@ -0,0 +1,17 @@
|
|
1
|
+
networks: {}
|
2
|
+
services:
|
3
|
+
entrypoint.configure_base:
|
4
|
+
command:
|
5
|
+
- bin/.configure
|
6
|
+
environment: {}
|
7
|
+
extends:
|
8
|
+
file: ../.docker-compose.base.yml
|
9
|
+
service: context_base
|
10
|
+
entrypoint.init_base:
|
11
|
+
command:
|
12
|
+
- bin/.init
|
13
|
+
- dist
|
14
|
+
environment: {}
|
15
|
+
extends:
|
16
|
+
file: ../.docker-compose.base.yml
|
17
|
+
service: context_base
|