stoobly-agent 1.10.0__py3-none-any.whl → 1.10.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.
Files changed (173) hide show
  1. stoobly_agent/__init__.py +1 -1
  2. stoobly_agent/__main__.py +10 -0
  3. stoobly_agent/app/api/application_http_request_handler.py +5 -2
  4. stoobly_agent/app/cli/ca_cert_cli.py +9 -5
  5. stoobly_agent/app/cli/helpers/replay_facade.py +2 -2
  6. stoobly_agent/app/cli/intercept_cli.py +5 -5
  7. stoobly_agent/app/cli/request_cli.py +2 -2
  8. stoobly_agent/app/cli/scaffold/app.py +14 -5
  9. stoobly_agent/app/cli/scaffold/app_command.py +0 -4
  10. stoobly_agent/app/cli/scaffold/app_config.py +49 -2
  11. stoobly_agent/app/cli/scaffold/app_create_command.py +145 -76
  12. stoobly_agent/app/cli/scaffold/constants.py +9 -4
  13. stoobly_agent/app/cli/scaffold/docker/constants.py +3 -1
  14. stoobly_agent/app/cli/scaffold/docker/service/build_decorator.py +4 -4
  15. stoobly_agent/app/cli/scaffold/docker/service/builder.py +31 -54
  16. stoobly_agent/app/cli/scaffold/docker/service/configure_gateway.py +3 -0
  17. stoobly_agent/app/cli/scaffold/docker/template_files.py +112 -0
  18. stoobly_agent/app/cli/scaffold/docker/workflow/build_decorator.py +1 -1
  19. stoobly_agent/app/cli/scaffold/docker/workflow/builder.py +30 -47
  20. stoobly_agent/app/cli/scaffold/docker/workflow/command_decorator.py +3 -2
  21. stoobly_agent/app/cli/scaffold/docker/workflow/detached_decorator.py +1 -1
  22. stoobly_agent/app/cli/scaffold/docker/workflow/dns_decorator.py +2 -3
  23. stoobly_agent/app/cli/scaffold/docker/workflow/local_decorator.py +1 -1
  24. stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +1 -1
  25. stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py +1 -1
  26. stoobly_agent/app/cli/scaffold/docker/workflow/run_command.py +423 -0
  27. stoobly_agent/app/cli/scaffold/local/__init__.py +0 -0
  28. stoobly_agent/app/cli/scaffold/local/service/__init__.py +0 -0
  29. stoobly_agent/app/cli/scaffold/local/service/builder.py +72 -0
  30. stoobly_agent/app/cli/scaffold/local/workflow/__init__.py +0 -0
  31. stoobly_agent/app/cli/scaffold/local/workflow/builder.py +35 -0
  32. stoobly_agent/app/cli/scaffold/local/workflow/run_command.py +339 -0
  33. stoobly_agent/app/cli/scaffold/service_command.py +9 -1
  34. stoobly_agent/app/cli/scaffold/service_config.py +9 -25
  35. stoobly_agent/app/cli/scaffold/service_create_command.py +18 -6
  36. stoobly_agent/app/cli/scaffold/service_docker_compose.py +3 -3
  37. stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py +10 -7
  38. stoobly_agent/app/cli/scaffold/templates/app/.Makefile +2 -2
  39. stoobly_agent/app/cli/scaffold/templates/app/build/.docker-compose.base.yml +4 -4
  40. stoobly_agent/app/cli/scaffold/templates/app/build/mock/configure +3 -0
  41. stoobly_agent/app/cli/scaffold/templates/app/build/record/configure +28 -0
  42. stoobly_agent/app/cli/scaffold/templates/app/build/test/configure +3 -0
  43. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/.docker-compose.base.yml +4 -4
  44. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/configure +3 -0
  45. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/run +3 -0
  46. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/configure +3 -0
  47. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/run +3 -0
  48. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/configure +3 -0
  49. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/run +3 -0
  50. stoobly_agent/app/cli/scaffold/templates/build/services/build/mock/.configure +5 -1
  51. stoobly_agent/app/cli/scaffold/templates/build/services/build/mock/.init +5 -1
  52. stoobly_agent/app/cli/scaffold/templates/build/services/build/mock/.run +14 -0
  53. stoobly_agent/app/cli/scaffold/templates/build/services/build/record/.configure +5 -1
  54. stoobly_agent/app/cli/scaffold/templates/build/services/build/record/.init +5 -1
  55. stoobly_agent/app/cli/scaffold/templates/build/services/build/record/.run +14 -0
  56. stoobly_agent/app/cli/scaffold/templates/build/services/build/test/.configure +5 -1
  57. stoobly_agent/app/cli/scaffold/templates/build/services/build/test/.init +5 -1
  58. stoobly_agent/app/cli/scaffold/templates/build/services/build/test/.run +14 -0
  59. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/mock/.configure +5 -1
  60. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/mock/.init +5 -1
  61. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/mock/.run +19 -0
  62. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/record/.configure +5 -1
  63. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/record/.init +5 -1
  64. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/record/.run +19 -0
  65. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/test/.configure +5 -1
  66. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/test/.init +5 -1
  67. stoobly_agent/app/cli/scaffold/templates/build/services/entrypoint/test/.run +19 -0
  68. stoobly_agent/app/cli/scaffold/templates/build/workflows/exec/scaffold/.up +0 -1
  69. stoobly_agent/app/cli/scaffold/templates/build/workflows/mock/.configure +5 -1
  70. stoobly_agent/app/cli/scaffold/templates/build/workflows/mock/.init +5 -1
  71. stoobly_agent/app/cli/scaffold/templates/build/workflows/mock/.run +14 -0
  72. stoobly_agent/app/cli/scaffold/templates/build/workflows/record/.configure +25 -1
  73. stoobly_agent/app/cli/scaffold/templates/build/workflows/record/.init +5 -1
  74. stoobly_agent/app/cli/scaffold/templates/build/workflows/record/.run +14 -0
  75. stoobly_agent/app/cli/scaffold/templates/build/workflows/test/.configure +5 -1
  76. stoobly_agent/app/cli/scaffold/templates/build/workflows/test/.init +5 -1
  77. stoobly_agent/app/cli/scaffold/templates/build/workflows/test/.run +14 -0
  78. stoobly_agent/app/cli/scaffold/templates/constants.py +35 -19
  79. stoobly_agent/app/cli/scaffold/templates/factory.py +34 -18
  80. stoobly_agent/app/cli/scaffold/templates/plugins/cypress/test/.run +21 -0
  81. stoobly_agent/app/cli/scaffold/templates/plugins/playwright/test/.run +21 -0
  82. stoobly_agent/app/cli/scaffold/templates/workflow/mock/configure +5 -0
  83. stoobly_agent/app/cli/scaffold/templates/workflow/mock/run +3 -0
  84. stoobly_agent/app/cli/scaffold/templates/workflow/record/configure +21 -0
  85. stoobly_agent/app/cli/scaffold/templates/workflow/record/run +3 -0
  86. stoobly_agent/app/cli/scaffold/templates/workflow/test/configure +5 -0
  87. stoobly_agent/app/cli/scaffold/templates/workflow/test/run +3 -0
  88. stoobly_agent/app/cli/scaffold/workflow_command.py +18 -4
  89. stoobly_agent/app/cli/scaffold/workflow_copy_command.py +5 -4
  90. stoobly_agent/app/cli/scaffold/workflow_create_command.py +31 -29
  91. stoobly_agent/app/cli/scaffold/workflow_run_command.py +18 -151
  92. stoobly_agent/app/cli/scaffold_cli.py +134 -182
  93. stoobly_agent/app/cli/scenario_cli.py +2 -2
  94. stoobly_agent/app/cli/types/test.py +2 -2
  95. stoobly_agent/app/cli/types/workflow_run_command.py +52 -3
  96. stoobly_agent/app/proxy/handle_mock_service.py +1 -1
  97. stoobly_agent/app/proxy/intercept_settings.py +6 -26
  98. stoobly_agent/app/proxy/mock/eval_fixtures_service.py +177 -27
  99. stoobly_agent/app/proxy/mock/types/__init__.py +22 -1
  100. stoobly_agent/app/proxy/record/upload_request_service.py +3 -6
  101. stoobly_agent/app/proxy/replay/body_parser_service.py +8 -5
  102. stoobly_agent/app/proxy/replay/multipart.py +15 -13
  103. stoobly_agent/app/proxy/replay/replay_request_service.py +2 -2
  104. stoobly_agent/app/proxy/run.py +3 -0
  105. stoobly_agent/app/proxy/test/context.py +0 -4
  106. stoobly_agent/app/proxy/test/context_abc.py +0 -5
  107. stoobly_agent/app/proxy/utils/publish_change_service.py +20 -23
  108. stoobly_agent/app/settings/__init__.py +10 -7
  109. stoobly_agent/cli.py +61 -16
  110. stoobly_agent/config/data_dir.py +1 -8
  111. stoobly_agent/public/12-es2015.618ecfd5f735b801b50f.js +1 -0
  112. stoobly_agent/public/12-es5.618ecfd5f735b801b50f.js +1 -0
  113. stoobly_agent/public/index.html +1 -1
  114. stoobly_agent/public/main-es2015.5a9aa16433404c3f423a.js +1 -0
  115. stoobly_agent/public/main-es5.5a9aa16433404c3f423a.js +1 -0
  116. stoobly_agent/public/runtime-es2015.77bcd31efed9e5d5d431.js +1 -0
  117. stoobly_agent/public/runtime-es5.77bcd31efed9e5d5d431.js +1 -0
  118. stoobly_agent/test/app/cli/intercept/intercept_configure_test.py +17 -6
  119. stoobly_agent/test/app/cli/scaffold/docker/cli_invoker.py +177 -0
  120. stoobly_agent/test/app/cli/scaffold/{cli_test.py → docker/cli_test.py} +4 -11
  121. stoobly_agent/test/app/cli/scaffold/{e2e_test.py → docker/e2e_test.py} +42 -27
  122. stoobly_agent/test/app/cli/scaffold/local/__init__.py +0 -0
  123. stoobly_agent/test/app/cli/scaffold/{cli_invoker.py → local/cli_invoker.py} +38 -32
  124. stoobly_agent/test/app/cli/scaffold/local/e2e_test.py +342 -0
  125. stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
  126. stoobly_agent/test/app/proxy/mock/eval_fixtures_service_test.py +903 -2
  127. stoobly_agent/test/app/proxy/replay/body_parser_service_test.py +95 -3
  128. stoobly_agent/test/config/data_dir_test.py +2 -7
  129. stoobly_agent/test/test_helper.py +16 -5
  130. {stoobly_agent-1.10.0.dist-info → stoobly_agent-1.10.2.dist-info}/METADATA +4 -2
  131. {stoobly_agent-1.10.0.dist-info → stoobly_agent-1.10.2.dist-info}/RECORD +157 -129
  132. {stoobly_agent-1.10.0.dist-info → stoobly_agent-1.10.2.dist-info}/WHEEL +1 -1
  133. stoobly_agent/app/cli/helpers/shell.py +0 -26
  134. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/configure +0 -3
  135. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/configure +0 -3
  136. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/configure +0 -3
  137. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/configure +0 -3
  138. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/configure +0 -3
  139. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/configure +0 -3
  140. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/configure +0 -13
  141. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/configure +0 -47
  142. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/configure +0 -13
  143. stoobly_agent/public/12-es2015.be58ed0ef449008b932e.js +0 -1
  144. stoobly_agent/public/12-es5.be58ed0ef449008b932e.js +0 -1
  145. stoobly_agent/public/main-es2015.089b46f303768fbe864f.js +0 -1
  146. stoobly_agent/public/main-es5.089b46f303768fbe864f.js +0 -1
  147. stoobly_agent/public/runtime-es2015.f8c814b38b27708e91c1.js +0 -1
  148. stoobly_agent/public/runtime-es5.f8c814b38b27708e91c1.js +0 -1
  149. /stoobly_agent/app/cli/scaffold/templates/app/build/mock/{.docker-compose.mock.yml → .docker-compose.yml} +0 -0
  150. /stoobly_agent/app/cli/scaffold/templates/app/build/mock/{bin/init → init} +0 -0
  151. /stoobly_agent/app/cli/scaffold/templates/app/build/record/{.docker-compose.record.yml → .docker-compose.yml} +0 -0
  152. /stoobly_agent/app/cli/scaffold/templates/app/build/record/{bin/init → init} +0 -0
  153. /stoobly_agent/app/cli/scaffold/templates/app/build/test/{.docker-compose.test.yml → .docker-compose.yml} +0 -0
  154. /stoobly_agent/app/cli/scaffold/templates/app/build/test/{bin/init → init} +0 -0
  155. /stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/{.docker-compose.mock.yml → .docker-compose.yml} +0 -0
  156. /stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/{bin/init → init} +0 -0
  157. /stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/{.docker-compose.record.yml → .docker-compose.yml} +0 -0
  158. /stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/{bin/init → init} +0 -0
  159. /stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/{.docker-compose.test.yml → .docker-compose.yml} +0 -0
  160. /stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/{bin/init → init} +0 -0
  161. /stoobly_agent/app/cli/scaffold/templates/app/gateway/mock/{.docker-compose.mock.yml → .docker-compose.yml} +0 -0
  162. /stoobly_agent/app/cli/scaffold/templates/app/gateway/record/{.docker-compose.record.yml → .docker-compose.yml} +0 -0
  163. /stoobly_agent/app/cli/scaffold/templates/app/gateway/test/{.docker-compose.test.yml → .docker-compose.yml} +0 -0
  164. /stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/{.docker-compose.exec.yml → .docker-compose.yml} +0 -0
  165. /stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/mock/{.docker-compose.mock.yml → .docker-compose.yml} +0 -0
  166. /stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/record/{.docker-compose.record.yml → .docker-compose.yml} +0 -0
  167. /stoobly_agent/app/cli/scaffold/templates/plugins/cypress/test/{.docker-compose.test.yml → .docker-compose.yml} +0 -0
  168. /stoobly_agent/app/cli/scaffold/templates/plugins/playwright/test/{.docker-compose.test.yml → .docker-compose.yml} +0 -0
  169. /stoobly_agent/app/cli/scaffold/templates/workflow/mock/{bin/init → init} +0 -0
  170. /stoobly_agent/app/cli/scaffold/templates/workflow/record/{bin/init → init} +0 -0
  171. /stoobly_agent/app/cli/scaffold/templates/workflow/test/{bin/init → init} +0 -0
  172. {stoobly_agent-1.10.0.dist-info → stoobly_agent-1.10.2.dist-info}/entry_points.txt +0 -0
  173. {stoobly_agent-1.10.0.dist-info → stoobly_agent-1.10.2.dist-info/licenses}/LICENSE +0 -0
