stoobly-agent 1.2.3__py3-none-any.whl → 1.4.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.
Files changed (102) hide show
  1. stoobly_agent/__init__.py +1 -1
  2. stoobly_agent/app/api/application_http_request_handler.py +3 -3
  3. stoobly_agent/app/api/proxy_controller.py +8 -7
  4. stoobly_agent/app/cli/config_cli.py +1 -1
  5. stoobly_agent/app/cli/helpers/certificate_authority.py +7 -6
  6. stoobly_agent/app/cli/helpers/print_service.py +17 -0
  7. stoobly_agent/app/cli/scaffold/app.py +16 -34
  8. stoobly_agent/app/cli/scaffold/app_command.py +4 -7
  9. stoobly_agent/app/cli/scaffold/app_config.py +15 -2
  10. stoobly_agent/app/cli/scaffold/app_create_command.py +18 -2
  11. stoobly_agent/app/cli/scaffold/command.py +1 -1
  12. stoobly_agent/app/cli/scaffold/constants.py +9 -5
  13. stoobly_agent/app/cli/scaffold/docker/app_builder.py +3 -7
  14. stoobly_agent/app/cli/scaffold/docker/constants.py +0 -1
  15. stoobly_agent/app/cli/scaffold/docker/service/builder.py +12 -11
  16. stoobly_agent/app/cli/scaffold/docker/workflow/builder.py +14 -31
  17. stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +6 -2
  18. stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py +6 -2
  19. stoobly_agent/app/cli/scaffold/hosts_file_manager.py +112 -0
  20. stoobly_agent/app/cli/scaffold/service.py +1 -2
  21. stoobly_agent/app/cli/scaffold/service_command.py +1 -1
  22. stoobly_agent/app/cli/scaffold/service_config.py +10 -14
  23. stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py +9 -11
  24. stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context +2 -4
  25. stoobly_agent/app/cli/scaffold/templates/app/.Makefile +108 -68
  26. stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml +8 -13
  27. stoobly_agent/app/cli/scaffold/templates/app/Makefile +1 -1
  28. stoobly_agent/app/cli/scaffold/templates/app/build/.docker-compose.base.yml +8 -4
  29. stoobly_agent/app/cli/scaffold/templates/app/build/mock/.docker-compose.mock.yml +2 -6
  30. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/.configure +3 -0
  31. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/.init +3 -0
  32. stoobly_agent/app/cli/scaffold/templates/app/build/record/.docker-compose.record.yml +2 -6
  33. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/.configure +3 -0
  34. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/.init +3 -0
  35. stoobly_agent/app/cli/scaffold/templates/app/build/test/.docker-compose.test.yml +2 -6
  36. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/.configure +3 -0
  37. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/.init +3 -0
  38. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/.docker-compose.base.yml +2 -0
  39. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/.docker-compose.mock.yml +2 -8
  40. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/.docker-compose.record.yml +2 -8
  41. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/.docker-compose.test.yml +2 -8
  42. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/.docker-compose.exec.yml +2 -3
  43. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.logs +1 -0
  44. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.services +9 -0
  45. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/mock/.docker-compose.mock.yml +1 -2
  46. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/record/.docker-compose.record.yml +1 -2
  47. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/.configure +3 -0
  48. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/.init +7 -1
  49. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/.configure +3 -0
  50. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/.init +7 -1
  51. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/.configure +3 -0
  52. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/.init +7 -1
  53. stoobly_agent/app/cli/scaffold/validate_command.py +2 -2
  54. stoobly_agent/app/cli/scaffold/workflow.py +5 -4
  55. stoobly_agent/app/cli/scaffold/workflow_command.py +3 -3
  56. stoobly_agent/app/cli/scaffold/workflow_create_command.py +0 -1
  57. stoobly_agent/app/cli/scaffold/workflow_run_command.py +78 -45
  58. stoobly_agent/app/cli/scaffold_cli.py +246 -109
  59. stoobly_agent/app/cli/snapshot_cli.py +7 -3
  60. stoobly_agent/app/models/adapters/joined_request_adapter.py +6 -0
  61. stoobly_agent/app/models/factories/resource/local_db/helpers/scenario_snapshot.py +3 -1
  62. stoobly_agent/app/models/helpers/apply.py +34 -17
  63. stoobly_agent/app/models/helpers/create_request_params_service.py +4 -0
  64. stoobly_agent/app/proxy/handle_mock_service.py +2 -0
  65. stoobly_agent/app/proxy/handle_replay_service.py +2 -0
  66. stoobly_agent/app/proxy/mitmproxy/request_facade.py +1 -1
  67. stoobly_agent/app/proxy/mitmproxy/response_body_facade.py +19 -0
  68. stoobly_agent/app/proxy/mitmproxy/response_facade.py +90 -18
  69. stoobly_agent/app/proxy/record/join_request_service.py +1 -1
  70. stoobly_agent/app/proxy/replay/body_parser_service.py +11 -3
  71. stoobly_agent/app/settings/constants/request_component.py +2 -1
  72. stoobly_agent/config/constants/custom_headers.py +13 -13
  73. stoobly_agent/config/constants/headers.py +0 -2
  74. stoobly_agent/config/data_dir.py +2 -1
  75. stoobly_agent/config/schema.yml +2 -2
  76. stoobly_agent/public/18-es2015.583f191cc7ad512ee262.js +1 -0
  77. stoobly_agent/public/18-es5.583f191cc7ad512ee262.js +1 -0
  78. stoobly_agent/public/35-es2015.8f79ff8748d4ff06ab03.js +1 -0
  79. stoobly_agent/public/35-es5.8f79ff8748d4ff06ab03.js +1 -0
  80. stoobly_agent/public/index.html +1 -1
  81. stoobly_agent/public/main-es2015.2cc16523aa3fcaba51e5.js +1 -0
  82. stoobly_agent/public/main-es5.2cc16523aa3fcaba51e5.js +1 -0
  83. stoobly_agent/public/{runtime-es2015.9addf49b79aca951b7e2.js → runtime-es2015.b914470164e4d6e75d96.js} +1 -1
  84. stoobly_agent/public/{runtime-es5.9addf49b79aca951b7e2.js → runtime-es5.b914470164e4d6e75d96.js} +1 -1
  85. stoobly_agent/test/app/cli/scaffold/cli_invoker.py +1 -2
  86. stoobly_agent/test/app/cli/scaffold/{hosts_file_reader_test.py → hosts_file_manager_test.py} +20 -20
  87. stoobly_agent/test/app/cli/snapshot/snapshot_apply_test.py +162 -1
  88. stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
  89. stoobly_agent/test/mock_data/scaffold/docker-compose-assets-service.yml +1 -3
  90. {stoobly_agent-1.2.3.dist-info → stoobly_agent-1.4.0.dist-info}/METADATA +1 -1
  91. {stoobly_agent-1.2.3.dist-info → stoobly_agent-1.4.0.dist-info}/RECORD +94 -93
  92. stoobly_agent/app/cli/scaffold/hosts_file_reader.py +0 -65
  93. stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.proxy +0 -34
  94. stoobly_agent/public/18-es2015.d3b430636a4d6f544d92.js +0 -1
  95. stoobly_agent/public/18-es5.d3b430636a4d6f544d92.js +0 -1
  96. stoobly_agent/public/35-es2015.f741ebce0bfc25f0ec99.js +0 -1
  97. stoobly_agent/public/35-es5.f741ebce0bfc25f0ec99.js +0 -1
  98. stoobly_agent/public/main-es2015.ccd46ac1b6638ddf2066.js +0 -1
  99. stoobly_agent/public/main-es5.ccd46ac1b6638ddf2066.js +0 -1
  100. {stoobly_agent-1.2.3.dist-info → stoobly_agent-1.4.0.dist-info}/LICENSE +0 -0
  101. {stoobly_agent-1.2.3.dist-info → stoobly_agent-1.4.0.dist-info}/WHEEL +0 -0
  102. {stoobly_agent-1.2.3.dist-info → stoobly_agent-1.4.0.dist-info}/entry_points.txt +0 -0
