stoobly-agent 1.0.9__py3-none-any.whl → 1.0.11__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 CHANGED
@@ -1,2 +1,2 @@
1
1
  COMMAND = 'stoobly-agent'
2
- VERSION = '1.0.9'
2
+ VERSION = '1.0.11'
@@ -13,6 +13,7 @@ class App():
13
13
  self.__ca_certs_dir_path = kwargs.get('ca_certs_dir_path') or data_dir.mitmproxy_conf_dir_path
14
14
  self.__certs_dir_path = data_dir.certs_dir_path
15
15
  self.__context_dir_path = data_dir.context_dir_path
16
+ self.__data_dir = data_dir
16
17
  self.__dir_path = path
17
18
  self.__name = os.path.basename(self.__dir_path)
18
19
  self.__network = os.path.basename(self.__dir_path)
@@ -46,6 +47,10 @@ class App():
46
47
  self.__validate_path(v)
47
48
  self.__context_dir_path = v
48
49
 
50
+ @property
51
+ def data_dir(self):
52
+ return self.__data_dir
53
+
49
54
  @property
50
55
  def data_dir_path(self):
51
56
  return os.path.join(self.context_dir_path, DATA_DIR_NAME)
@@ -19,6 +19,6 @@ class AppCreateCommand(AppCommand):
19
19
  self.app.copy_folders_and_hidden_files(self.app_templates_root_dir, dest)
20
20
 
21
21
  with open(os.path.join(dest, '.gitignore'), 'w') as fp:
22
- fp.write("\n".join(['**/.env', '**/.config.yml']))
22
+ fp.write("\n".join(['**/.env']))
23
23
 
24
24
  self.app_config.write()
@@ -4,6 +4,7 @@ from stoobly_agent.config.data_dir import DATA_DIR_NAME
4
4
 
5
5
 
6
6
  APP_NETWORK_ENV = 'APP_NETWORK'
7
+ BIN_FOLDER_NAME = 'bin'
7
8
  CA_CERTS_DIR_ENV = 'CA_CERTS_DIR'
8
9
  CERTS_DIR_ENV = 'CERTS_DIR'
9
10
  COMPOSE_TEMPLATE = '.docker-compose.{workflow}.yml'
@@ -12,6 +13,7 @@ CONTEXT_DIR_ENV = 'CONTEXT_DIR'
12
13
  DOCKER_NAMESPACE = 'docker'
13
14
  ENV_FILE = '.env'
14
15
  FIXTURES_FOLDER_NAME = 'fixtures'
16
+ NAMESERVERS_FILE = '.nameservers'
15
17
  SERVICE_DETACHED = '${SERVICE_DETACHED}'
16
18
  SERVICE_DETACHED_ENV = 'SERVICE_DETACHED'
17
19
  SERVICE_DOCKER_COMPOSE_PATH = '${SERVICE_DOCKER_COMPOSE_PATH}'
@@ -7,9 +7,10 @@ from ...constants import (
7
7
  COMPOSE_TEMPLATE, SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV, SERVICE_NAME_ENV, SERVICE_PORT, SERVICE_PORT_ENV, SERVICE_SCHEME,
8
8
  SERVICE_SCHEME_ENV, STOOBLY_HOME_DIR, WORKFLOW_NAME_ENV
9
9
  )
10
+ from ...templates.constants import SERVICE_HOSTNAME_BUILD_ARG
11
+ from ...workflow_env import WorkflowEnv
10
12
  from ..builder import Builder
11
13
  from ..service.builder import ServiceBuilder
12
- from ...templates.constants import SERVICE_HOSTNAME_BUILD_ARG
13
14
 
14
15
  class WorkflowBuilder(Builder):
15
16
 
@@ -2,7 +2,9 @@ import pdb
2
2
 
3
3
  from urllib.parse import urlparse
4
4
 
5
- from ...constants import SERVICE_DNS, SERVICE_HOSTNAME, SERVICE_PORT
5
+ from stoobly_agent.config.data_dir import DataDir
6
+
7
+ from ...constants import SERVICE_DNS, SERVICE_DNS_ENV, SERVICE_HOSTNAME, SERVICE_PORT
6
8
  from .builder import WorkflowBuilder
7
9
 
8
10
  class ReverseProxyDecorator():
@@ -57,7 +59,7 @@ class ReverseProxyDecorator():
57
59
  # If we are reverse proxying to potentially an external host,
58
60
  # Docker's embedded DNS will use the host's /etc/host file as part of the resolution process
59
61
  # This can lead the hostname to resolve to localhost instead of the service's actual IP address
60
- if config.dns and not config.detached:
62
+ if not config.detached:
61
63
  service['dns'] = SERVICE_DNS
62
64
 
63
65
  services[proxy_name] = service
@@ -1,16 +1,11 @@
1
1
  # Wraps the .config.yml file in the service folder
2
-
3
- import dns.resolver
4
2
  import pdb
5
- import subprocess
6
- import re
7
3
 
8
4
  from .config import Config