@@ -7,47 +7,40 @@ from stoobly_agent.config.data_dir import DATA_DIR_NAME
7
7
 
8
8
  from ...app_config import AppConfig
9
9
  from ...constants import (
10
- APP_DIR, DOCKER_NAMESPACE,
10
+ APP_DIR, SERVICES_NAMESPACE,
11
11
  SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV,
12
12
  SERVICE_NAME, SERVICE_NAME_ENV,
13
13
  SERVICE_ID,
14
14
  SERVICE_PORT, SERVICE_PORT_ENV,
15
- SERVICE_SCHEME, SERVICE_SCHEME_ENV,
16
- STOOBLY_HOME_DIR, STOOBLY_HOME_DIR,
15
+ SERVICE_SCHEME, SERVICE_SCHEME_ENV,
16
+ SERVICE_UPSTREAM_HOSTNAME, SERVICE_UPSTREAM_HOSTNAME_ENV, SERVICE_UPSTREAM_PORT, SERVICE_UPSTREAM_PORT_ENV, SERVICE_UPSTREAM_SCHEME, SERVICE_UPSTREAM_SCHEME_ENV,
17
+ STOOBLY_HOME_DIR,
17
18
  WORKFLOW_NAME, WORKFLOW_NAME_ENV, WORKFLOW_SCRIPTS, WORKFLOW_TEMPLATE
18
19
  )