stoobly_agent/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
1
  COMMAND = 'stoobly-agent'
2
- VERSION = '1.2.3'
2
+ VERSION = '1.4.0'
@@ -7,7 +7,7 @@ from mitmproxy.coretypes.multidict import MultiDict
7
7
  from urllib.parse import urlparse, parse_qs
8
8
 
9
9
  from stoobly_agent.app.proxy.replay.body_parser_service import decode_response
10
- from stoobly_agent.config.constants import headers
10
+ from stoobly_agent.config.constants import custom_headers, headers
11
11
 
12
12
  from .routes import ROUTES
13
13
  from .simple_http_request_handler import SimpleHTTPRequestHandler
@@ -102,11 +102,11 @@ class ApplicationHTTPRequestHandler(SimpleHTTPRequestHandler):
102
102
  'Content-Type',
103
103
  headers.ACCESS_TOKEN.title(),
104
104
  headers.CLIENT.title(),
105
- headers.DO_PROXY.title(),
105
+ custom_headers.DO_PROXY.title(),
106
106
  headers.EXPIRY.title(),
107
107
  headers.PROXY_HEADERS.title(),
108
108
  headers.REQUEST_PATH.title(),
109
- headers.SERVICE_URL.title(),
109
+ custom_headers.SERVICE_URL.title(),
110
110
  headers.TOKEN_TYPE.title(),
111
111
  headers.UID.title(),
112
112
  ])
@@ -3,7 +3,8 @@ import requests
3
3
  from http.cookies import SimpleCookie
4
4
  from urllib3.exceptions import InsecureRequestWarning
5
5
 