9
5
  from .constants import (
10
6
  SERVICE_DETACHED_ENV,
11
7
  SERVICE_DOCKER_COMPOSE_PATH_ENV,
12
8
  SERVICE_HOSTNAME_ENV,
13
- SERVICE_DNS_ENV,
14
9
  SERVICE_PRIORITY_ENV,
15
10
  SERVICE_PORT_ENV,
16
11
  SERVICE_PROXY_MODE_ENV,
@@ -25,7 +20,6 @@ class ServiceConfig(Config):
25
20
  self.__detached = None
26
21
  self.__docker_compose_path = None
27
22
  self.__hostname = None
28
- self.__dns = None
29
23
  self.__port = None
30
24
  self.__priority = None
31
25
  self.__proxy_mode = None
@@ -75,28 +69,6 @@ class ServiceConfig(Config):
75
69
  def hostname(self, v):
76
70
  self.__hostname = v
77
71
 
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
72
  @property
101
73
  def port(self):
102
74
  if not self.__port:
@@ -147,9 +119,6 @@ class ServiceConfig(Config):
147
119
  def load(self, config = None):
148
120
  config = config or self.read()
149
121
 
150
- # Do not load dns from config, have it dynamically determined
151
- #self.dns = config.get(SERVICE_DNS_ENV)
152
-
153
122
  self.detached = config.get(SERVICE_DETACHED_ENV)
154
123
  self.docker_compose_path = config.get(SERVICE_DOCKER_COMPOSE_PATH_ENV)
155
124
  self.hostname = config.get(SERVICE_HOSTNAME_ENV)
@@ -167,9 +136,6 @@ class ServiceConfig(Config):
167
136
  if self.hostname:
168
137
  config[SERVICE_HOSTNAME_ENV] = self.hostname
169
138
 
170
- if self.dns:
171
- config[SERVICE_DNS_ENV] = self.dns
172
-
173
139
  if self.port:
174
140
  config[SERVICE_PORT_ENV] = self.port
175
141
 
@@ -183,32 +149,4 @@ class ServiceConfig(Config):
183
149
 
184
150
  config[SERVICE_PROXY_MODE_ENV] = self.proxy_mode
185
151
 
186
- super().write(config)
187
-
188
- def __find_dns(self):
189
- dns_resolver = dns.resolver.Resolver()
190
- nameservers = dns_resolver.nameservers
191
-
192
- # If systemd-resolved is not used
193
- if nameservers != ['127.0.0.53']:
194
- return nameservers
195
-
196
- # Run the `resolvectl status` command and capture its output
197
- result = subprocess.run(['resolvectl', 'status'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
198
-
199
- # Check if the command ran successfully
200
- if result.returncode != 0:
201
- return []
202
-
203
- # Extract the DNS servers using a regular expression
204
- #dns_servers = re.findall(r'DNS Servers: ([\d.]+(?:, [\d.]+)*)', result.stdout)
205
- pattern = re.compile('DNS Servers:(.*?)DNS Domain', re.DOTALL)
206
- match = re.findall(pattern, result.stdout)
207
-
208
- if not match:
209
- return []
210
-
211
- # Split the DNS servers string into a list
212
- dns_servers = match[0].strip().split("\n")
213
- return list(map(lambda dns_server: dns_server.strip(), dns_servers))
214
-
152
+ super().write(config)
@@ -21,6 +21,7 @@ workflow_run_options=$${STOOBLY_WORKFLOW_RUN_OPTIONS:+$$STOOBLY_WORKFLOW_RUN_OPT
21
21
 
22
22
  app_data_dir=$(app_dir)/.stoobly
23
23
  data_dir=$(context_dir)/.stoobly
24
+ app_tmp_dir=$(app_data_dir)/tmp
24
25
 
25
26
  # Commands
26
27
  docker_compose_command=docker compose
@@ -41,71 +42,82 @@ workflow_run_env=export APP_DIR="$(app_dir)" && export CERTS_DIR="$(certs_dir)"
41
42
  workflow_run=$(workflow_run_env) && $(source_env) && bash "$(workflow_run_script)"
42
43
 
43
44
  certs:
44
- export EXEC_COMMAND=bin/.mkcert && \
45
+ @export EXEC_COMMAND=bin/.mkcert && \
45
46
  $(stoobly_exec)
47
+ nameservers:
48
+ @if [ -f /etc/resolv.conf ]; then \
49
+ nameserver=$$(grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' /etc/resolv.conf | tr -d '\n') && \
50
+ if [ "$$nameserver" = "127.0.0.53" ]; then \
51
+ echo "Nameserver is 127.0.0.53. Checking resolvectl status..."; \
52
+ nameserver=$$(resolvectl status | sed -n '/DNS Servers:/s/.*DNS Servers:\s*\([^ ]*\).*/\1/p' | head -n 1); \
53
+ fi; \
54
+ echo "$$nameserver" > $(app_tmp_dir)/.nameservers; \
55
+ else \
56
+ echo "/etc/resolv.conf not found."; \
57
+ fi
46
58
  intercept/disable:
47
- export EXEC_COMMAND=bin/.disable && \
59
+ @export EXEC_COMMAND=bin/.disable && \
48
60
  $(stoobly_exec)
49
61
  intercept/enable:
50
- export EXEC_COMMAND=bin/.enable && \
62
+ @export EXEC_COMMAND=bin/.enable && \
51
63
  export EXEC_ARGS=$(scenario_key) && \
52
64
  $(stoobly_exec)
53
- mock: certs
54
- export EXEC_COMMAND=bin/.run && \
65
+ mock: nameservers
66
+ @export EXEC_COMMAND=bin/.run && \
55
67
  export EXEC_OPTIONS="$(workflow_run_options)$(options)" && \
56
68
  export EXEC_ARGS="mock" && \
57
69
  $(stoobly_exec_run) && \
58
70
  $(workflow_run)
59
71
  mock/stop:
60
- export EXEC_COMMAND=bin/.stop && \
72
+ @export EXEC_COMMAND=bin/.stop && \
61
73
  export EXEC_OPTIONS="$(options)" && \
62
74
  export EXEC_ARGS="mock" && \
63
75
  $(stoobly_exec_run) && \
64
76
  $(workflow_run)
65
- record: certs
66
- export EXEC_COMMAND=bin/.run && \
77
+ record: nameservers
78
+ @export EXEC_COMMAND=bin/.run && \
67
79
  export EXEC_OPTIONS="$(workflow_run_options)$(options)" && \
68
80
  export EXEC_ARGS="record" && \
69
81
  $(stoobly_exec_run) && \
70
82
  $(workflow_run)
71
83
  record/stop:
72
- export EXEC_COMMAND=bin/.stop && \
84
+ @export EXEC_COMMAND=bin/.stop && \
73
85
  export EXEC_OPTIONS="$(options)" && \
74
86
  export EXEC_ARGS="record" && \
75
87
  $(stoobly_exec_run) && \
76
88
  $(workflow_run)
77
89
  scenario/create:
78
90
  # Create a scenario
79
- export EXEC_COMMAND=bin/.create && \
91
+ @export EXEC_COMMAND=bin/.create && \
80
92
  export EXEC_OPTIONS="$(options)" && \
81
93
  export EXEC_ARGS="$(name)" && \
82
94
  $(stoobly_exec)
83
95
  scenario/delete:
84
96
  # Delete a scenario
85
- export EXEC_COMMAND=bin/.delete && \
97
+ @export EXEC_COMMAND=bin/.delete && \
86
98
  export EXEC_OPTIONS="$(options)" && \
87
99
  export EXEC_ARGS="$(key)" && \
88
100
  $(stoobly_exec)
89
101
  scenario/reset:
90
102
  # Resets a scenario to its last snapshot
91
- export EXEC_COMMAND=bin/.reset && \:
103
+ @export EXEC_COMMAND=bin/.reset && \:
92
104
  export EXEC_OPTIONS="$(options)" && \
93
105
  export EXEC_ARGS="$(key)" && \
94
106
  $(stoobly_exec)
95
107
  scenario/snapshot:
96
108
  # Create committable files for a scenario
97
- export EXEC_COMMAND=bin/.snapshot && \
109
+ @export EXEC_COMMAND=bin/.snapshot && \
98
110
  export EXEC_OPTIONS="$(options)" && \
99
111
  export EXEC_ARGS="$(key)" && \
100
112
  $(stoobly_exec)
101
113
  test:
102
- export EXEC_COMMAND=bin/.run && \
114
+ @export EXEC_COMMAND=bin/.run && \
103
115
  export EXEC_OPTIONS="$(workflow_run_options)$(options)" && \
104
116
  export EXEC_ARGS="test" && \
105
117
  $(stoobly_exec_run) && \
106
118
  $(workflow_run)
107
119
  test/stop:
108
- export EXEC_COMMAND=bin/.stop && \
120
+ @export EXEC_COMMAND=bin/.stop && \
109
121
  export EXEC_OPTIONS="$(options)" && \
110
122
  export EXEC_ARGS="test" && \
111
123
  $(stoobly_exec_run) && \
@@ -5,6 +5,8 @@ workflow=$1
5
5
 
6
6
  mkdir -p .stoobly/tmp
7
7
 
8
+ stoobly-agent scaffold app mkcert
9
+
8
10
  stoobly-agent scaffold workflow run \
9
11
  --app-dir-path "$(pwd)" \
10
12
  --dry-run \
@@ -3,6 +3,8 @@
3
3
  extra_options=$EXEC_OPTIONS
4
4
  workflow=$1
5
5
 
6
+ mkdir -p .stoobly/tmp
7
+
6
8
  stoobly-agent scaffold workflow stop \
7
9
  --app-dir-path "$(pwd)" \
8
10
  --dry-run \
@@ -1,4 +1,5 @@
1
1
  import pdb
2
+ import re
2
3
  from time import sleep
3
4
 
4
5
  import docker
@@ -31,7 +32,7 @@ class ValidateCommand():
31
32
 
32
33
  init_container = self.__get_container(init_container_name)
33
34
  logs = init_container.logs()
34
- if logs:
35
+ if logs and re.search('error', str(logs), re.IGNORECASE):
35
36
  raise ScaffoldValidateException(f"Error logs potentially detected in: {init_container_name}")
36
37
  if init_container.status != 'exited' or init_container.attrs['State']['ExitCode'] != 0:
37
38
  raise ScaffoldValidateException(f"init container has not exited like expected: {init_container_name}")
@@ -6,7 +6,7 @@ from stoobly_agent.lib.logger import Logger
6
6
 
7
7
  from .app import App
8
8
  from .config import Config
9
- from .constants import COMPOSE_TEMPLATE, CONFIG_FILE, ENV_FILE, FIXTURES_FOLDER_NAME
9
+ from .constants import BIN_FOLDER_NAME, COMPOSE_TEMPLATE, CONFIG_FILE, ENV_FILE, FIXTURES_FOLDER_NAME
10
10
  from .docker.constants import DOCKER_COMPOSE_CUSTOM
11
11
  from .service_command import ServiceCommand
12
12
 
@@ -19,6 +19,10 @@ class WorkflowCommand(ServiceCommand):
19
19
 
20
20
  self.__workflow_name = kwargs['workflow_name']
21
21
 
22
+ @property
23
+ def bin_dir_path(self):
24
+ return os.path.join(self.workflow_path, BIN_FOLDER_NAME)
25
+
22
26
  @property
23
27
  def compose_path(self):
24
28
  return os.path.join(
@@ -0,0 +1,20 @@
1
+ from .config import Config
2
+ from .constants import ENV_FILE
3
+ from .env import Env
4
+
5
+ class WorkflowEnv(Config):
6
+
7
+ def __init__(self, dir: str):
8
+ super().__init__(dir, ENV_FILE)
9
+
10
+ self.__env_vars = {}
11
+
12
+ def get(self, key):
13
+ return self.__env_vars.get(key)
14
+
15
+ def load(self):
16
+ self.__env_vars = self.read()
17
+
18
+ def write(self, env_vars: dict):
19
+ Env(self.path).write(env_vars)
20
+ self.__env_vars = env_vars
@@ -1,5 +1,8 @@
1
+ import dns.resolver
1
2
  import os
2
3
  import pdb
4
+ import subprocess
5
+ import re
3
6
 
4
7
  from typing import TypedDict
5
8
 
@@ -7,9 +10,12 @@ from stoobly_agent.config.data_dir import DataDir
7
10
  from stoobly_agent.lib.logger import Logger
8
11
 
9
12
  from .app import App
10
- from .constants import APP_NETWORK_ENV, CA_CERTS_DIR_ENV, CERTS_DIR_ENV, CONTEXT_DIR_ENV, SERVICE_NAME_ENV, USER_ID_ENV, WORKFLOW_NAME_ENV
11
- from .env import Env
13
+ from .constants import (
14
+ APP_NETWORK_ENV, CA_CERTS_DIR_ENV, CERTS_DIR_ENV, CONTEXT_DIR_ENV, NAMESERVERS_FILE,
15
+ SERVICE_DNS_ENV, SERVICE_NAME_ENV, USER_ID_ENV, WORKFLOW_NAME_ENV
16
+ )
12
17
  from .workflow_command import WorkflowCommand
18
+ from .workflow_env import WorkflowEnv
13
19
 
14
20
  LOG_ID = 'WorkflowRunCommand'
15
21
 
@@ -62,6 +68,20 @@ class WorkflowRunCommand(WorkflowCommand):
62
68
  def extra_compose_path(self):
63
69
  return self.__extra_compose_path
64
70
 
71
+ @property
72
+ def nameservers(self):
73
+ path = self.nameservers_path
74
+ if not os.path.exists(path):
75
+ return []
76
+
77
+ with open(path, 'r') as fp:
78
+ nameservers = fp.read()
79
+ return nameservers.split("\n")
80
+
81
+ @property
82
+ def nameservers_path(self):
83
+ return os.path.join(self.app.data_dir.tmp_dir_path, NAMESERVERS_FILE)
84
+
65
85
  @property
66
86
  def network(self):
67
87
  return self.__network
@@ -110,6 +130,7 @@ class WorkflowRunCommand(WorkflowCommand):
110
130
  command.append('-d')
111
131
 
112
132
  command.append('--build')
133
+ command.append('--pull always')
113
134
 
114
135
  self.write_env()
115
136
 
@@ -136,6 +157,27 @@ class WorkflowRunCommand(WorkflowCommand):
136
157
 
137
158
  return ' '.join(command)
138
159
 
160
+ def write_nameservers(self):
161
+ # If hostname is set then the service is external and we will need to configure the container's DNS.
162
+ # If we don't configure the container's DNS, then Docker's embedded DNS will potentially
163
+ # use configuration from the host's /etc/hosts file. The user may have configured their
164
+ # /etc/hosts file to resolve requests to localhost
165
+ #
166
+ # See:
167
+ # https://forums.docker.com/t/docker-127-0-0-11-resolver-should-use-host-etc-hosts-file/55157
168
+ # https://docs.docker.com/network/#dns-services
169
+ #
170
+ # TODO: ideally we want to know if the service is built locally, if so, then no need to set DNS
171
+ # since Docker's embedded DNS will resolve to it
172
+ dns_resolver = dns.resolver.Resolver()
173
+
174
+ with open(self.nameservers_path, 'w') as fp:
175
+ nameservers = self.__find_nameservers(dns_resolver)
176
+ ipv4_pattern = re.compile(r'^((25[0-5]|2[0-4][0-9]|1?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9][0-9]?)$')
177
+ nameservers = [ip for ip in nameservers if ipv4_pattern.match(ip)]
178
+ if nameservers:
179
+ fp.write("\n".join(nameservers))
180
+
139
181
  def write_env(self):
140
182
  _config = {}
141
183
  _config[CA_CERTS_DIR_ENV] = self.ca_certs_dir_path
@@ -148,7 +190,36 @@ class WorkflowRunCommand(WorkflowCommand):
148
190
  if self.network:
149
191
  _config[APP_NETWORK_ENV] = self.network
150
192
 
151
- env_vars = self.config(_config)
152
- env_path = self.workflow_env_path
153
- Env(env_path).write(env_vars)
193
+ nameservers = self.nameservers
194
+ if nameservers:
195
+ _config[SERVICE_DNS_ENV] = nameservers[0]
154
196
 
197
+ env_vars = self.config(_config)
198
+ WorkflowEnv(self.workflow_path).write(env_vars)
199
+ return env_vars
200
+
201
+ def __find_nameservers(self, dns_resolver: dns.resolver.Resolver):
202
+ nameservers = dns_resolver.nameservers
203
+
204
+ # If systemd-resolved is not used
205
+ if nameservers != ['127.0.0.53']:
206
+ return nameservers
207
+
208
+ # Run the `resolvectl status` command and capture its output
209
+ result = subprocess.run(['resolvectl', 'status'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
210
+
211
+ # Check if the command ran successfully
212
+ if result.returncode != 0:
213
+ return []
214
+
215
+ # Extract the DNS servers using a regular expression
216
+ #dns_servers = re.findall(r'DNS Servers: ([\d.]+(?:, [\d.]+)*)', result.stdout)
217
+ pattern = re.compile('DNS Servers:(.*?)DNS Domain', re.DOTALL)
218
+ match = re.findall(pattern, result.stdout)
219
+
220
+ if not match:
221
+ return []
222
+
223
+ # Split the DNS servers string into a list
224
+ dns_servers = match[0].strip().split("\n")
225
+ return list(map(lambda dns_server: dns_server.strip(), dns_servers))
@@ -367,8 +367,12 @@ def run(**kwargs):
367
367
 
368
368
  # Before services can be started, their network needs to be created
369
369
  if len(commands) > 0:
370
- create_network_command = commands[0].create_network()
370
+ command = commands[0]
371
+ create_network_command = command.create_network()
372
+
371
373
  if not kwargs['dry_run']:
374
+ command.write_nameservers()
375
+
372
376
  exec_stream(create_network_command)
373
377
  else:
374
378
  print(create_network_command)
@@ -418,7 +422,6 @@ def validate(**kwargs):
418
422
  print(f"\nFatal Scaffold Validation Exception: {sve}", file=sys.stderr)
419
423
  sys.exit(1)
420
424
 
421
-
422
425
  scaffold.add_command(app)
423
426
  scaffold.add_command(service)
424
427
  scaffold.add_command(workflow)
@@ -473,5 +476,4 @@ def __workflow_build(app, **kwargs):
473
476
  headless=kwargs['headless'],
474
477
  template=kwargs['template'],
475
478
  workflow_decorators=workflow_decorators
476
- )
477
-
479
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: stoobly-agent
3
- Version: 1.0.9
3
+ Version: 1.0.11
4
4
  Summary: Record, mock, and test HTTP(s) requests. CLI agent for Stoobly
5
5
  License: Apache-2.0
6
6
  Author: Matt Le
@@ -1,4 +1,4 @@
1
- stoobly_agent/__init__.py,sha256=r0VYJeYLDBgc5UvCAjDPGJ_KS3dTEnx7N7dyr9LmgzI,44
1
+ stoobly_agent/__init__.py,sha256=4ndlBfDCZW8uz1Z5ZYihu_3hi9biEC-Z6NJUmmeJqvI,45
2
2
  stoobly_agent/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  stoobly_agent/app/api/__init__.py,sha256=ctkB8KR-eXO0SFhj602huHiyvQ3PslFWd8fkcufgrAI,1000
4
4
  stoobly_agent/app/api/application_http_request_handler.py,sha256=jf4fkqjOiCeI2IM5Ro7ie0v_C6y0-7-5TIE_IKMPOfg,5513
@@ -67,13 +67,13 @@ stoobly_agent/app/cli/project_cli.py,sha256=EXjeLjbnq9PhfCjvyfZ0UnJ2tejeCS0SIAo3
67
67
  stoobly_agent/app/cli/report_cli.py,sha256=ZxJw0Xkx7KFZJn9e45BSKRKon8AD0Msrwy1fbPfbv0c,2543
68
68
  stoobly_agent/app/cli/request_cli.py,sha256=THNloW111l9MLE0oPg4y7hVXL1U7OXoz760g0A1CtJ0,7747
69
69
  stoobly_agent/app/cli/scaffold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- stoobly_agent/app/cli/scaffold/app.py,sha256=y9es1fDnYwQ3s-Pp58KvSgkt8Chn7BTq16GBG5RmYpY,3555
70
+ stoobly_agent/app/cli/scaffold/app.py,sha256=jmOn0moveA4pgCgI6i_RzztaNh-GK17FaznU9B9tmsc,3648
71
71
  stoobly_agent/app/cli/scaffold/app_command.py,sha256=o6WV6tcMGBWJsPFdV2DD-m1Dq0cy3Q3SESokaU5hgp4,2061
72
72
  stoobly_agent/app/cli/scaffold/app_config.py,sha256=ZAHGovwxFy3zICfusj9_gUC_FBTIoB7KbPbQaGK8x1c,573
73
- stoobly_agent/app/cli/scaffold/app_create_command.py,sha256=G4q-arXJH0uf6kagiWk26VqKG4zpOngxvJappxIkt-0,568
73
+ stoobly_agent/app/cli/scaffold/app_create_command.py,sha256=1qdKvRvJDmDmYERvbhaUapsglOOWPEHpCj0o7U7bQfo,550
74
74
  stoobly_agent/app/cli/scaffold/command.py,sha256=klpsgL6V7b2DRHpN33pl-QlmntDkvDO_dsF5JziYnL8,245
75
75
  stoobly_agent/app/cli/scaffold/config.py,sha256=HZU5tkvr3dkPr4JMXZtrJlu2wxxO-134Em6jReFFcq0,688
76
- stoobly_agent/app/cli/scaffold/constants.py,sha256=nQiQdE6nd89sQHw4yoHmD6wKEYUDa6Dbxu7b8mu5Oy4,1507
76
+ stoobly_agent/app/cli/scaffold/constants.py,sha256=B9nUW7FIoq2PUSSkQue0MSG6U7WNsnIBGzvFzoA8PXI,1565
77
77
  stoobly_agent/app/cli/scaffold/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  stoobly_agent/app/cli/scaffold/docker/app_builder.py,sha256=IsXZFUumWEBA8NYDFdAohuKmxocoqHqlVFg0-E92QLI,621
79
79
  stoobly_agent/app/cli/scaffold/docker/builder.py,sha256=lNOvDxoLB1L8KSDrvoG4CUuWLAM2egLxwOWeV9Tf8H8,2832
@@ -85,15 +85,15 @@ stoobly_agent/app/cli/scaffold/docker/service/set_gateway_ports.py,sha256=jvlO5x
85
85
  stoobly_agent/app/cli/scaffold/docker/service/types.py,sha256=qB-yYHlu-PZDc0HYgTUvE5bWNpHxaSThC3JUG8okR1k,88
86
86
  stoobly_agent/app/cli/scaffold/docker/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
87
  stoobly_agent/app/cli/scaffold/docker/workflow/build_decorator.py,sha256=vbmME0cbN2EnNRlzQ2umj7Y3L7aZT-EHqEpkBFMfe8U,758
88
- stoobly_agent/app/cli/scaffold/docker/workflow/builder.py,sha256=OF0InBOw87tD6pJ-UtVurXHGExBeoez67ramxbAutcE,6864
88
+ stoobly_agent/app/cli/scaffold/docker/workflow/builder.py,sha256=z1yJ-fEb7trBR-4ADK1tZq2PbTt-iqsnutzvRnTrtf4,6904
89
89
  stoobly_agent/app/cli/scaffold/docker/workflow/decorators_factory.py,sha256=Mi6SEFpG2MG9pymPLbPTWBMfosi1ThRAs5DXfjBz4Iw,643
90
90
  stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py,sha256=D8PgYULERvWLaW1Vn3qspRTuNBoicuP2M1EZnQyvD_M,1080
91
- stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py,sha256=-nyqU9xyPZIywzef1zOBCElhganLsfjt7G0atKTm1Pw,2042
91
+ stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py,sha256=d2E0ba0ga2IjIE3v1VnLmZLgKiyBB15BerCtL0FyndI,2095
92
92
  stoobly_agent/app/cli/scaffold/env.py,sha256=e-Ve4p3RUgzFx22B3SIYttvJ_yLuDtA27oDACZ8n-6E,1140
93
93
  stoobly_agent/app/cli/scaffold/managed_services_docker_compose.py,sha256=-wLBXUi7DCWsfm5KzZzd_kdJKOTl1NT924XR7dyjbSY,574
94
94
  stoobly_agent/app/cli/scaffold/service.py,sha256=HzYTiQGfReYXEY0Iv4YjGpu5fjCicV61Wst4khmmURs,504
95
95
  stoobly_agent/app/cli/scaffold/service_command.py,sha256=xqifA0PM9xpXK3TiilplmIrJNR7VG7BO0HrLh74yyZw,1058
96
- stoobly_agent/app/cli/scaffold/service_config.py,sha256=ev53iZw7Ij1lGYedYelcNFNdtTM6zMmIqofBaFo4gNs,5617
96
+ stoobly_agent/app/cli/scaffold/service_config.py,sha256=XFwTgf1JTfVVWmVyGTIadtfxSoPaoUV-70l3lAtSCzU,3485
97
97
  stoobly_agent/app/cli/scaffold/service_create_command.py,sha256=bmLGgx9qnh-X_i2_XfdWSQIer0gGkaQx6lXZSIzy-LI,2793
98
98
  stoobly_agent/app/cli/scaffold/service_docker_compose.py,sha256=OMUN1-ujQYIZXxDvS4XBf5C9wGalQULkwOiBBQPZbHY,820
99
99
  stoobly_agent/app/cli/scaffold/service_workflow.py,sha256=sQ_Edy_wGHKMXpD0DmhnOWkGEKz7gSgEGNI8f7aXOdg,444
@@ -101,7 +101,7 @@ stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py,sha256=zvqKm
101
101
  stoobly_agent/app/cli/scaffold/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
102
102
  stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context,sha256=1Zm5_ROKZzFMAkMt8dluEJASI2CBi9d9If_Gch9FMNM,193
103
103
  stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.proxy,sha256=JfZOVALEmRE_hVEMIHTmem9Ln32qnfKOAUO1c5Z9fqw,1027
104
- stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=zfa8uZFGZEJV0cnSLvbQ1kctrLu5zuO7Kdpj6yK-yuU,4176
104
+ stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=S2kEyDPSOeTYpyLEjPqGZa-r3nf3vhe23WEpuiidtqM,4717
105
105
  stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml,sha256=LNNuygX6hMtmElxaO6jTIYq3psYmxNv7xax7ra6JzO4,407
106
106
  stoobly_agent/app/cli/scaffold/templates/app/Makefile,sha256=t7xRaCc9q3k7W34S0h9KX02GljSVwGpPnFmiLUvWxsw,80
107
107
  stoobly_agent/app/cli/scaffold/templates/app/build/.config.yml,sha256=8Wt8ZZ5irvBYYS44xGrR_EWlZDuXH9kyWmquzsh7s8g,19
@@ -154,9 +154,9 @@ stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.disable,sha256
154
154
  stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.enable,sha256=sfUSPG4uHdXX95BLgivXQYLbsLBP2DjJIiSTXRtvXuY,188
155
155
  stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.mkcert,sha256=vyHaXmvy-7oL2RD8rIxwT-fdJS5kXmB0yHK5fRMo_cM,46
156
156
  stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.reset,sha256=_pvbLk-ektsCHEh_egDtd6c0sVqCPunwUWggarfoli0,238
157
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.run,sha256=X_fs8iPIjNOD_2XMRIlA4mWtMDLwvp1lxJuPU4cBQYk,233
157
+ stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.run,sha256=Jkx7q0MO8pYCSnlOEAEkx2Odgb8xbUeylv_RLHDD8NI,268
158
158
  stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.snapshot,sha256=Kav1QNhKG7f0DBzc4-9dmxZMmmVTxmPqakT_W4kVYKk,241
159
- stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.stop,sha256=n9k-qnQXfG5J_71FxkteLg962ErT1wTs1juEDtbmUgM,209
159
+ stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.stop,sha256=qj5fRkBubAGGAKiFrjHPMVULDiRLMsIkEF5Al3uhQlo,232
160
160
  stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/mock/.docker-compose.mock.yml,sha256=Ba-jNMZUcq62kK_hLpaN7dkEwz3_ZS91aJOOJ8U3Ark,257
161
161
  stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/record/.docker-compose.record.yml,sha256=cbK8vJUnk8llJ6pIE65AxJxD6SSal2ugm5sKjtz3uRY,260
162
162
  stoobly_agent/app/cli/scaffold/templates/constants.py,sha256=TjuWAZuAbWxS1hZR4jViF1LTBzT8iKLIJE65AvWRKNI,1460
@@ -180,16 +180,17 @@ stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/init,sha256=YxWVVQMEd
180
180
  stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures/.keep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
181
  stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures.yml,sha256=8DW2LN5WYg1hxmZkqr8o5dxLgDxHtBARFSUiNjz009Y,226
182
182
  stoobly_agent/app/cli/scaffold/templates/workflow/test/lifecycle_hooks.py,sha256=U7mlzT_wBR3uhHSG6CAyt5tBUNAvdIrCw33gdB-F294,467
183
- stoobly_agent/app/cli/scaffold/validate_command.py,sha256=k2NCNy3pK7uPKg5wFrVDY1uMA_BDva2DwvGbI6aLWKM,2303
183
+ stoobly_agent/app/cli/scaffold/validate_command.py,sha256=Rc_z632OSZLPyA4FuhNGz6oGxKKNxaQbE4CRkPcJYdo,2362
184
184
  stoobly_agent/app/cli/scaffold/validate_exceptions.py,sha256=Jtjl4OkbbSRWm0hy7Kf_50zcFh2J324HhNcnwJKH_Oc,54
185
185
  stoobly_agent/app/cli/scaffold/workflow.py,sha256=_uur4wdlxZh-piZralqPNoggIkVJ9AICiJVOz4KqKQQ,1421
186
- stoobly_agent/app/cli/scaffold/workflow_command.py,sha256=V4Wfv9bgh5MlWAaW_68uudC1wsMcvcTogjZ7mvKDD74,3308
186
+ stoobly_agent/app/cli/scaffold/workflow_command.py,sha256=5fq0t8utfxUQGwJt8dqssBH7AKhsyNVA8PJhmztz0_4,3425
187
187
  stoobly_agent/app/cli/scaffold/workflow_copy_command.py,sha256=R9hh5dWVz7vGld7pENAA_a9gW56EkgG2K35nBQYXwyI,1462
188
188
  stoobly_agent/app/cli/scaffold/workflow_create_command.py,sha256=5xnRYrVb2KlSDARZFjLGGWeURXRu63OHoRLEhO-EAvw,3401
189
+ stoobly_agent/app/cli/scaffold/workflow_env.py,sha256=x8V5pJmIiklD3f2q2-qq-CORf4YaXYq_r2JpR2MmSwk,416
189
190
  stoobly_agent/app/cli/scaffold/workflow_log_command.py,sha256=FN-XyMVnulbassBuqeB21J_PQnOsr_LNs0Dg2tcDkjg,435
190
- stoobly_agent/app/cli/scaffold/workflow_run_command.py,sha256=WmEA0TZtEajKhbaauBLqTuH3--ODXtQ5-A33VqaEWoI,4463
191
+ stoobly_agent/app/cli/scaffold/workflow_run_command.py,sha256=CTa-JcaTtIwXvGXeVmvgAYEXnvAh9NnbWK_iXtRSnOU,7107
191
192
  stoobly_agent/app/cli/scaffold/workflow_validate_command.py,sha256=fhHciJXg_u32Wmh8us8LhgQj8D1SxkBADtuBBF4K0FM,4377
192
- stoobly_agent/app/cli/scaffold_cli.py,sha256=sB12SJIGDpz-_HuMjWMnA-psfggR2DyMsIw8E-ZQWpg,18513
193
+ stoobly_agent/app/cli/scaffold_cli.py,sha256=3bMMw5M2uTk0Z3KUB3VGyS9JiS3TCaEpbDSeL6RHUZI,18568
193
194
  stoobly_agent/app/cli/scenario_cli.py,sha256=3J1EiJOvunkfWrEkOsanw-XrKkOk78ij_GjBlE9p7CE,8229
194
195
  stoobly_agent/app/cli/snapshot_cli.py,sha256=XNxpTm5z3bnBGNGI3_XZIif0ypN62WqYfDmShL5fXg4,9965
195
196
  stoobly_agent/app/cli/trace_cli.py,sha256=K7E-vx3JUcqEDSWOdIOi_AieKNQz7dBfmRrVvKDkzFI,4605
@@ -720,8 +721,8 @@ stoobly_agent/test/mock_data/scaffold/docker-compose-local-service.yml,sha256=x7
720
721
  stoobly_agent/test/mock_data/scaffold/index.html,sha256=qJwuYajKZ4ihWZrJQ3BNObV5kf1VGnnm_vqlPJzdqLE,258
721
722
  stoobly_agent/test/mock_data/uspto.yaml,sha256=6U5se7C3o-86J4m9xpOk9Npias399f5CbfWzR87WKwE,7835
722
723
  stoobly_agent/test/test_helper.py,sha256=m_oAI7tmRYCNZdKfNqISWhMv3e44tjeYViQ3nTUfnos,1007
723
- stoobly_agent-1.0.9.dist-info/LICENSE,sha256=8QKGyy45eN76Zk52h8gu1DKX2B_gbWgZ3nzDLofEbaE,548
724
- stoobly_agent-1.0.9.dist-info/METADATA,sha256=UfKvxrEkLC-N9EWc4jXE4NIpWWurBq8hqznXxJRNjWI,3425
725
- stoobly_agent-1.0.9.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
726
- stoobly_agent-1.0.9.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
727
- stoobly_agent-1.0.9.dist-info/RECORD,,
724
+ stoobly_agent-1.0.11.dist-info/LICENSE,sha256=8QKGyy45eN76Zk52h8gu1DKX2B_gbWgZ3nzDLofEbaE,548
725
+ stoobly_agent-1.0.11.dist-info/METADATA,sha256=h-NGNvATfZVk3ILpiL8t3svqHQYCHtkR6RF7U8VCcrw,3426
726
+ stoobly_agent-1.0.11.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
727
+ stoobly_agent-1.0.11.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
728
+ stoobly_agent-1.0.11.dist-info/RECORD,,