19
20
  from ...service_config import ServiceConfig
21
+ from ...local.service.builder import ServiceBuilder
20
22
  from ..app_builder import AppBuilder
21
23
  from ..builder import Builder
22
24
  from ..constants import DOCKER_COMPOSE_BASE
23
25
 
24
- class ServiceBuilder(Builder):
26
+ class DockerServiceBuilder(ServiceBuilder, Builder):
25
27
 
26
28
  def __init__(self, config: ServiceConfig, app_builder: AppBuilder = None):
27
29
  service_path = config.dir
28
- super().__init__(service_path, DOCKER_COMPOSE_BASE)
30
+
31
+ # Initialize both parent classes
32
+ ServiceBuilder.__init__(self, config)
33
+ Builder.__init__(self, service_path, DOCKER_COMPOSE_BASE)
29
34
 
30
35
  if not app_builder:
31
- app_dir = os.path.dirname(service_path)
32
- app_builder = AppBuilder(AppConfig(app_dir))
36
+ app_config = AppConfig(config.app_config_dir_path)
37
+ app_builder = AppBuilder(app_config)
33
38
  self.app_builder = app_builder
34
39
 
35
- self.__config = config
36
- self.__upstream_port = None
37
- self.__env = [SERVICE_NAME_ENV, WORKFLOW_NAME_ENV]
38
- self.__service_name = os.path.basename(service_path)
39
- self.__working_dir = os.path.join(
40
- STOOBLY_HOME_DIR, DATA_DIR_NAME, DOCKER_NAMESPACE, SERVICE_NAME, WORKFLOW_NAME
41
- )
42
-
43
40
  @property