6
- from stoobly_agent.config.constants import headers
6
+ from stoobly_agent.app.api.simple_http_request_handler import SimpleHTTPRequestHandler
7
+ from stoobly_agent.config.constants import custom_headers, headers
7
8
  from stoobly_agent.config.mitmproxy import MitmproxyConfig
8
9
  from stoobly_agent.lib.logger import Logger
9
10
 
@@ -46,7 +47,7 @@ class ProxyController:
46
47
  def do_PUT(self, context):
47
48
  self.__proxy(context, requests.put)
48
49
 
49
- def __proxy(self, context, method):
50
+ def __proxy(self, context: SimpleHTTPRequestHandler, method):
50
51
  url = self.__get_url(context)
51
52
 
52
53
  if url:
@@ -110,7 +111,7 @@ class ProxyController:
110
111
  status = status,
111
112
  )
112
113
 
113
- def __get_headers(self, context):
114
+ def __get_headers(self, context: SimpleHTTPRequestHandler):
114
115
  request_headers = dict(context.headers)
115
116
 
116
117
  headers_white_list = []
@@ -125,12 +126,12 @@ class ProxyController:
125
126
 
126
127
  return white_listed_headers
127
128
 
128
- def __get_url(self, context):
129
- service_url = context.headers.get(headers.SERVICE_URL)
129
+ def __get_url(self, context: SimpleHTTPRequestHandler):
130
+ service_url = context.headers.get(custom_headers.SERVICE_URL)
130
131
 
131
132
  if not service_url:
132
133
  context.render(
133
- plain = f"Invalid {headers.SERVICE_URL} header {service_url}",
134
+ plain = f"Invalid {custom_headers.SERVICE_URL} header {service_url}",
134
135
  status = 400
135
136
  )
136
137
  return None
@@ -146,7 +147,7 @@ class ProxyController:
146
147
 
147
148
  return f"{service_url}{request_path}"
148
149
 
149
- def __get_cookies(self, context):
150
+ def __get_cookies(self, context: SimpleHTTPRequestHandler):
150
151
  return SimpleCookie(context.headers.get('Cookie'))
151
152
 
152
153
  def __get_body(self, context):
@@ -180,7 +180,7 @@ def rewrite(ctx):
180
180
  @click.option('--project-key', help='Project to add rewrite rule to.')
181
181
  @click.option(
182
182
  '--type',
183
- type=click.Choice([request_component.BODY_PARAM, request_component.HEADER, request_component.QUERY_PARAM]),
183
+ type=click.Choice([request_component.BODY_PARAM, request_component.HEADER, request_component.QUERY_PARAM, request_component.RESPONSE_HEADER, request_component.RESPONSE_PARAM]),
184
184
  help='Request component type.'
185
185
  )
186
186
  @click.option(
@@ -23,10 +23,6 @@ class CertificateAuthority():
23
23
 
24
24
  def __init__(self, certs_dir = DataDir.instance().mitmproxy_conf_dir_path, cn = MITMPROXY_CN):
25
25
  self.certs_dir = certs_dir
26
-
27
- if not os.path.exists(certs_dir):
28
- self.generate_certs()
29
-
30
26
  self.cn = cn
31
27
  self.key_size = 2048
32
28
 
@@ -98,6 +94,9 @@ class CertificateAuthority():
98
94
  subprocess.run("sudo update-ca-trust extract".split(), check=True)
99
95
 
100
96
  def install(self):
97
+ if not self.certs_generated:
98
+ self.generate_certs()
99
+
101
100
  distro_name = distro.name(pretty=True)
102
101
 
103
102
  # Ubuntu or other Debian based
@@ -109,7 +108,9 @@ class CertificateAuthority():
109
108
  # elif distro.id() == 'rhel':
110
109
  # return
111
110
  else:
112
- raise TypeError(f"{distro_name} is not supported yet for automatic CA cert installation.")
111
+ raise TypeError(
112
+ f"{distro_name} is not supported yet for automatic installation. For manual installation, see https://docs.mitmproxy.org/stable/concepts-certificates/"
113
+ )
113
114
 
114
115
  def sign(self, hostname: str, dest = None, port = 443):
115
116
  dest = dest or self.certs_dir
@@ -201,5 +202,5 @@ class CertificateAuthority():
201
202
  return org_name, alt_names
202
203
 
203
204
  except Exception as e:
204
- Logger.instance(LOG_ID).warn(f"Could not retrieve certificate for {domain}: {e}")
205
+ Logger.instance(LOG_ID).debug(f"Could not retrieve certificate for {domain}: {e}")
205
206
  return None, alt_names
@@ -89,6 +89,23 @@ def print_scenarios(scenarios, **kwargs: TabulatePrintOptions):
89
89
  select=kwargs.get('select') or []
90
90
  )
91
91
 
92
+ def print_services(services, **kwargs: TabulatePrintOptions):
93
+ filter = []
94
+ format = kwargs.get('format')
95
+
96
+ if format == JSON_FORMAT:
97
+ json_print(services, **{
98
+ 'filter': filter,
99
+ **kwargs
100
+ })
101
+ else:
102
+ tabulate_print(
103
+ services,
104
+ filter=filter,
105
+ headers=not kwargs.get('without_headers'),
106
+ select=kwargs.get('select') or []
107
+ )
108
+
92
109
  def print_snapshots(snapshots, **kwargs: TabulatePrintOptions):
93
110
  filter = ['resource_uuid']
94
111
  format = kwargs.get('format')
@@ -5,20 +5,18 @@ from stoobly_agent.config.data_dir import DataDir, DATA_DIR_NAME
5
5
 
6
6
  class App():
7
7
 
8
- def __init__(self, path: str, namespace: str, **kwargs):
8
+ def __init__(self, path: str, scaffold_namespace: str, **kwargs):
9
9
  path = os.path.abspath(path) or os.getcwd()
10
10
  data_dir: DataDir = DataDir.instance(path)
11
11
 
12
- self.__scaffold_dir_path = data_dir.path
12
+ self.__data_dir_path = data_dir.path
13
13
  self.__ca_certs_dir_path = kwargs.get('ca_certs_dir_path') or data_dir.mitmproxy_conf_dir_path
14
- self.__certs_dir_path = data_dir.certs_dir_path
15
- self.__context_dir_path = data_dir.context_dir_path
14
+ self.__certs_dir_path = kwargs.get('certs_dir_path') or data_dir.certs_dir_path
15
+ self.__context_dir_path = kwargs.get('context_dir_path') or data_dir.context_dir_path
16
16
  self.__data_dir = data_dir
17
17
  self.__dir_path = path
18
- self.__name = os.path.basename(self.__dir_path)
19
- self.__network = os.path.basename(self.__dir_path)
20
- self.__namespace = namespace
21
- self.__skip_validate_path = not not kwargs.get('skip_validate_path')
18
+ self.__scaffold_namespace = scaffold_namespace
19
+ self.__skip_validate_path = not not kwargs.get('dry_run')
22
20
 
23
21
  @property
24
22
  def ca_certs_dir_path(self):
@@ -56,44 +54,28 @@ class App():
56
54
  return os.path.join(self.context_dir_path, DATA_DIR_NAME)
57
55
 
58
56
  @property
59
- def exists(self):
60
- return os.path.exists(self.dir_path)
57
+ def valid(self):
58
+ return os.path.exists(self.scaffold_namespace_path)
61
59
 
62
60
  @property
63
- def name(self):
64
- return self.__name
65
-
66
- @name.setter
67
- def name(self, v: str):
68
- self.__name = v
69
-
70
- @property
71
- def network(self):
72
- return self.__network
73
-
74
- @network.setter
75
- def network(self, v: str):
76
- self.__network = v
61
+ def scaffold_namespace(self):
62
+ return self.__scaffold_namespace
77
63
 
78
64
  @property
79
- def namespace(self):
80
- return self.__namespace
81
-
82
- @property
83
- def namespace_path(self):
84
- return os.path.join(self.data_dir_path, self.namespace)
65
+ def scaffold_namespace_path(self):
66
+ return os.path.join(self.data_dir_path, self.scaffold_namespace)
85
67
 
86
68
  @property
87
69
  def dir_path(self):
88
70
  return self.__dir_path
89
71
 
90
72
  @property
91
- def scaffold_dir_path(self):
92
- return self.__scaffold_dir_path
73
+ def data_dir_path(self):
74
+ return self.__data_dir_path
93
75
 
94
76
  @property
95
77
  def scaffold_namespace_path(self):
96
- return os.path.join(self.scaffold_dir_path, self.namespace)
78
+ return os.path.join(self.data_dir_path, self.scaffold_namespace)
97
79
 
98
80
  @property
99
81
  def services(self):
@@ -101,7 +83,7 @@ class App():
101
83
 
102
84
  @property
103
85
  def service_paths(self):
104
- services_dir = os.path.join(self.scaffold_dir_path, self.namespace)
86
+ services_dir = os.path.join(self.data_dir_path, self.scaffold_namespace)
105
87
 
106
88
  services = []
107
89
  for filename in os.listdir(services_dir):
@@ -13,9 +13,6 @@ class AppCommand(Command):
13
13
 
14
14
  self.__config = AppConfig(self.scaffold_namespace_path)
15
15
 
16
- if not self.__config.network:
17
- self.__config.network = app.network
18
-
19
16
  @property
20
17
  def app_dir_path(self):
21
18
  return self.app.dir_path
@@ -33,16 +30,16 @@ class AppCommand(Command):
33
30
  return self.__config.path
34
31
 
35
32
  @property
36
- def app_namespace_path(self):
37
- return self.app.namespace_path
33
+ def scaffold_namespace_path(self):
34
+ return self.app.scaffold_namespace_path
38
35
 