44
41
  def app_base(self):
45
42
  return f"{self.service_name}.app_base"
46
43
 
47
- @property
48
- def config(self):
49
- return self.__config
50
-
51
44
  @property
52
45
  def configure_base(self):
53
46
  return f"{self.service_name}.configure_base"
@@ -56,10 +49,6 @@ class ServiceBuilder(Builder):
56
49
  def configure_base_service(self):
57
50
  return self.services.get(self.configure_base)
58
51
 
59
- @property
60
- def upstream_port(self) -> int:
61
- return self.__upstream_port
62
-
63
52
  @property
64
53
  def extends_service(self):
65
54
  if self.config.detached:
@@ -83,10 +72,6 @@ class ServiceBuilder(Builder):
83
72
  def proxy_base_service(self):
84
73
  return self.services.get(self.proxy_base)
85
74
 
86
- @property
87
- def service_name(self):
88
- return self.__service_name
89
-
90
75
  def build_extends_init_base(self, source_dir: str):
91
76
  return self.build_extends(self.init_base, source_dir)
92
77
 
@@ -127,7 +112,7 @@ class ServiceBuilder(Builder):
127
112
  'service': self.extends_service
128
113
  },
129
114
  'labels': labels,
130
- 'working_dir': self.__working_dir,
115
+ 'working_dir': self.working_dir,
131
116
  }
132
117
 
133
118
  if len(volumes):
@@ -146,14 +131,14 @@ class ServiceBuilder(Builder):
146
131
  self.__with_detached_volumes(volumes)
147
132
 