39
36
  @property
40
37
  def app_templates_root_dir(self):
41
38
  return os.path.join(self.templates_root_dir, 'app')
42
39
 
43
40
  @property
44
- def scaffold_dir_path(self):
45
- return self.app.scaffold_dir_path
41
+ def data_dir_path(self):
42
+ return self.app.data_dir_path
46
43
 
47
44
  @property
48
45
  def scaffold_namespace_path(self):
@@ -1,15 +1,24 @@
1
1
  from .config import Config
2
- from .constants import APP_NETWORK_ENV
2
+ from .constants import APP_NAME_ENV, APP_NETWORK_ENV
3
3
 
4
4
  class AppConfig(Config):
5
5
 
6
6
  def __init__(self, dir: str):
7
7
  super().__init__(dir)
8
8
 
9
+ self.__name = None
9
10
  self.__network = None
10
11
 
11
12
  self.load()
12
13
 
14
+ @property
15
+ def name(self):
16
+ return self.__name
17
+
18
+ @name.setter
19
+ def name(self, v):
20
+ self.__name = v
21
+
13
22
  @property
14
23
  def network(self):
15
24
  return self.__network
@@ -21,11 +30,15 @@ class AppConfig(Config):
21
30
  def load(self, config = None):
22
31
  config = config or self.read()
23
32
 
24
- self.__network = config.get(APP_NETWORK_ENV)
33
+ self.name = config.get(APP_NAME_ENV)
34
+ self.network = config.get(APP_NETWORK_ENV)
25
35
 
26
36
  def write(self):
27
37
  config = {}
28
38
 
39
+ if self.name:
40
+ config[APP_NAME_ENV] = self.name
41
+
29
42
  if self.network:
30
43
  config[APP_NETWORK_ENV] = self.network
31
44
 
@@ -1,17 +1,33 @@
1
1
  import os
2
2
  import pdb
3
3
 
4
+ from typing import TypedDict
5
+
4
6
  from .app import App
5
7
  from .app_command import AppCommand
6
8
 
9
+ class AppCreateOptions(TypedDict):
10
+ name: str
11
+ network: str
12
+
7
13
  class AppCreateCommand(AppCommand):
8
14
 
9
- def __init__(self, app: App, **kwargs):
15
+ def __init__(self, app: App, **kwargs: AppCreateOptions):
10
16
  super().__init__(app)
11
17
 
18
+ if kwargs.get('app_name'):
19
+ self.app_config.name = kwargs['app_name']
20
+
21
+ if kwargs.get('network'):
22
+ self.app_config.network = kwargs['network']
23
+
12
24
  @property
13
25
  def app_name(self):
14
- return self.app.name
26
+ return self.app_config.name
27
+
28
+ @property
29
+ def app_network(self):
30
+ return self.app_config.network
15
31
 
16
32
  def build(self):
17
33
  dest = self.scaffold_namespace_path
@@ -4,7 +4,7 @@ class Command():
4
4
 
5
5
  def __init__(self, app: App):
6
6
  self.__app = app
7
- self.__namespace = app.namespace
7
+ self.__namespace = app.scaffold_namespace
8
8
 
9
9
  @property
10
10
  def app(self):
@@ -1,9 +1,11 @@
1
- from typing import Literal
1
+ import os
2
2
 
3
- from stoobly_agent.config.data_dir import DATA_DIR_NAME
3
+ from typing import Literal
4
4
 
5
+ from stoobly_agent.config.data_dir import CERTS_DIR_NAME, DATA_DIR_NAME
5
6
 
6
7
  APP_NETWORK_ENV = 'APP_NETWORK'
8
+ APP_NAME_ENV = 'APP_NAME'
7
9
  BIN_FOLDER_NAME = 'bin'
8
10
  CA_CERTS_DIR_ENV = 'CA_CERTS_DIR'
9
11
  CERTS_DIR_ENV = 'CERTS_DIR'
@@ -16,12 +18,11 @@ FIXTURES_FOLDER_NAME = 'fixtures'
16
18
  NAMESERVERS_FILE = '.nameservers'
17
19
  SERVICE_DETACHED = '${SERVICE_DETACHED}'
18
20
  SERVICE_DETACHED_ENV = 'SERVICE_DETACHED'
19
- SERVICE_DOCKER_COMPOSE_PATH = '${SERVICE_DOCKER_COMPOSE_PATH}'
20
- SERVICE_DOCKER_COMPOSE_PATH_ENV = 'SERVICE_DOCKER_COMPOSE_PATH'
21
21
  SERVICE_HOSTNAME = '${SERVICE_HOSTNAME}'
22
22
  SERVICE_HOSTNAME_ENV = 'SERVICE_HOSTNAME'
23
23
  SERVICE_DNS = '${SERVICE_DNS}'
24
24
  SERVICE_DNS_ENV = 'SERVICE_DNS'
25
+ SERVICE_NAME = '${SERVICE_NAME}'
25
26
  SERVICE_NAME_ENV = 'SERVICE_NAME'
26
27
  SERVICE_PROXY_MODE = '${SERVICE_PROXY_MODE}'
27
28
  SERVICE_PROXY_MODE_ENV = 'SERVICE_PROXY_MODE'
@@ -31,7 +32,8 @@ SERVICE_PORT = '${SERVICE_PORT}'
31
32
  SERVICE_PORT_ENV = 'SERVICE_PORT'
32
33
  SERVICE_PRIORITY_ENV = 'SERVICE_PRIORITY'
33
34
  STOOBLY_HOME_DIR = '/home/stoobly'
34
- STOOBLY_DATA_DIR = f"{STOOBLY_HOME_DIR}/{DATA_DIR_NAME}"
35
+ STOOBLY_DATA_DIR = os.path.join(STOOBLY_HOME_DIR, DATA_DIR_NAME)
36
+ STOOBLY_CERTS_DIR = os.path.join(STOOBLY_DATA_DIR, CERTS_DIR_NAME)
35
37
  USER_ID_ENV = 'USER_ID'
36
38
  VIRTUAL_HOST_ENV = 'VIRTUAL_HOST'
37
39
  VIRTUAL_PORT_ENV = 'VIRTUAL_PORT'
@@ -44,7 +46,9 @@ WORKFLOW_CONTAINER_CONFIGURE_TEMPLATE = '{service_name}.' + WORKFLOW_CONTAINER_C
44
46
  WORKFLOW_CONTAINER_INIT_TEMPLATE = '{service_name}.' + WORKFLOW_CONTAINER_INIT
45
47
  WORKFLOW_CONTAINER_PROXY_TEMPLATE = '{service_name}.' + WORKFLOW_CONTAINER_PROXY
46
48
  WORKFLOW_MOCK_TYPE = 'mock'
49
+ WORKFLOW_NAME = '${WORKFLOW_NAME}'
47
50
  WORKFLOW_NAME_ENV = 'WORKFLOW_NAME'
51
+ WORKFLOW_NAMESPACE_ENV = 'WORKFLOW_NAMESPACE'
48
52
  WORKFLOW_RECORD_TYPE = 'record'
49
53
  WORKFLOW_TEST_TYPE = 'test'
50
54
 
@@ -1,7 +1,7 @@
1
1
  import os
2
2
 
3
3
  from .builder import Builder
4
- from .constants import DOCKER_COMPOSE_BASE, DOCKERFILE_CONTEXT, DOCKERFILE_PROXY
4
+ from .constants import DOCKER_COMPOSE_BASE, DOCKERFILE_CONTEXT
5
5
  from ..app_config import AppConfig
6
6
 
7
7
  class AppBuilder(Builder):
@@ -18,9 +18,5 @@ class AppBuilder(Builder):
18
18
  return os.path.join(self.dir_path, DOCKERFILE_CONTEXT)
19
19
 
20
20
  @property
21
- def proxy_base(self):
22
- return 'proxy_base'
23
-
24
- @property
25
- def proxy_docker_file_path(self):
26
- return os.path.join(self.dir_path, DOCKERFILE_PROXY)
21
+ def stoobly_base(self):
22
+ return 'stoobly_base'
@@ -3,7 +3,6 @@ DOCKER_COMPOSE_BASE = '.docker-compose.base.yml'
3
3
  DOCKER_COMPOSE_BASE_TEMPLATE = '.docker-compose.base.template.yml'
4
4
  DOCKER_COMPOSE_CUSTOM = 'docker-compose.yml'
5
5
  DOCKERFILE_CONTEXT = '.Dockerfile.context'
6
- DOCKERFILE_PROXY = '.Dockerfile.proxy'
7
6
  DOCKERFILE_SERVICE = 'Dockerfile.source'
8
7
  GATEWAY_NETWORK = 'gateway'
9
8
 
@@ -2,7 +2,7 @@ import os
2
2
  import pdb
3
3
 
4
4
  from ...app_config import AppConfig
5
- from ...constants import SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV, STOOBLY_HOME_DIR
5
+ from ...constants import SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV, SERVICE_NAME, STOOBLY_HOME_DIR, WORKFLOW_NAME
6
6
  from ...service_config import ServiceConfig
7
7
  from ..app_builder import AppBuilder
8
8
  from ..builder import Builder
@@ -44,6 +44,13 @@ class ServiceBuilder(Builder):
44
44
  def configure_base_service(self):
45
45
  return self.services.get(self.configure_base)
46
46
 
47
+ @property
48
+ def extends_service(self):
49
+ if self.config.detached:
50
+ return self.app_builder.stoobly_base
51
+ else:
52
+ return self.app_builder.context_base
53
+
47
54
  @property
48
55
  def proxy_base(self):