148
133
  self.with_service(self.init_base, {
149
- 'command': [f"{WORKFLOW_SCRIPTS}/{WORKFLOW_TEMPLATE}/.init", 'bin/init'],
134
+ 'command': [f"{WORKFLOW_SCRIPTS}/{WORKFLOW_TEMPLATE}/.init", 'init'],
150
135
  'environment': environment,
151
136
  'extends': {
152
137
  'file': os.path.relpath(self.app_builder.compose_file_path, self.dir_path),
153
138
  'service': self.extends_service
154
139
  },
155
140
  'volumes': volumes,
156
- 'working_dir': self.__working_dir,
141
+ 'working_dir': self.working_dir,
157
142
  })
158
143
 
159
144
  def build_configure_base(self):
@@ -167,13 +152,13 @@ class ServiceBuilder(Builder):
167
152
  self.__with_detached_volumes(volumes)
168
153
 
169
154
  base = {
170
- 'command': [f"{WORKFLOW_SCRIPTS}/{WORKFLOW_TEMPLATE}/.configure", 'bin/configure'],
155
+ 'command': [f"{WORKFLOW_SCRIPTS}/{WORKFLOW_TEMPLATE}/.configure", 'configure'],
171
156
  'environment': environment,
172
157
  'extends': {
173
158
  'file': os.path.relpath(self.app_builder.compose_file_path, self.dir_path),
174
159
  'service': self.extends_service
175
160
  },
176
- 'working_dir': self.__working_dir,
161
+ 'working_dir': self.working_dir,
177
162
  }
178
163
 
179
164
  if len(volumes):
@@ -181,24 +166,6 @@ class ServiceBuilder(Builder):
181
166
 
182
167
  self.with_service(self.configure_base, base)
183
168
 
184
- def env_dict(self):
185
- env = {}
186
- for e in self.__env:
187
- env[e] = '${' + e + '}'
188
- return env
189
-
190
- def with_upstream_port(self, v: int):
191
- if not isinstance(v, int):
192
- return self
193
- self.__upstream_port = v
194
- return self
195
-
196
- def with_env(self, v: List[str]):
197
- if not isinstance(v, list):
198
- return self
199
- self.__env += v
200
- return self
201
-
202
169
  def write(self):
203
170
  self.build_init_base()
204
171
  self.build_configure_base()
@@ -213,20 +180,30 @@ class ServiceBuilder(Builder):
213
180
  if self.networks:
214
181
  compose['networks'] = self.networks
215
182
 
216
- super().write(compose)
183
+ Builder.write(self, compose)
217
184
 
218
185
  def __with_detached_volumes(self, volumes: list):
219
186
  # Mount named volume
220
187
  volumes.append(f"{self.service_name}:{STOOBLY_HOME_DIR}/{DATA_DIR_NAME}")
221
188
 
222
189
  # Mount docker folder
223
- volumes.append(f"../:{STOOBLY_HOME_DIR}/{DATA_DIR_NAME}/{DOCKER_NAMESPACE}")
190
+ volumes.append(f"../:{STOOBLY_HOME_DIR}/{DATA_DIR_NAME}/{SERVICES_NAMESPACE}")
224
191
 
225
192
  def __with_url_environment(self, environment):
226
- environment[SERVICE_HOSTNAME_ENV] = SERVICE_HOSTNAME
193
+ if self.config.hostname:
194
+ environment[SERVICE_HOSTNAME_ENV] = SERVICE_HOSTNAME
227
195
 
228
196
  if self.config.scheme:
229
197
  environment[SERVICE_SCHEME_ENV] = SERVICE_SCHEME
230
198
 
231
199
  if self.config.port:
232
- environment[SERVICE_PORT_ENV] = SERVICE_PORT
200
+ environment[SERVICE_PORT_ENV] = SERVICE_PORT
201
+
202
+ if self.config.upstream_hostname:
203
+ environment[SERVICE_UPSTREAM_HOSTNAME_ENV] = SERVICE_UPSTREAM_HOSTNAME
204
+
205
+ if self.config.upstream_port:
206
+ environment[SERVICE_UPSTREAM_PORT_ENV] = SERVICE_UPSTREAM_PORT
207
+
208
+ if self.config.upstream_scheme:
209
+ environment[SERVICE_UPSTREAM_SCHEME_ENV] = SERVICE_UPSTREAM_SCHEME
@@ -21,6 +21,9 @@ def configure_gateway(workflow_namespace: WorkflowNamespace, service_paths: List
21
21
  docker_compose_src_path = os.path.join(gateway_service_path, DOCKER_COMPOSE_BASE_TEMPLATE)
22
22
  docker_compose_dest_path = os.path.join(gateway_service_path, DOCKER_COMPOSE_BASE)
23
23
 
24
+ if not os.path.exists(docker_compose_src_path):
25
+ return
26
+
24
27
  compose = {}
25
28
  with open(docker_compose_src_path, 'r') as fp:
26
29
  compose = yaml.safe_load(fp)
@@ -0,0 +1,112 @@
1
+ import os
2
+ import shutil
3
+ import yaml
4
+
5
+ from mergedeep import merge
6
+
7
+ from ..constants import PLUGINS_FOLDER, WORKFLOW_TEST_TYPE
8
+ from ..templates.constants import CORE_ENTRYPOINT_SERVICE_NAME
9
+ from .constants import (
10
+ DOCKER_COMPOSE_BASE_TEMPLATE,
11
+ DOCKER_COMPOSE_CUSTOM,
12
+ DOCKER_COMPOSE_WORKFLOW,
13
+ DOCKER_MAKEFILE,
14
+ DOCKER_MAKEFILE_DOT,
15
+ DOCKERFILE_CONTEXT,
16
+ DOCKER_COMPOSE_BASE,
17
+ DOCKER_COMPOSE_NETWORKS,
18
+ PLUGIN_CONTAINER_SERVICE_TEMPLATE,
19
+ PLUGIN_DOCKER_ENTRYPOINT,
20
+ PLUGIN_DOCKERFILE_TEMPLATE,
21
+ )
22
+
23
+ DOCKER_APP_TEMPLATE_FILES = [
24
+ DOCKER_MAKEFILE,
25
+ DOCKER_MAKEFILE_DOT,
26
+ DOCKERFILE_CONTEXT,
27
+ DOCKER_COMPOSE_BASE,
28
+ DOCKER_COMPOSE_NETWORKS,
29
+ ]
30
+
31
+ def __merge_compose_plugin(dest_path: str, template_path: str, plugin: str):
32
+ if not os.path.exists(dest_path):
33
+ open(dest_path, 'a').close()
34
+
35
+ def load_yaml(path):
36
+ with open(path, 'r') as f:
37
+ return yaml.safe_load(f) or {}
38
+
39
+ data1 = load_yaml(dest_path)
40
+ data2 = load_yaml(template_path)
41
+
42
+ services = data1.get('services') or {}
43
+ if services.get(PLUGIN_CONTAINER_SERVICE_TEMPLATE.format(plugin=plugin, service=CORE_ENTRYPOINT_SERVICE_NAME)):
44
+ return
45
+
46
+ with open(dest_path, 'w') as out:
47
+ merged = merge(data1, data2)
48
+ yaml.dump(merged, out, default_flow_style=False)
49
+
50
+ def remove_app_docker_files(dest_path: str):
51
+ for file_name in DOCKER_APP_TEMPLATE_FILES:
52
+ file_path = os.path.join(dest_path, file_name)
53
+ if os.path.exists(file_path):
54
+ os.remove(file_path)
55
+
56
+ def remove_service_docker_files(service_path: str):
57
+ compose_files = [DOCKER_COMPOSE_BASE, DOCKER_COMPOSE_CUSTOM, DOCKER_COMPOSE_BASE_TEMPLATE]
58
+
59
+ # For each file in dest_path recursively, check whether it is DOCKER_COMPOSE_BASE or DOCKER_COMPOSE_BASE_TEMPLATE, if so remove it
60
+ for root, _, files in os.walk(service_path):
61
+ for file in files:
62
+ if file in compose_files or file == DOCKER_COMPOSE_WORKFLOW:
63
+ os.remove(os.path.join(root, file))
64
+
65
+ def plugin_docker_cypress(templates_root_dir: str, plugin: str, dest: str):
66
+ dockerfile_name = PLUGIN_DOCKERFILE_TEMPLATE.format(plugin=plugin)
67
+ dockerfile_dest_path = os.path.join(dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, dockerfile_name)
68
+
69
+ # Copy Dockerfile to workflow
70
+ dockerfile_src_path = os.path.join(templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, dockerfile_name)
71
+ shutil.copyfile(dockerfile_src_path, dockerfile_dest_path)
72
+
73
+ # Merge template into dest compose yml
74
+ compose_dest_path = os.path.join(
75
+ dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, DOCKER_COMPOSE_WORKFLOW
76
+ )
77
+ template_path = os.path.join(
78
+ templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, DOCKER_COMPOSE_WORKFLOW
79
+ )
80
+ __merge_compose_plugin(compose_dest_path, template_path, plugin)
81
+
82
+ def plugin_docker_playwright(templates_root_dir: str, plugin: str, dest: str):
83
+ dockerfile_name = PLUGIN_DOCKERFILE_TEMPLATE.format(plugin=plugin)
84
+ dockerfile_src_path = os.path.join(templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, dockerfile_name)
85
+ dockerfile_dest_path = os.path.join(dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, dockerfile_name)
86
+ shutil.copyfile(dockerfile_src_path, dockerfile_dest_path)
87
+
88
+ entrypoint_src_path = os.path.join(templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, PLUGIN_DOCKER_ENTRYPOINT)
89
+ entrypoint_dest_path = os.path.join(dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, PLUGIN_DOCKER_ENTRYPOINT)
90
+ shutil.copyfile(entrypoint_src_path, entrypoint_dest_path)
91
+
92
+ # Merge template into dest compose yml
93
+ compose_dest_path = os.path.join(
94
+ dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, DOCKER_COMPOSE_WORKFLOW
95
+ )
96
+ template_path = os.path.join(
97
+ templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, DOCKER_COMPOSE_WORKFLOW
98
+ )
99
+ __merge_compose_plugin(compose_dest_path, template_path, plugin)
100
+
101
+ def plugin_local_cypress(templates_root_dir: str, plugin: str, dest: str):
102
+ # Copy run script
103
+ run_script_src_path = os.path.join(templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, '.run')
104
+ run_script_dest_path = os.path.join(dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, '.run')
105
+ # Use shutil.copy instead of shutil.copyfile to preserve permissions
106
+ shutil.copy(run_script_src_path, run_script_dest_path)
107
+
108
+ def plugin_local_playwright(templates_root_dir: str, plugin: str, dest: str):
109
+ # Copy run script
110
+ run_script_src_path = os.path.join(templates_root_dir, PLUGINS_FOLDER, plugin, WORKFLOW_TEST_TYPE, '.run')
111
+ run_script_dest_path = os.path.join(dest, CORE_ENTRYPOINT_SERVICE_NAME, WORKFLOW_TEST_TYPE, '.run')
112
+ shutil.copy(run_script_src_path, run_script_dest_path)
@@ -1,6 +1,6 @@
1
1
  import pdb
2
2
 
3
- from .builder import WorkflowBuilder
3
+ from ...local.workflow.builder import WorkflowBuilder
4
4
 
5
5
  class BuildDecorator():
6
6
 
@@ -1,29 +1,26 @@
1
1
  import os
2
2
  import pdb
3
3
 
4
+ from typing import List, Union
5
+
4
6
  from ...constants import (
5
- COMPOSE_TEMPLATE, SERVICE_HOSTNAME,
6
- SERVICE_HOSTNAME_ENV, SERVICE_NAME_ENV, SERVICE_PORT, SERVICE_PORT_ENV, SERVICE_SCHEME, SERVICE_SCHEME_ENV,
7
7
  WORKFLOW_CONTAINER_CONFIGURE_TEMPLATE, WORKFLOW_CONTAINER_INIT_TEMPLATE, WORKFLOW_CONTAINER_PROXY_TEMPLATE, WORKFLOW_NAME, WORKFLOW_NAME_ENV
8
8
  )
9
+ from ...local.workflow.builder import WorkflowBuilder
9
10
  from ..builder import Builder
10
- from ..service.builder import ServiceBuilder
11
-
12
- class WorkflowBuilder(Builder):
13
-
14
- def __init__(self, workflow_path: str, service_builder: ServiceBuilder):
15
- self._env = [SERVICE_NAME_ENV, WORKFLOW_NAME_ENV]
16
- self.__workflow_name = os.path.basename(workflow_path)
17
- super().__init__(workflow_path, COMPOSE_TEMPLATE.format(workflow=self.__workflow_name))
11
+ from ..constants import DOCKER_COMPOSE_WORKFLOW
12
+ from ..service.builder import DockerServiceBuilder
13
+ from .mock_decorator import MockDecorator
14
+ from .reverse_proxy_decorator import ReverseProxyDecorator
18
15
 
19
- self.__context = '../'
20
- self.__profiles = [WORKFLOW_NAME]
16
+ class DockerWorkflowBuilder(Builder, WorkflowBuilder):
21
17
 
22
- if not service_builder:
23
- service_path = os.path.dirname(workflow_path)
24
- service_builder = ServiceBuilder(service_path)
18
+ def __init__(self, workflow_path: str, service_builder: DockerServiceBuilder):
19
+ WorkflowBuilder.__init__(self, workflow_path, service_builder)
20
+ Builder.__init__(self, workflow_path, DOCKER_COMPOSE_WORKFLOW)
25
21
 
26
- self.__service_builder = service_builder
22
+ self._context = '../'
23
+ self._profiles = [WORKFLOW_NAME]
27
24
 
28
25
  @property
29
26
  def app(self):
@@ -33,17 +30,13 @@ class WorkflowBuilder(Builder):
33
30
  def base_compose_file_path(self):
34
31
  return os.path.relpath(self.service_builder.compose_file_path, self.dir_path)
35
32
 
36
- @property
37
- def config(self):
38
- return self.service_builder.config
39
-
40
33
  @property
41
34
  def configure(self):
42
35
  return WORKFLOW_CONTAINER_CONFIGURE_TEMPLATE.format(service_name=self.namespace)
43
36
 
44
37
  @property
45
38
  def context(self):
46
- return self.__context
39
+ return self._context
47
40
 
48
41
  @property
49
42
  def context_docker_file_path(self):
@@ -59,24 +52,12 @@ class WorkflowBuilder(Builder):
59
52
 
60
53
  @property
61
54
  def profiles(self):
62
- return self.__profiles
55
+ return self._profiles
63
56
 
64
57
  @property
65
58
  def proxy(self):
66
59
  return WORKFLOW_CONTAINER_PROXY_TEMPLATE.format(service_name=self.namespace)
67
60
 
68
- @property
69
- def service_builder(self):
70
- return self.__service_builder
71
-
72
- @property
73
- def service_path(self):
74
- return self.__service_builder.dir_path
75
-
76
- @property
77
- def workflow_name(self):
78
- return self.__workflow_name
79
-
80
61
  def build_all(self):
81
62
  # Resources
82
63
  if self.config.detached:
@@ -147,11 +128,21 @@ class WorkflowBuilder(Builder):
147
128
 
148
129
  self.with_service(self.proxy, service)
149
130
 
150
- def env_dict(self):
151
- env = {}
152
- for e in self._env:
153
- env[e] = '${' + e + '}'
154
- return env
131
+ def build(self, workflow_decorators: List[Union[MockDecorator, ReverseProxyDecorator]] = None):
132
+ """Build the Docker workflow with all components and decorators."""
133
+
134
+ # Build all workflow components
135
+ self.build_all()
136
+
137
+ # Apply workflow decorators if provided
138
+ if isinstance(workflow_decorators, list):
139
+ for workflow_decorator in workflow_decorators:
140
+ workflow_decorator(self).decorate()
141
+
142
+ # Write the compose file
143
+ self.write()
144
+
145
+ return self
155
146
 
156
147
  def write(self):
157
148
  compose = {
@@ -166,11 +157,3 @@ class WorkflowBuilder(Builder):
166
157
 
167
158
  super().write(compose)
168
159
 
169
- def __with_url_environment(self, environment):
170
- environment[SERVICE_HOSTNAME_ENV] = SERVICE_HOSTNAME
171
-
172
- if self.config.scheme:
173
- environment[SERVICE_SCHEME_ENV] = SERVICE_SCHEME
174
-
175
- if self.config.port:
176
- environment[SERVICE_PORT_ENV] = SERVICE_PORT
@@ -1,7 +1,7 @@
1
1
  from ...constants import (
2
- SERVICE_PROXY_MODE, SERVICE_UPSTREAM_HOSTNAME, SERVICE_UPSTREAM_PORT, SERVICE_UPSTREAM_SCHEME,
2
+ SERVICE_UPSTREAM_HOSTNAME, SERVICE_UPSTREAM_PORT, SERVICE_UPSTREAM_SCHEME,
3
3
  )
4
- from .builder import WorkflowBuilder
4
+ from ...local.workflow.builder import WorkflowBuilder
5
5
 
6
6
  class CommandDecorator():
7
7
 
@@ -15,6 +15,7 @@ class CommandDecorator():
15
15
  @property
16
16
  def proxy_mode(self):
17
17
  config = self.workflow_builder.config
18
+
18
19
  if config.upstream_hostname == 'host.docker.internal':
19
20
  return f"upstream:{SERVICE_UPSTREAM_SCHEME}://{SERVICE_UPSTREAM_HOSTNAME}:{SERVICE_UPSTREAM_PORT}"
20
21
 
@@ -2,7 +2,7 @@ import os
2
2
  import pdb
3
3
 
4
4
  from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, STOOBLY_CERTS_DIR
5
- from .builder import WorkflowBuilder
5
+ from ...local.workflow.builder import WorkflowBuilder
6
6
  from .command_decorator import CommandDecorator
7
7
 
8
8
  class DetachedDecorator(CommandDecorator):
@@ -1,8 +1,7 @@
1
1
  from ...constants import SERVICE_DNS
2
+ from ...local.workflow.builder import WorkflowBuilder
2
3
 
3
- from .builder import WorkflowBuilder
4
-
5
- class DnsDecorator():
4
+ class DnsDecorator:
6
5
 
7
6
  def __init__(self, workflow_builder: WorkflowBuilder):
8
7
  self.__workflow_builder = workflow_builder
@@ -1,4 +1,4 @@
1
- from .builder import WorkflowBuilder
1
+ from ...local.workflow.builder import WorkflowBuilder
2
2
 
3
3
  class LocalDecorator():
4
4
 
@@ -4,7 +4,7 @@ import pdb
4
4
  from ...constants import (
5
5
  SERVICE_HOSTNAME, SERVICE_PORT, STOOBLY_CERTS_DIR,
6
6
  )
7
- from .builder import WorkflowBuilder
7
+ from ...local.workflow.builder import WorkflowBuilder
8
8
  from .command_decorator import CommandDecorator
9
9
 
10
10
  class MockDecorator(CommandDecorator):
@@ -4,7 +4,7 @@ import pdb
4
4
  from urllib.parse import urlparse
5
5
 
6
6
  from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, STOOBLY_CERTS_DIR
7
- from .builder import WorkflowBuilder
7
+ from ...local.workflow.builder import WorkflowBuilder
8
8
  from .command_decorator import CommandDecorator
9
9
 
10
10
  class ReverseProxyDecorator(CommandDecorator):