49
56
  return f"{self.service_name}.proxy_base"
@@ -52,10 +59,6 @@ class ServiceBuilder(Builder):
52
59
  def proxy_base_service(self):
53
60
  return self.services.get(self.proxy_base)
54
61
 
55
- @property
56
- def service_mount(self):
57
- return f".:{STOOBLY_HOME_DIR}"
58
-
59
62
  @property
60
63
  def service_name(self):
61
64
  return self.__service_name
@@ -80,9 +83,8 @@ class ServiceBuilder(Builder):
80
83
  },
81
84
  'extends': {
82
85
  'file': os.path.relpath(self.app_builder.compose_file_path, self.dir_path),
83
- 'service': self.app_builder.proxy_base
86
+ 'service': self.extends_service
84
87
  },
85
- 'volumes': [self.service_mount]
86
88
  })
87
89
 
88
90
  args[SERVICE_HOSTNAME_ENV] = f"{SERVICE_HOSTNAME}"
@@ -90,13 +92,12 @@ class ServiceBuilder(Builder):
90
92
  def build_init_base(self):
91
93
  environment = {}
92
94
  self.with_service(self.init_base, {
93
- 'command': ['bin/.init', 'dist'],
95
+ 'command': ['bin/.init'],
94
96
  'environment': environment,
95
97
  'extends': {
96
98
  'file': os.path.relpath(self.app_builder.compose_file_path, self.dir_path),
97
- 'service': self.app_builder.context_base
99
+ 'service': self.extends_service
98
100
  },
99
- 'volumes': [self.service_mount]
100
101
  })
101
102
 
102
103
  def build_configure_base(self):
@@ -106,7 +107,7 @@ class ServiceBuilder(Builder):
106
107
  'environment': environment,
107
108
  'extends': {
108
109
  'file': os.path.relpath(self.app_builder.compose_file_path, self.dir_path),
109
- 'service': self.app_builder.context_base
110
+ 'service': self.extends_service
110
111
  }
111
112
  })
112
113
 
@@ -3,12 +3,13 @@ import pdb
3
3
 
4
4
  from typing import List
5
5
 
6
+ from stoobly_agent.config.data_dir import DATA_DIR_NAME
7
+
6
8
  from ...constants import (
7
- COMPOSE_TEMPLATE, STOOBLY_HOME_DIR, SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV, SERVICE_NAME_ENV,
9
+ COMPOSE_TEMPLATE, DOCKER_NAMESPACE, STOOBLY_HOME_DIR, SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV, SERVICE_NAME_ENV,
8
10
  SERVICE_PORT, SERVICE_PORT_ENV, SERVICE_SCHEME, SERVICE_SCHEME_ENV,
9
11
  WORKFLOW_CONTAINER_CONFIGURE_TEMPLATE, WORKFLOW_CONTAINER_INIT_TEMPLATE, WORKFLOW_CONTAINER_PROXY_TEMPLATE, WORKFLOW_NAME_ENV
10
12
  )
11
- from ...templates.constants import SERVICE_HOSTNAME_BUILD_ARG
12
13
  from ..builder import Builder
13
14
  from ..service.builder import ServiceBuilder
14
15
 
@@ -21,13 +22,15 @@ class WorkflowBuilder(Builder):
21
22
 
22
23
  self.__context = '../'
23
24
  self.__profiles = [self.__workflow_name]
24
- self.__workdir = os.path.join(STOOBLY_HOME_DIR, self.workflow_name)
25
25
 
26
26
  if not service_builder:
27
27
  service_path = os.path.dirname(workflow_path)
28
28
  service_builder = ServiceBuilder(service_path)
29
29
 
30
30
  self.__service_builder = service_builder
31
+ self.__working_dir = os.path.join(
32
+ STOOBLY_HOME_DIR, DATA_DIR_NAME, DOCKER_NAMESPACE, self.service_builder.service_name, self.workflow_name
33
+ )
31
34
 
32
35
  if self.config.hostname:
33
36
  self.with_public_network()
@@ -58,13 +61,6 @@ class WorkflowBuilder(Builder):
58
61
  def context(self):
59
62
  return self.__context
60
63
 
61
- @property
62
- def context_build(self):
63
- return {
64
- 'context': self.context,
65
- 'dockerfile': self.context_docker_file_path,
66
- }
67
-
68
64
  @property
69
65
  def context_docker_file_path(self):
70
66
  return os.path.relpath(self.service_builder.app_builder.context_docker_file_path, self.service_path)
@@ -81,21 +77,6 @@ class WorkflowBuilder(Builder):
81
77
  def proxy(self):
82
78
  return WORKFLOW_CONTAINER_PROXY_TEMPLATE.format(service_name=self.namespace)
83
79
 
84
- @property
85
- def proxy_build(self):
86
- args = {}
87
- args[SERVICE_HOSTNAME_BUILD_ARG] = SERVICE_HOSTNAME
88
-
89
- return {
90
- 'args': args,
91
- 'context': self.context,
92
- 'dockerfile': self.proxy_docker_file_path,
93
- }
94
-
95
- @property
96
- def proxy_docker_file_path(self):
97
- return os.path.relpath(self.service_builder.app_builder.proxy_docker_file_path, self.service_path)
98
-
99
80
  @property
100
81
  def service_builder(self):
101
82
  return self.__service_builder
@@ -128,19 +109,21 @@ class WorkflowBuilder(Builder):
128
109
  volumes = []
129
110
 
130
111
  service = {
131
- 'build': self.context_build,
132
112
  'environment': environment,
133
113
  'extends': self.service_builder.build_extends_init_base(self.dir_path),
134
114
  'profiles': self.profiles,
135
115
  'volumes': volumes,
136
- 'working_dir': self.__workdir,
116
+ 'working_dir': self.__working_dir,
137
117
  }
138
118
 
139
119
  if self.config.hostname:
140
120
  self.__with_url_environment(environment)
141
121
 
142
122
  if self.config.detached:
123
+ # Mount named volume
143
124
  volumes.append(f"{self.service_builder.service_name}:{STOOBLY_HOME_DIR}/.stoobly")
125
+ # Mount docker folder
126
+ volumes.append(f"../..:{STOOBLY_HOME_DIR}/.stoobly/docker")
144
127
 
145
128
  self.with_service(self.init, service)
146
129
 
@@ -154,13 +137,12 @@ class WorkflowBuilder(Builder):
154
137
  volumes = []
155
138
 
156
139
  service = {
157
- 'build': self.context_build,
158
140
  'depends_on': depends_on,
159
141
  'environment': environment,
160
142
  'extends': self.service_builder.build_extends_configure_base(self.dir_path),
161
143
  'profiles': self.profiles,
162
144
  'volumes': volumes,
163
- 'working_dir': self.__workdir,
145
+ 'working_dir': self.__working_dir,
164
146
  }
165
147
 
166
148
  if self.config.hostname:
@@ -173,6 +155,7 @@ class WorkflowBuilder(Builder):
173
155
 
174
156
  if self.config.detached:
175
157
  volumes.append(f"{self.service_builder.service_name}:{STOOBLY_HOME_DIR}/.stoobly")
158
+ volumes.append(f"../..:{STOOBLY_HOME_DIR}/.stoobly/docker")
176
159
 
177
160
  self.with_service(self.configure, service)
178
161
 
@@ -187,14 +170,13 @@ class WorkflowBuilder(Builder):
187
170
  volumes = []
188
171
 
189
172
  service = {
190
- 'build': self.proxy_build,
191
173
  'depends_on': depends_on,
192
174
  'environment': environment,
193
175
  'extends': self.service_builder.build_extends_proxy_base(self.dir_path),
194
176
  'networks': networks,
195
177
  'profiles': self.profiles,
196
178
  'volumes': volumes,
197
- 'working_dir': self.__workdir,
179
+ 'working_dir': self.__working_dir,
198
180
  }
199
181
 
200
182
  if self.configure in self.services:
@@ -217,6 +199,7 @@ class WorkflowBuilder(Builder):
217
199
 
218
200
  if self.config.detached:
219
201
  volumes.append(f"{self.service_builder.service_name}:{STOOBLY_HOME_DIR}/.stoobly")
202
+ volumes.append(f"../..:{STOOBLY_HOME_DIR}/.stoobly/docker")
220
203
 
221
204
  self.with_service(self.proxy, service)
222
205
 
@@ -1,6 +1,7 @@
1
+ import os
1
2
  import pdb
2
3
 
3
- from ...constants import SERVICE_HOSTNAME, SERVICE_PORT
4
+ from ...constants import SERVICE_HOSTNAME, SERVICE_PORT, STOOBLY_CERTS_DIR
4
5
  from .builder import WorkflowBuilder
5
6
 
6
7
  class MockDecorator():
@@ -20,7 +21,6 @@ class MockDecorator():
20
21
  config = self.service_builder.config
21
22
 
22
23
  command = [
23
- '--certs', f"/etc/ssl/certs/{SERVICE_HOSTNAME}-joined.pem",
24
24
  '--headless',
25
25
  '--intercept',
26
26
  '--lifecycle-hooks-path', 'lifecycle_hooks.py',
@@ -30,6 +30,10 @@ class MockDecorator():
30
30
  '--ssl-insecure'
31
31
  ]
32
32
 
33
+ if config.scheme == 'https':
34
+ command.append('--certs')
35
+ command.append(os.path.join(STOOBLY_CERTS_DIR, f"{SERVICE_HOSTNAME}-joined.pem"))
36
+
33
37
  services = self.__workflow_builder.services
34
38
  proxy_name = self.__workflow_builder.proxy
35
39
  proxy_service = services.get(proxy_name) or {}