stoobly-agent 1.9.9__py3-none-any.whl → 1.9.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 +1 -1
- stoobly_agent/app/cli/helpers/shell.py +9 -1
- stoobly_agent/app/cli/intercept_cli.py +1 -1
- stoobly_agent/app/cli/scaffold/app.py +6 -0
- stoobly_agent/app/cli/scaffold/app_command.py +1 -1
- stoobly_agent/app/cli/scaffold/app_config.py +14 -14
- stoobly_agent/app/cli/scaffold/app_create_command.py +7 -7
- stoobly_agent/app/cli/scaffold/command.py +3 -3
- stoobly_agent/app/cli/scaffold/constants.py +6 -3
- stoobly_agent/app/cli/scaffold/docker/service/builder.py +7 -3
- stoobly_agent/app/cli/scaffold/docker/service/configure_gateway.py +6 -6
- stoobly_agent/app/cli/scaffold/env.py +0 -2
- stoobly_agent/app/cli/scaffold/service_command.py +1 -1
- stoobly_agent/app/cli/scaffold/service_config.py +12 -7
- stoobly_agent/app/cli/scaffold/service_create_command.py +1 -1
- stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py +3 -2
- stoobly_agent/app/cli/scaffold/templates/app/.Makefile +15 -11
- stoobly_agent/app/cli/scaffold/templates/app/gateway/.docker-compose.base.template.yml +1 -1
- stoobly_agent/app/cli/scaffold/workflow_command.py +3 -3
- stoobly_agent/app/cli/scaffold/workflow_env.py +10 -3
- stoobly_agent/app/cli/scaffold/workflow_namesapce.py +41 -0
- stoobly_agent/app/cli/scaffold/workflow_run_command.py +15 -23
- stoobly_agent/app/cli/scaffold_cli.py +15 -16
- stoobly_agent/app/cli/types/workflow_run_command.py +18 -0
- {stoobly_agent-1.9.9.dist-info → stoobly_agent-1.9.11.dist-info}/METADATA +1 -1
- {stoobly_agent-1.9.9.dist-info → stoobly_agent-1.9.11.dist-info}/RECORD +29 -27
- {stoobly_agent-1.9.9.dist-info → stoobly_agent-1.9.11.dist-info}/LICENSE +0 -0
- {stoobly_agent-1.9.9.dist-info → stoobly_agent-1.9.11.dist-info}/WHEEL +0 -0
- {stoobly_agent-1.9.9.dist-info → stoobly_agent-1.9.11.dist-info}/entry_points.txt +0 -0
stoobly_agent/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
COMMAND = 'stoobly-agent'
|
2
|
-
VERSION = '1.9.
|
2
|
+
VERSION = '1.9.11'
|
@@ -1,10 +1,18 @@
|
|
1
|
+
import os
|
1
2
|
import subprocess
|
2
3
|
import sys
|
3
4
|
|
4
5
|
from dotenv import load_dotenv
|
5
6
|
|
7
|
+
DOTENV_PATH = 'STOOBLY_DOTENV_PATH'
|
8
|
+
|
6
9
|
def exec_stream(command):
|
7
|
-
|
10
|
+
dotenv_path = os.environ.get(DOTENV_PATH)
|
11
|
+
|
12
|
+
if dotenv_path and os.path.exists(dotenv_path):
|
13
|
+
load_dotenv(dotenv_path=dotenv_path)
|
14
|
+
else:
|
15
|
+
load_dotenv()
|
8
16
|
|
9
17
|
# Start the process
|
10
18
|
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
@@ -8,7 +8,7 @@ from stoobly_agent.lib.api.keys.project_key import ProjectKey
|
|
8
8
|
|
9
9
|
from .helpers.handle_config_update_service import handle_intercept_active_update, handle_order_update
|
10
10
|
|
11
|
-
settings = Settings.instance()
|
11
|
+
settings: Settings = Settings.instance()
|
12
12
|
|
13
13
|
mode_options = [mode.MOCK, mode.RECORD, mode.REPLAY]
|
14
14
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import hashlib
|
1
2
|
import os
|
2
3
|
import shutil
|
3
4
|
|
@@ -73,6 +74,11 @@ class App():
|
|
73
74
|
def data_dir_path(self):
|
74
75
|
return self.__data_dir_path
|
75
76
|
|
77
|
+
@property
|
78
|
+
def network(self):
|
79
|
+
# An app may contain one or more context dirs from which services will derive their mocks from
|
80
|
+
return hashlib.md5(self.context_dir_path.encode()).hexdigest()
|
81
|
+
|
76
82
|
@property
|
77
83
|
def scaffold_namespace_path(self):
|
78
84
|
return os.path.join(self.data_dir_path, self.scaffold_namespace)
|
@@ -1,16 +1,25 @@
|
|
1
1
|
from .config import Config
|
2
|
-
from .constants import
|
2
|
+
from .constants import APP_DOCKER_SOCKET_PATH_ENV, APP_NAME_ENV, APP_UI_PORT_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.__docker_socket_path = '/var/run/docker.sock'
|
9
10
|
self.__name = None
|
10
|
-
self.
|
11
|
+
self.__ui_port = None
|
11
12
|
|
12
13
|
self.load()
|
13
14
|
|
15
|
+
@property
|
16
|
+
def docker_socket_path(self):
|
17
|
+
return self.__docker_socket_path
|
18
|
+
|
19
|
+
@docker_socket_path.setter
|
20
|
+
def docker_socket_path(self, v):
|
21
|
+
self.__docker_socket_path = v
|
22
|
+
|
14
23
|
@property
|
15
24
|
def name(self):
|
16
25
|
return self.__name
|
@@ -19,14 +28,6 @@ class AppConfig(Config):
|
|
19
28
|
def name(self, v):
|
20
29
|
self.__name = v
|
21
30
|
|
22
|
-
@property
|
23
|
-
def network(self):
|
24
|
-
return self.__network
|
25
|
-
|
26
|
-
@network.setter
|
27
|
-
def network(self, v):
|
28
|
-
self.__network = v
|
29
|
-
|
30
31
|
@property
|
31
32
|
def ui_port(self):
|
32
33
|
return self.__ui_port
|
@@ -39,18 +40,17 @@ class AppConfig(Config):
|
|
39
40
|
config = config or self.read()
|
40
41
|
|
41
42
|
self.name = config.get(APP_NAME_ENV)
|
42
|
-
self.network = config.get(APP_NETWORK_ENV)
|
43
43
|
self.ui_port = config.get(APP_UI_PORT_ENV)
|
44
44
|
|
45
45
|
def write(self):
|
46
46
|
config = {}
|
47
47
|
|
48
|
+
if self.docker_socket_path:
|
49
|
+
config[APP_DOCKER_SOCKET_PATH_ENV] = self.docker_socket_path
|
50
|
+
|
48
51
|
if self.name:
|
49
52
|
config[APP_NAME_ENV] = self.name
|
50
53
|
|
51
|
-
if self.network:
|
52
|
-
config[APP_NETWORK_ENV] = self.network
|
53
|
-
|
54
54
|
if self.ui_port:
|
55
55
|
config[APP_UI_PORT_ENV] = self.ui_port
|
56
56
|
|
@@ -7,8 +7,8 @@ from .app import App
|
|
7
7
|
from .app_command import AppCommand
|
8
8
|
|
9
9
|
class AppCreateOptions(TypedDict):
|
10
|
+
docker_socket_path: str
|
10
11
|
name: str
|
11
|
-
network: str
|
12
12
|
ui_port: int
|
13
13
|
|
14
14
|
class AppCreateCommand(AppCommand):
|
@@ -19,19 +19,19 @@ class AppCreateCommand(AppCommand):
|
|
19
19
|
if kwargs.get('app_name'):
|
20
20
|
self.app_config.name = kwargs['app_name']
|
21
21
|
|
22
|
-
if kwargs.get('
|
23
|
-
self.app_config.
|
22
|
+
if kwargs.get('docker_socket_path'):
|
23
|
+
self.app_config.docker_socket_path = kwargs['docker_socket_path']
|
24
24
|
|
25
25
|
if kwargs.get('ui_port'):
|
26
26
|
self.app_config.ui_port = kwargs['ui_port']
|
27
27
|
|
28
28
|
@property
|
29
|
-
def
|
30
|
-
return self.app_config.
|
29
|
+
def docker_socket_path(self):
|
30
|
+
return self.app_config.docker_socket_path
|
31
31
|
|
32
32
|
@property
|
33
|
-
def
|
34
|
-
return self.app_config.
|
33
|
+
def app_name(self):
|
34
|
+
return self.app_config.name
|
35
35
|
|
36
36
|
@property
|
37
37
|
def app_ui_port(self):
|
@@ -4,12 +4,12 @@ class Command():
|
|
4
4
|
|
5
5
|
def __init__(self, app: App):
|
6
6
|
self.__app = app
|
7
|
-
self.
|
7
|
+
self.__scaffold_namespace = app.scaffold_namespace
|
8
8
|
|
9
9
|
@property
|
10
10
|
def app(self):
|
11
11
|
return self.__app
|
12
12
|
|
13
13
|
@property
|
14
|
-
def
|
15
|
-
return self.
|
14
|
+
def scaffold_namespace(self):
|
15
|
+
return self.__scaffold_namespace
|
@@ -6,6 +6,7 @@ from stoobly_agent.config.data_dir import CERTS_DIR_NAME, DATA_DIR_NAME
|
|
6
6
|
|
7
7
|
APP_DIR = '${APP_DIR}'
|
8
8
|
APP_DIR_ENV = 'APP_DIR'
|
9
|
+
APP_DOCKER_SOCKET_PATH_ENV = 'APP_DOCKER_SOCKET_PATH'
|
9
10
|
APP_NETWORK_ENV = 'APP_NETWORK'
|
10
11
|
APP_NAME_ENV = 'APP_NAME'
|
11
12
|
APP_UI_PORT_ENV = 'APP_UI_PORT'
|
@@ -16,15 +17,17 @@ COMPOSE_TEMPLATE = '.docker-compose.{workflow}.yml'
|
|
16
17
|
CONFIG_FILE = '.config.yml'
|
17
18
|
CONTEXT_DIR_ENV = 'CONTEXT_DIR'
|
18
19
|
DOCKER_NAMESPACE = 'docker'
|
19
|
-
|
20
|
+
DOTENV_FILE = '.env'
|
20
21
|
NAMESERVERS_FILE = '.nameservers'
|
21
22
|
PUBLIC_FOLDER_NAME = 'public'
|
22
23
|
SERVICE_DETACHED = '${SERVICE_DETACHED}'
|
23
24
|
SERVICE_DETACHED_ENV = 'SERVICE_DETACHED'
|
24
|
-
SERVICE_HOSTNAME = '${SERVICE_HOSTNAME}'
|
25
|
-
SERVICE_HOSTNAME_ENV = 'SERVICE_HOSTNAME'
|
26
25
|
SERVICE_DNS = '${SERVICE_DNS}'
|
27
26
|
SERVICE_DNS_ENV = 'SERVICE_DNS'
|
27
|
+
SERVICE_HOSTNAME = '${SERVICE_HOSTNAME}'
|
28
|
+
SERVICE_HOSTNAME_ENV = 'SERVICE_HOSTNAME'
|
29
|
+
SERVICE_ID = '${SERVICE_ID}'
|
30
|
+
SERVICE_ID_ENV = 'SERVICE_ID'
|
28
31
|
SERVICE_NAME = '${SERVICE_NAME}'
|
29
32
|
SERVICE_NAME_ENV = 'SERVICE_NAME'
|
30
33
|
SERVICE_PROXY_MODE = '${SERVICE_PROXY_MODE}'
|
@@ -7,8 +7,12 @@ 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,
|
11
|
-
SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV,
|
10
|
+
APP_DIR, DOCKER_NAMESPACE,
|
11
|
+
SERVICE_HOSTNAME, SERVICE_HOSTNAME_ENV,
|
12
|
+
SERVICE_NAME, SERVICE_NAME_ENV,
|
13
|
+
SERVICE_ID,
|
14
|
+
SERVICE_PORT, SERVICE_PORT_ENV,
|
15
|
+
SERVICE_SCHEME, SERVICE_SCHEME_ENV,
|
12
16
|
STOOBLY_HOME_DIR, STOOBLY_HOME_DIR,
|
13
17
|
WORKFLOW_NAME, WORKFLOW_NAME_ENV, WORKFLOW_SCRIPTS, WORKFLOW_TEMPLATE
|
14
18
|
)
|
@@ -91,7 +95,7 @@ class ServiceBuilder(Builder):
|
|
91
95
|
if not self.config.hostname:
|
92
96
|
return
|
93
97
|
|
94
|
-
service_id =
|
98
|
+
service_id = SERVICE_ID
|
95
99
|
environment = { **self.env_dict() }
|
96
100
|
labels = [
|
97
101
|
'traefik.enable=true',
|
@@ -4,13 +4,13 @@ import yaml
|
|
4
4
|
|
5
5
|
from typing import List
|
6
6
|
|
7
|
-
from stoobly_agent.config.data_dir import DATA_DIR_NAME, TMP_DIR_NAME
|
8
7
|
from stoobly_agent.app.cli.scaffold.constants import APP_DIR
|
9
8
|
from stoobly_agent.app.cli.scaffold.service_config import ServiceConfig
|
10
9
|
from stoobly_agent.app.cli.scaffold.docker.constants import APP_INGRESS_NETWORK_NAME, APP_EGRESS_NETWORK_NAME, DOCKER_COMPOSE_BASE, DOCKER_COMPOSE_BASE_TEMPLATE
|
11
10
|
from stoobly_agent.app.cli.scaffold.templates.constants import CORE_GATEWAY_SERVICE_NAME
|
11
|
+
from stoobly_agent.app.cli.scaffold.workflow_namesapce import WorkflowNamespace
|
12
12
|
|
13
|
-
def configure_gateway(
|
13
|
+
def configure_gateway(workflow_namespace: WorkflowNamespace, service_paths: List[str], no_publish = False):
|
14
14
|
if len(service_paths) == 0:
|
15
15
|
return
|
16
16
|
|
@@ -36,7 +36,7 @@ def configure_gateway(namespace: str, service_paths: List[str], no_publish = Fal
|
|
36
36
|
gateway_base['ports'] = ports
|
37
37
|
|
38
38
|
app_dir_path = os.path.dirname(os.path.dirname(service_dir_path))
|
39
|
-
__with_traefik_config(
|
39
|
+
__with_traefik_config(workflow_namespace, service_paths, app_dir_path, gateway_base)
|
40
40
|
__with_networks(gateway_base, hostnames)
|
41
41
|
|
42
42
|
with open(docker_compose_dest_path, 'w') as fp:
|
@@ -50,7 +50,7 @@ def __with_networks(config: dict, hostnames: List[str]):
|
|
50
50
|
'aliases': hostnames
|
51
51
|
}
|
52
52
|
|
53
|
-
def __with_traefik_config(
|
53
|
+
def __with_traefik_config(workflow_namespace: WorkflowNamespace, service_paths: List[str], app_dir_path: str, compose: dict):
|
54
54
|
config_dest = '/etc/traefik/traefik.yml'
|
55
55
|
|
56
56
|
if not compose['volumes']:
|
@@ -98,8 +98,8 @@ def __with_traefik_config(namespace: str, service_paths: List[str], app_dir_path
|
|
98
98
|
})
|
99
99
|
|
100
100
|
# Create traefik.yml in .stoobly/tmp
|
101
|
-
traefik_template_relative_path =
|
102
|
-
traefik_template_dest_path =
|
101
|
+
traefik_template_relative_path = workflow_namespace.traefik_config_relative_path(app_dir_path)
|
102
|
+
traefik_template_dest_path = workflow_namespace.traefik_config_path
|
103
103
|
|
104
104
|
if not os.path.exists(os.path.dirname(traefik_template_dest_path)):
|
105
105
|
os.makedirs(os.path.dirname(traefik_template_dest_path), exist_ok=True)
|
@@ -7,6 +7,7 @@ from .config import Config
|
|
7
7
|
from .constants import (
|
8
8
|
SERVICE_DETACHED_ENV,
|
9
9
|
SERVICE_HOSTNAME_ENV,
|
10
|
+
SERVICE_ID_ENV,
|
10
11
|
SERVICE_PRIORITY_ENV,
|
11
12
|
SERVICE_PORT_ENV,
|
12
13
|
SERVICE_PROXY_MODE_ENV,
|
@@ -55,7 +56,7 @@ class ServiceConfig(Config):
|
|
55
56
|
|
56
57
|
@property
|
57
58
|
def id(self):
|
58
|
-
return hashlib.md5(
|
59
|
+
return hashlib.md5(self.url.encode()).hexdigest()
|
59
60
|
|
60
61
|
@property
|
61
62
|
def hostname(self):
|
@@ -106,18 +107,22 @@ class ServiceConfig(Config):
|
|
106
107
|
if not self.hostname:
|
107
108
|
return ''
|
108
109
|
|
109
|
-
|
110
|
+
return f"reverse:{self.url}"
|
111
|
+
|
112
|
+
@property
|
113
|
+
def url(self):
|
114
|
+
_url = f"{self.scheme}://{self.hostname}"
|
110
115
|
|
111
116
|
if not self.port:
|
112
|
-
return
|
117
|
+
return _url
|
113
118
|
|
114
119
|
if self.scheme == 'http' and self.port == 80:
|
115
|
-
return
|
120
|
+
return _url
|
116
121
|
|
117
122
|
if self.scheme == 'https' and self.port == 443:
|
118
|
-
return
|
123
|
+
return _url
|
119
124
|
|
120
|
-
return f"{
|
125
|
+
return f"{_url}:{self.port}"
|
121
126
|
|
122
127
|
@proxy_mode.setter
|
123
128
|
def proxy_mode(self, v):
|
@@ -171,7 +176,7 @@ class ServiceConfig(Config):
|
|
171
176
|
config[SERVICE_SCHEME_ENV] = self.scheme
|
172
177
|
|
173
178
|
config[SERVICE_DETACHED_ENV] = bool(self.detached)
|
174
|
-
|
179
|
+
config[SERVICE_ID_ENV] = self.id
|
175
180
|
config[SERVICE_PROXY_MODE_ENV] = self.proxy_mode
|
176
181
|
|
177
182
|
super().write(config)
|
@@ -116,8 +116,9 @@ class ServiceWorkflowValidateCommand(ServiceCommand, ValidateCommand):
|
|
116
116
|
|
117
117
|
def validate_internal_hostname(self, url: str) -> None:
|
118
118
|
print(f"Validating hostname inside Docker network, url: {url}")
|
119
|
-
|
120
|
-
|
119
|
+
|
120
|
+
# See WorkflowRunCommand for how 'network' is generated
|
121
|
+
network = f"{self.workflow_name}.{self.app.network}"
|
121
122
|
timeout_seconds = 1
|
122
123
|
output = self.docker_client.containers.run(
|
123
124
|
image='curlimages/curl:8.11.0',
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# STOOBLY_CA_CERTS_DIR: path to folder where ca certs are stored, defaults to $(pwd)/.stoobly/ca_certs
|
5
5
|
# STOOBLY_CERTS_DIR: path to a folder to store certs, defaults to $(pwd)/.stoobly/certs
|
6
6
|
# STOOBLY_CONTEXT_DIR: path to the folder containing the .stoobly folder, defaults to $(pwd)
|
7
|
-
#
|
7
|
+
# STOOBLY_DOTENV_FILE: path to dotenv file, defaults to $(pwd)/.env
|
8
8
|
# STOOBLY_WORKFLOW_SERVICE_OPTIONS: extra --service options to pass 'stoobly-agent scaffold workflow' commands
|
9
9
|
|
10
10
|
# Overridable Options
|
@@ -28,7 +28,7 @@ app_dir=$$(realpath "$${STOOBLY_APP_DIR:-$(CONTEXT_DIR_DEFAULT)}")
|
|
28
28
|
ca_certs_dir=$$(realpath "$${STOOBLY_CA_CERTS_DIR:-$(app_data_dir)/ca_certs}")
|
29
29
|
certs_dir=$$(realpath "$${STOOBLY_CERTS_DIR:-$(app_data_dir)/certs}")
|
30
30
|
context_dir=$$(realpath "$${STOOBLY_CONTEXT_DIR:-$(CONTEXT_DIR_DEFAULT)}")
|
31
|
-
|
31
|
+
dotenv_file=$$(realpath "$${STOOBLY_DOTENV_FILE:-.env}" 2> /dev/null || echo '')
|
32
32
|
workflow=record
|
33
33
|
workflow_service_options=$(shell echo $$STOOBLY_WORKFLOW_SERVICE_OPTIONS)
|
34
34
|
|
@@ -38,34 +38,34 @@ app_tmp_dir=$(app_data_dir)/tmp
|
|
38
38
|
dockerfile_path=$(app_namespace_dir)/.Dockerfile.context
|
39
39
|
exec_docker_compose_file_path=$(app_namespace_dir)/stoobly-ui/exec/.docker-compose.exec.yml
|
40
40
|
workflow_namespace=$(if $(namespace),$(namespace),$(workflow))
|
41
|
+
workflow_namespace_dir=$(app_tmp_dir)/$(workflow_namespace)
|
41
42
|
workflow_script=.stoobly/tmp/$(workflow_namespace)/run.sh
|
42
43
|
|
43
44
|
# Options
|
44
45
|
certs_dir_options=--ca-certs-dir-path $(ca_certs_dir) --certs-dir-path $(certs_dir)
|
45
46
|
working_dir_options=--app-dir-path $(app_dir) --context-dir-path $(context_dir)
|
46
47
|
|
47
|
-
workflow_down_options
|
48
|
+
workflow_down_options=$(working_dir_options) --user-id $(USER_ID) $(workflow_down_extra_options)
|
48
49
|
workflow_log_options=$(workflow_log_extra_options)
|
49
50
|
workflow_run_options=--namespace $(workflow_namespace) --script-path $(workflow_script) $(workflow_service_options)
|
50
51
|
workflow_up_options=$(working_dir_options) $(certs_dir_options) --user-id $(USER_ID) $(workflow_up_extra_options)
|
51
|
-
|
52
|
+
|
52
53
|
# Commands
|
53
54
|
exec_env=APP_DIR="$(app_dir)" CA_CERTS_DIR="$(ca_certs_dir)" USER_ID="$(USER_ID)"
|
54
55
|
exec_up=$(DOCKER_BIN) compose -f "$(exec_docker_compose_file_path)" run --rm stoobly_ui.command
|
55
|
-
source_env=set -a; [ -f "$(env_file)" ] && . "$(env_file)"; set +a
|
56
56
|
|
57
57
|
# Build base image
|
58
58
|
stoobly_exec_build=$(DOCKER_BIN) build $(stoobly_exec_build_args) $(app_namespace_dir) > /dev/null
|
59
59
|
stoobly_exec_build_args=-f "$(dockerfile_path)" -t stoobly.$(USER_ID) --build-arg USER_ID=$(USER_ID) $(PULL_OPTION) --quiet
|
60
60
|
|
61
61
|
# Exec any
|
62
|
-
stoobly_exec=$(
|
62
|
+
stoobly_exec=$(stoobly_exec_build) && $(stoobly_exec_env) $(exec_up)
|
63
63
|
stoobly_exec_env=$(exec_env) CONTEXT_DIR="$(context_dir)"
|
64
64
|
|
65
65
|
# Exec workflow run
|
66
66
|
# Scaffold is stored in the application source code directory.
|
67
67
|
# When running a scaffold command from within a container, it needs access to $(app_dir) rather than $(context_dir)
|
68
|
-
stoobly_exec_run=$(
|
68
|
+
stoobly_exec_run=$(stoobly_exec_build) && $(stoobly_exec_run_env) $(exec_up)
|
69
69
|
stoobly_exec_run_env=$(exec_env) CONTEXT_DIR="$(app_dir)"
|
70
70
|
|
71
71
|
# Workflow run
|
@@ -88,14 +88,16 @@ ca-cert/install: stoobly/install
|
|
88
88
|
certs:
|
89
89
|
@export EXEC_COMMAND=scaffold/.mkcert EXEC_OPTIONS="" EXEC_ARGS="" && \
|
90
90
|
$(stoobly_exec)
|
91
|
-
|
91
|
+
dotenv: workflow/namespace
|
92
|
+
@if [ -f "$(dotenv_file)" ]; then cp "$(dotenv_file)" $(workflow_namespace_dir)/.env; fi
|
93
|
+
nameservers: workflow/namespace
|
92
94
|
@if [ -f /etc/resolv.conf ]; then \
|
93
95
|
nameserver=$$(grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' /etc/resolv.conf) && \
|
94
96
|
if [ "$$nameserver" = "127.0.0.53" ]; then \
|
95
97
|
echo "Nameserver is 127.0.0.53. Checking resolvectl status..."; \
|
96
98
|
nameserver=$$(resolvectl status | sed -n '/DNS Servers:/s/.*DNS Servers:\s*\([^ ]*\).*/\1/p' | head -n 1); \
|
97
99
|
fi; \
|
98
|
-
echo "$$nameserver" > $(
|
100
|
+
echo "$$nameserver" > $(workflow_namespace_dir)/.nameservers; \
|
99
101
|
else \
|
100
102
|
echo "/etc/resolv.conf not found." >&2; \
|
101
103
|
fi
|
@@ -158,7 +160,7 @@ test/logs: workflow/test workflow/logs
|
|
158
160
|
test/down: workflow/test workflow/down
|
159
161
|
tmpdir:
|
160
162
|
@mkdir -p $(app_tmp_dir)
|
161
|
-
workflow/down:
|
163
|
+
workflow/down: dotenv
|
162
164
|
@export EXEC_COMMAND=scaffold/.down EXEC_OPTIONS="$(workflow_down_options) $(workflow_run_options) $(options)" EXEC_ARGS="$(workflow)" && \
|
163
165
|
$(stoobly_exec_run) && \
|
164
166
|
$(workflow_run)
|
@@ -182,6 +184,8 @@ workflow/logs:
|
|
182
184
|
$(workflow_run)
|
183
185
|
workflow/mock:
|
184
186
|
$(eval workflow=mock)
|
187
|
+
workflow/namespace: tmpdir
|
188
|
+
@mkdir -p $(workflow_namespace_dir)
|
185
189
|
workflow/record:
|
186
190
|
$(eval workflow=record)
|
187
191
|
workflow/services:
|
@@ -189,7 +193,7 @@ workflow/services:
|
|
189
193
|
$(stoobly_exec_run)
|
190
194
|
workflow/test:
|
191
195
|
$(eval workflow=test) $(eval workflow_up_extra_options=$(workflow_up_extra_options) --no-publish)
|
192
|
-
workflow/up:
|
196
|
+
workflow/up: dotenv
|
193
197
|
@export EXEC_COMMAND=scaffold/.up EXEC_OPTIONS="$(workflow_up_options) $(workflow_run_options) $(options)" EXEC_ARGS="$(workflow)" && \
|
194
198
|
$(stoobly_exec_run) && \
|
195
199
|
$(workflow_run)
|
@@ -5,7 +5,7 @@ import yaml
|
|
5
5
|
from stoobly_agent.lib.logger import Logger
|
6
6
|
|
7
7
|
from .app import App
|
8
|
-
from .constants import BIN_FOLDER_NAME, COMPOSE_TEMPLATE, CONFIG_FILE,
|
8
|
+
from .constants import BIN_FOLDER_NAME, COMPOSE_TEMPLATE, CONFIG_FILE, DOTENV_FILE, PUBLIC_FOLDER_NAME
|
9
9
|
from .docker.constants import DOCKER_COMPOSE_CUSTOM
|
10
10
|
from .service_command import ServiceCommand
|
11
11
|
from .workflow_config import WorkflowConfig
|
@@ -101,8 +101,8 @@ class WorkflowCommand(ServiceCommand):
|
|
101
101
|
return os.path.join(self.workflow_path, CONFIG_FILE)
|
102
102
|
|
103
103
|
@property
|
104
|
-
def
|
105
|
-
return os.path.join(self.workflow_path,
|
104
|
+
def workflow_dotenv_path(self):
|
105
|
+
return os.path.join(self.workflow_path, DOTENV_FILE)
|
106
106
|
|
107
107
|
@property
|
108
108
|
def workflow_exists(self):
|
@@ -1,11 +1,15 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
from dotenv import dotenv_values
|
4
|
+
|
1
5
|
from .config import Config
|
2
|
-
from .constants import
|
6
|
+
from .constants import DOTENV_FILE
|
3
7
|
from .env import Env
|
4
8
|
|
5
9
|
class WorkflowEnv(Config):
|
6
10
|
|
7
11
|
def __init__(self, dir: str):
|
8
|
-
super().__init__(dir,
|
12
|
+
super().__init__(dir, DOTENV_FILE)
|
9
13
|
|
10
14
|
self.__env_vars = {}
|
11
15
|
|
@@ -15,6 +19,9 @@ class WorkflowEnv(Config):
|
|
15
19
|
def load(self):
|
16
20
|
self.__env_vars = self.read()
|
17
21
|
|
18
|
-
def write(self, env_vars: dict):
|
22
|
+
def write(self, env_vars: dict, dotenv_path: str = None):
|
23
|
+
if dotenv_path and os.path.exists(dotenv_path):
|
24
|
+
env_vars = { **env_vars, **dotenv_values(dotenv_path) }
|
25
|
+
|
19
26
|
Env(self.path).write(env_vars)
|
20
27
|
self.__env_vars = env_vars
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import os
|
2
|
+
|
3
|
+
|
4
|
+
from .app import App
|
5
|
+
from .constants import DOTENV_FILE, NAMESERVERS_FILE
|
6
|
+
|
7
|
+
class WorkflowNamespace():
|
8
|
+
|
9
|
+
def __init__(self, app: App, namespace: str = None):
|
10
|
+
self._app = app
|
11
|
+
self._namespace = namespace
|
12
|
+
self._path = os.path.join(app.data_dir.tmp_dir_path, namespace or '')
|
13
|
+
|
14
|
+
@property
|
15
|
+
def dotenv_path(self):
|
16
|
+
return os.path.join(self.path, DOTENV_FILE)
|
17
|
+
|
18
|
+
@property
|
19
|
+
def nameservers_path(self):
|
20
|
+
return os.path.join(self.path, NAMESERVERS_FILE)
|
21
|
+
|
22
|
+
@property
|
23
|
+
def namespace(self):
|
24
|
+
return self._namespace
|
25
|
+
|
26
|
+
@property
|
27
|
+
def path(self):
|
28
|
+
return self._path
|
29
|
+
|
30
|
+
@property
|
31
|
+
def run_script_path(self):
|
32
|
+
return os.path.join(self.path, 'run.sh')
|
33
|
+
|
34
|
+
@property
|
35
|
+
def traefik_config_path(self):
|
36
|
+
return os.path.join(self.path, 'traefik.yml')
|
37
|
+
|
38
|
+
def traefik_config_relative_path(self, path: str):
|
39
|
+
if not path:
|
40
|
+
return path
|
41
|
+
return self.traefik_config_path.replace(path if path[len(path) - 1] == '/' else path + '/', '', 1)
|
@@ -3,42 +3,25 @@ import os
|
|
3
3
|
import pdb
|
4
4
|
import subprocess
|
5
5
|
import re
|
6
|
-
import yaml
|
7
6
|
|
8
|
-
from typing import TypedDict
|
9
7
|
|
10
8
|
from stoobly_agent.config.data_dir import DataDir
|
11
9
|
from stoobly_agent.lib.logger import Logger
|
12
10
|
|
13
11
|
from .app import App
|
14
12
|
from .constants import (
|
15
|
-
APP_DIR_ENV, APP_NETWORK_ENV, CA_CERTS_DIR_ENV, CERTS_DIR_ENV, CONTEXT_DIR_ENV,
|
13
|
+
APP_DIR_ENV, APP_NETWORK_ENV, CA_CERTS_DIR_ENV, CERTS_DIR_ENV, CONTEXT_DIR_ENV,
|
16
14
|
SERVICE_DNS_ENV, SERVICE_NAME_ENV, SERVICE_SCRIPTS_DIR, SERVICE_SCRIPTS_ENV, USER_ID_ENV,
|
17
15
|
WORKFLOW_NAME_ENV, WORKFLOW_NAMESPACE_ENV, WORKFLOW_SCRIPTS_DIR, WORKFLOW_SCRIPTS_ENV, WORKFLOW_TEMPLATE_ENV
|
18
16
|
)
|
19
17
|
from .docker.constants import APP_EGRESS_NETWORK_TEMPLATE, APP_INGRESS_NETWORK_TEMPLATE, DOCKERFILE_CONTEXT
|
20
18
|
from .workflow_command import WorkflowCommand
|
21
19
|
from .workflow_env import WorkflowEnv
|
20
|
+
from .workflow_namesapce import WorkflowNamespace
|
21
|
+
from ..types.workflow_run_command import BuildOptions, ComposeOptions, DownOptions, UpOptions
|
22
22
|
|
23
23
|
LOG_ID = 'WorkflowRunCommand'
|
24
24
|
|
25
|
-
class ComposeOptions(TypedDict):
|
26
|
-
namespace: str
|
27
|
-
user_id: str
|
28
|
-
|
29
|
-
class BuildOptions(ComposeOptions):
|
30
|
-
user_id: str
|
31
|
-
verbose: bool
|
32
|
-
|
33
|
-
class DownOptions(ComposeOptions):
|
34
|
-
extra_compose_path: str
|
35
|
-
rmi: bool
|
36
|
-
|
37
|
-
class UpOptions(ComposeOptions):
|
38
|
-
attached: bool
|
39
|
-
extra_compose_path: str
|
40
|
-
pull: bool
|
41
|
-
|
42
25
|
class WorkflowRunCommand(WorkflowCommand):
|
43
26
|
def __init__(self, app: App, **kwargs):
|
44
27
|
super().__init__(app, **kwargs)
|
@@ -48,7 +31,8 @@ class WorkflowRunCommand(WorkflowCommand):
|
|
48
31
|
self.__ca_certs_dir_path = kwargs.get('ca_certs_dir_path') or app.ca_certs_dir_path
|
49
32
|
self.__certs_dir_path = kwargs.get('certs_dir_path') or app.certs_dir_path
|
50
33
|
self.__context_dir_path = kwargs.get('context_dir_path') or app.context_dir_path
|
51
|
-
self.
|
34
|
+
self.__namespace = kwargs.get('namespace') or self.workflow_name
|
35
|
+
self.__network = f"{self.__namespace}.{kwargs.get('network') or app.network}"
|
52
36
|
|
53
37
|
@property
|
54
38
|
def app_dir_path(self):
|
@@ -78,6 +62,10 @@ class WorkflowRunCommand(WorkflowCommand):
|
|
78
62
|
def current_working_dir(self, v):
|
79
63
|
self.__current_working_dir = v
|
80
64
|
|
65
|
+
@property
|
66
|
+
def dotenv_path(self):
|
67
|
+
return WorkflowNamespace(self.app, self.namespace).dotenv_path
|
68
|
+
|
81
69
|
@property
|
82
70
|
def nameservers(self):
|
83
71
|
path = self.nameservers_path
|
@@ -90,7 +78,11 @@ class WorkflowRunCommand(WorkflowCommand):
|
|
90
78
|
|
91
79
|
@property
|
92
80
|
def nameservers_path(self):
|
93
|
-
return
|
81
|
+
return WorkflowNamespace(self.app, self.namespace).nameservers_path
|
82
|
+
|
83
|
+
@property
|
84
|
+
def namespace(self):
|
85
|
+
return self.__namespace
|
94
86
|
|
95
87
|
@property
|
96
88
|
def network(self):
|
@@ -290,7 +282,7 @@ class WorkflowRunCommand(WorkflowCommand):
|
|
290
282
|
_config[SERVICE_DNS_ENV] = '8.8.8.8'
|
291
283
|
|
292
284
|
env_vars = self.config(_config)
|
293
|
-
WorkflowEnv(self.workflow_path).write(env_vars)
|
285
|
+
WorkflowEnv(self.workflow_path).write(env_vars, self.dotenv_path)
|
294
286
|
return env_vars
|
295
287
|
|
296
288
|
def __find_nameservers(self, dns_resolver: dns.resolver.Resolver):
|
@@ -30,6 +30,7 @@ from stoobly_agent.app.cli.scaffold.workflow import Workflow
|
|
30
30
|
from stoobly_agent.app.cli.scaffold.workflow_create_command import WorkflowCreateCommand
|
31
31
|
from stoobly_agent.app.cli.scaffold.workflow_copy_command import WorkflowCopyCommand
|
32
32
|
from stoobly_agent.app.cli.scaffold.workflow_log_command import WorkflowLogCommand
|
33
|
+
from stoobly_agent.app.cli.scaffold.workflow_namesapce import WorkflowNamespace
|
33
34
|
from stoobly_agent.app.cli.scaffold.workflow_run_command import WorkflowRunCommand
|
34
35
|
from stoobly_agent.app.cli.scaffold.workflow_validate_command import WorkflowValidateCommand
|
35
36
|
from stoobly_agent.config.constants import env_vars
|
@@ -88,7 +89,7 @@ def hostname(ctx):
|
|
88
89
|
help="Scaffold application"
|
89
90
|
)
|
90
91
|
@click.option('--app-dir-path', default=current_working_dir, help='Path to create the app scaffold.')
|
91
|
-
@click.option('--
|
92
|
+
@click.option('--docker-socket-path', default='/var/run/docker.sock', help='Path to Docker socket.')
|
92
93
|
@click.option('--quiet', is_flag=True, help='Disable log output.')
|
93
94
|
@click.option('--ui-port', default=4200, type=click.IntRange(1, 65535), help='UI service port.')
|
94
95
|
@click.argument('app_name', callback=validate_app_name)
|
@@ -100,9 +101,6 @@ def create(**kwargs):
|
|
100
101
|
if not kwargs['quiet'] and os.path.exists(app.scaffold_namespace_path):
|
101
102
|
print(f"{kwargs['app_dir_path']} already exists, updating scaffold maintained files...")
|
102
103
|
|
103
|
-
if not kwargs['network']:
|
104
|
-
kwargs['network'] = kwargs['app_name']
|
105
|
-
|
106
104
|
AppCreateCommand(app, **kwargs).build()
|
107
105
|
|
108
106
|
@app.command(
|
@@ -344,7 +342,10 @@ def copy(**kwargs):
|
|
344
342
|
def down(**kwargs):
|
345
343
|
os.environ[env_vars.LOG_LEVEL] = kwargs['log_level']
|
346
344
|
|
347
|
-
|
345
|
+
containerized = kwargs['containerized']
|
346
|
+
|
347
|
+
app_dir_path = current_working_dir if containerized else kwargs['app_dir_path']
|
348
|
+
app = App(app_dir_path, DOCKER_NAMESPACE, **kwargs)
|
348
349
|
__validate_app(app)
|
349
350
|
|
350
351
|
__with_namespace_defaults(kwargs)
|
@@ -361,7 +362,7 @@ def down(**kwargs):
|
|
361
362
|
command.current_working_dir = current_working_dir
|
362
363
|
commands.append(command)
|
363
364
|
|
364
|
-
script = __build_script(**kwargs)
|
365
|
+
script = __build_script(app, **kwargs)
|
365
366
|
|
366
367
|
commands = sorted(commands, key=lambda command: command.service_config.priority)
|
367
368
|
for index, command in enumerate(commands):
|
@@ -450,7 +451,7 @@ def logs(**kwargs):
|
|
450
451
|
command = WorkflowLogCommand(app, **config)
|
451
452
|
commands.append(command)
|
452
453
|
|
453
|
-
script = __build_script(**kwargs)
|
454
|
+
script = __build_script(app, **kwargs)
|
454
455
|
|
455
456
|
commands = sorted(commands, key=lambda command: command.service_config.priority)
|
456
457
|
for index, command in enumerate(commands):
|
@@ -514,7 +515,9 @@ def up(**kwargs):
|
|
514
515
|
# Gateway ports are dynamically set depending on the workflow run
|
515
516
|
workflow = Workflow(kwargs['workflow_name'], app)
|
516
517
|
configure_gateway(
|
517
|
-
kwargs['namespace'] or workflow.workflow_name
|
518
|
+
WorkflowNamespace(app, kwargs['namespace'] or workflow.workflow_name),
|
519
|
+
workflow.service_paths_from_services(services),
|
520
|
+
kwargs['no_publish']
|
518
521
|
)
|
519
522
|
|
520
523
|
commands: List[WorkflowRunCommand] = []
|
@@ -525,7 +528,7 @@ def up(**kwargs):
|
|
525
528
|
command.current_working_dir = current_working_dir
|
526
529
|
commands.append(command)
|
527
530
|
|
528
|
-
script = __build_script(**kwargs)
|
531
|
+
script = __build_script(app, **kwargs)
|
529
532
|
|
530
533
|
# Before services can be started, their image and network needs to be created
|
531
534
|
if len(commands) > 0:
|
@@ -678,11 +681,11 @@ scaffold.add_command(service)
|
|
678
681
|
scaffold.add_command(workflow)
|
679
682
|
scaffold.add_command(hostname)
|
680
683
|
|
681
|
-
def __build_script(**kwargs):
|
684
|
+
def __build_script(app: App, **kwargs):
|
682
685
|
script_path = kwargs['script_path']
|
683
686
|
if not script_path:
|
684
|
-
|
685
|
-
script_path =
|
687
|
+
workflow_namespace = WorkflowNamespace(app, kwargs.get('namespace') or kwargs['workflow_name'])
|
688
|
+
script_path = workflow_namespace.run_script_path
|
686
689
|
|
687
690
|
script_dir = os.path.dirname(script_path)
|
688
691
|
if not os.path.exists(script_dir):
|
@@ -827,10 +830,6 @@ def __with_namespace_defaults(kwargs):
|
|
827
830
|
if not kwargs.get('namespace'):
|
828
831
|
kwargs['namespace'] = kwargs.get('workflow_name')
|
829
832
|
|
830
|
-
# If network there was a network option, but it is not set, default network to namespace
|
831
|
-
if 'network' in kwargs and not kwargs['network']:
|
832
|
-
kwargs['network'] = kwargs['namespace']
|
833
|
-
|
834
833
|
def __workflow_create(app, **kwargs):
|
835
834
|
command = WorkflowCreateCommand(app, **kwargs)
|
836
835
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import TypedDict
|
2
|
+
|
3
|
+
class ComposeOptions(TypedDict):
|
4
|
+
namespace: str
|
5
|
+
user_id: str
|
6
|
+
|
7
|
+
class BuildOptions(ComposeOptions):
|
8
|
+
user_id: str
|
9
|
+
verbose: bool
|
10
|
+
|
11
|
+
class DownOptions(ComposeOptions):
|
12
|
+
extra_compose_path: str
|
13
|
+
rmi: bool
|
14
|
+
|
15
|
+
class UpOptions(ComposeOptions):
|
16
|
+
attached: bool
|
17
|
+
extra_compose_path: str
|
18
|
+
pull: bool
|
@@ -1,4 +1,4 @@
|
|
1
|
-
stoobly_agent/__init__.py,sha256=
|
1
|
+
stoobly_agent/__init__.py,sha256=T0T5meojgC4kb3-HURdzQoFWyRESweACkhTLNw5Rsnk,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=Vvz53yB0bR7J-QqMAkLlhcZrA4P64ZEN7w8cMbgl6o0,5261
|
@@ -52,7 +52,7 @@ stoobly_agent/app/cli/helpers/request_synchronize_handler.py,sha256=wawAL8hoZLqO
|
|
52
52
|
stoobly_agent/app/cli/helpers/run_command_service.py,sha256=w9CNDZDj_gxCCXAFFOLONuOVu6_W9f8z1RX3-5RKuTM,731
|
53
53
|
stoobly_agent/app/cli/helpers/scenario_facade.py,sha256=nWcycEZBL87OFCCQx85-5QaK0Q9XXk2-RMeC1uef2_Y,3134
|
54
54
|
stoobly_agent/app/cli/helpers/schema_builder.py,sha256=-R_oU_d8nPNdNA31WDp8lCh7XpCeazLm_1dl_Kq8DLU,1127
|
55
|
-
stoobly_agent/app/cli/helpers/shell.py,sha256=
|
55
|
+
stoobly_agent/app/cli/helpers/shell.py,sha256=pnztxQjm8kdeVZH40PlTSuiGB_yaSP8PXRS15MoUxtE,838
|
56
56
|
stoobly_agent/app/cli/helpers/synchronize_request_service.py,sha256=pwsILyrR6XPBJAIVaato0tRrbCT4z5-FymJgfeWTsVw,6018
|
57
57
|
stoobly_agent/app/cli/helpers/tabulate_print_service.py,sha256=d4xtJgn9sueL8nAwOSIyiyzuY1ptsD1wxEdLQe0X2tc,964
|
58
58
|
stoobly_agent/app/cli/helpers/test_facade.py,sha256=gRnbjYNxnzPmtvFp2J6TZgxaMSzDjpAWdb79kaFBt_I,2227
|
@@ -61,19 +61,19 @@ stoobly_agent/app/cli/helpers/trace_aliases.py,sha256=8N8pnsnONwVv-fabCTvDlXec-W
|
|
61
61
|
stoobly_agent/app/cli/helpers/trace_context_facade.py,sha256=3MDjY_bdhvE2dad_B_w9gemCZZoiVjotbE8o9hrmVYo,1027
|
62
62
|
stoobly_agent/app/cli/helpers/validations.py,sha256=nvcrEHvjMOAyHlJK0bQIwyzBUciJ0qNkNESa2zZ5ZFo,6232
|
63
63
|
stoobly_agent/app/cli/helpers/verify_raw_request_service.py,sha256=tmLeRBYhNgAQeJD-rF6Nj22F_TfVktVSb1wjRPFblBQ,658
|
64
|
-
stoobly_agent/app/cli/intercept_cli.py,sha256=
|
64
|
+
stoobly_agent/app/cli/intercept_cli.py,sha256=LNHfAec6Tf_cFNwuNvcvig-k9lKi7kVsMGIDC0fWp2o,5116
|
65
65
|
stoobly_agent/app/cli/main_group.py,sha256=3UzBxin2f2p5KNqo6Oayo_I1VI2pHpqOoRexUnJ74a4,2187
|
66
66
|
stoobly_agent/app/cli/project_cli.py,sha256=EXjeLjbnq9PhfCjvyfZ0UnJ2tejeCS0SIAo3Nc4fKOc,3852
|
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=
|
71
|
-
stoobly_agent/app/cli/scaffold/app_command.py,sha256=
|
72
|
-
stoobly_agent/app/cli/scaffold/app_config.py,sha256=
|
73
|
-
stoobly_agent/app/cli/scaffold/app_create_command.py,sha256=
|
74
|
-
stoobly_agent/app/cli/scaffold/command.py,sha256=
|
70
|
+
stoobly_agent/app/cli/scaffold/app.py,sha256=0HJm8cdyIBAdOBr18499MkZGhmEFu6I7GSZXR7pKxkw,3650
|
71
|
+
stoobly_agent/app/cli/scaffold/app_command.py,sha256=w15VCsyefIE9HfzpIRMrv2BEep46ZSPgvsjZmFOMPZs,2377
|
72
|
+
stoobly_agent/app/cli/scaffold/app_config.py,sha256=z4sxZcXZTEoXyUZajUuffuWQN8x8eovu-TBtgoTMXEE,1182
|
73
|
+
stoobly_agent/app/cli/scaffold/app_create_command.py,sha256=HOlXL6Ugid2qHagqDVGl3ksjLKE4WF_3Dji8FoQlpuM,1215
|
74
|
+
stoobly_agent/app/cli/scaffold/command.py,sha256=G4Zp647cuviaEXUdcl7Rbx_qQAr0Z_DS7-Y3MWDC1Qc,281
|
75
75
|
stoobly_agent/app/cli/scaffold/config.py,sha256=HZU5tkvr3dkPr4JMXZtrJlu2wxxO-134Em6jReFFcq0,688
|
76
|
-
stoobly_agent/app/cli/scaffold/constants.py,sha256=
|
76
|
+
stoobly_agent/app/cli/scaffold/constants.py,sha256=VuCpzeGxlFEQuX6WEK5D_4ih8-S-iotwOny458K85_c,2612
|
77
77
|
stoobly_agent/app/cli/scaffold/containerized_app.py,sha256=dAjn4RwcZV3aEL0POUmrbF_DC-r9h6s1zx7gT2t45v0,175
|
78
78
|
stoobly_agent/app/cli/scaffold/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
79
79
|
stoobly_agent/app/cli/scaffold/docker/app_builder.py,sha256=7z5pk5JKlRDHx2USxY-WurttLyyUkIVYfl34_u1x9dE,501
|
@@ -81,8 +81,8 @@ stoobly_agent/app/cli/scaffold/docker/builder.py,sha256=uiGqhxBHEasZAqLzjKUGUs-1
|
|
81
81
|
stoobly_agent/app/cli/scaffold/docker/constants.py,sha256=1khQdgTaQ89ykGRNdTQh_ejFOdjNFGaZ_3cOGda6y7Y,692
|
82
82
|
stoobly_agent/app/cli/scaffold/docker/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
83
83
|
stoobly_agent/app/cli/scaffold/docker/service/build_decorator.py,sha256=ZU7z4bkvdS3OK5O4fJhlA9_PNwnFtZW6t7vNF7V5obQ,1003
|
84
|
-
stoobly_agent/app/cli/scaffold/docker/service/builder.py,sha256=
|
85
|
-
stoobly_agent/app/cli/scaffold/docker/service/configure_gateway.py,sha256=
|
84
|
+
stoobly_agent/app/cli/scaffold/docker/service/builder.py,sha256=u3_YNuxX8TT4TvhzTqe5b2Zvi9fF7TLWJFepkBSXwhk,5857
|
85
|
+
stoobly_agent/app/cli/scaffold/docker/service/configure_gateway.py,sha256=jbMaa08R2EoZ2esoC4uREfPoBK9b5vyPRuTNOT0QDjE,3949
|
86
86
|
stoobly_agent/app/cli/scaffold/docker/service/types.py,sha256=qB-yYHlu-PZDc0HYgTUvE5bWNpHxaSThC3JUG8okR1k,88
|
87
87
|
stoobly_agent/app/cli/scaffold/docker/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
88
88
|
stoobly_agent/app/cli/scaffold/docker/workflow/build_decorator.py,sha256=VKD9hXbJGRIWHS5IeYXeX0-FQ0F43zG8VmsegL6eYwA,703
|
@@ -91,21 +91,21 @@ stoobly_agent/app/cli/scaffold/docker/workflow/decorators_factory.py,sha256=bjQ8
|
|
91
91
|
stoobly_agent/app/cli/scaffold/docker/workflow/dns_decorator.py,sha256=nlDPbyF1hkVItzFH3bk9KlqfDC8usyFZs353-ibqxvA,938
|
92
92
|
stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py,sha256=DcBnwA8YhE-VdrUiWf2xPcqirEMZEQm3AwssAg9CxLo,1226
|
93
93
|
stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py,sha256=zD4FEtBMiPEtvEb798LOfFH8sJhTWQYpA9THLq5UMbg,1227
|
94
|
-
stoobly_agent/app/cli/scaffold/env.py,sha256=
|
94
|
+
stoobly_agent/app/cli/scaffold/env.py,sha256=dT33tHoQaUxfsFCYm8kfaAv-qPVrUPmNFQmLnFQhZeQ,1107
|
95
95
|
stoobly_agent/app/cli/scaffold/hosts_file_manager.py,sha256=zNX5wh6zXQ4J2BA0YYdD7_CPqDz02b_ghXsY3oTjjB4,4999
|
96
96
|
stoobly_agent/app/cli/scaffold/managed_services_docker_compose.py,sha256=-wLBXUi7DCWsfm5KzZzd_kdJKOTl1NT924XR7dyjbSY,574
|
97
97
|
stoobly_agent/app/cli/scaffold/service.py,sha256=74JwjTRRkk6lo-k9hre1iGztbKa9zDqjPVx3Qgpze-s,699
|
98
|
-
stoobly_agent/app/cli/scaffold/service_command.py,sha256=
|
99
|
-
stoobly_agent/app/cli/scaffold/service_config.py,sha256=
|
100
|
-
stoobly_agent/app/cli/scaffold/service_create_command.py,sha256=
|
98
|
+
stoobly_agent/app/cli/scaffold/service_command.py,sha256=n5tVp8jIypnNO9uxtaMt33lX5ho0xhV6A53HDN2Yet4,1239
|
99
|
+
stoobly_agent/app/cli/scaffold/service_config.py,sha256=WCHy1bZ8-nlVwCWdOWKXrdIVTtjye8XStA1bqvbRgZ0,3959
|
100
|
+
stoobly_agent/app/cli/scaffold/service_create_command.py,sha256=nCONco0ducMcX4rsdFe3A-iRiySyUnu-T6bTb312XP0,2824
|
101
101
|
stoobly_agent/app/cli/scaffold/service_delete_command.py,sha256=_nBDQjm8eL62MQpzSCxgUHlW04ZXKG8MDlN1BXxlqww,986
|
102
102
|
stoobly_agent/app/cli/scaffold/service_docker_compose.py,sha256=OMUN1-ujQYIZXxDvS4XBf5C9wGalQULkwOiBBQPZbHY,820
|
103
103
|
stoobly_agent/app/cli/scaffold/service_update_command.py,sha256=oWusBKfvjt4RnK03_V3CJYWrfsCI4_LcR7W12eLXMR4,2579
|
104
104
|
stoobly_agent/app/cli/scaffold/service_workflow.py,sha256=sQ_Edy_wGHKMXpD0DmhnOWkGEKz7gSgEGNI8f7aXOdg,444
|
105
|
-
stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py,sha256
|
105
|
+
stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py,sha256=-hdg7RLsoEQXCI9rebIXyO3d8JbpyTxGnhpjaPQfmFk,11514
|
106
106
|
stoobly_agent/app/cli/scaffold/templates/__init__.py,sha256=x8C_a0VoO_vUbosp4_6IC1U7Ge9NnUdVKDPpVMtMkeY,171
|
107
107
|
stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context,sha256=Okk4Q0Fj7Wi5NU58gQfpjpFwAL3RUBJyRe56kteQfcA,158
|
108
|
-
stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=
|
108
|
+
stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=uV-xqit3fz3tfcU6sbBOxK0Zon11v-fydfuYLSxS7jQ,9164
|
109
109
|
stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml,sha256=6tFqXh3ine8vaD0FCL5TMoY5NjKx2wLUR8XpW3tJtew,245
|
110
110
|
stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.networks.yml,sha256=I4PbJpQjFHb5IbAUWNvYM6okDEtmwtKFDQg-yog05WM,141
|
111
111
|
stoobly_agent/app/cli/scaffold/templates/app/Makefile,sha256=TEmPG7Bf0KZOnmfsgdzza3UdwcVMmM5Lj1YdLc4cgjA,79
|
@@ -138,7 +138,7 @@ stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/configure,sha25
|
|
138
138
|
stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/init,sha256=YxWVVQMEdGarcMtBcE1Sj2kdLgUgwY9kXp3MjPsVcmg,46
|
139
139
|
stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/docker-compose.yml,sha256=JpWLQrW69EatLD3HPHpmi3Y6n7cjlrUgekYVbJ4ngSY,523
|
140
140
|
stoobly_agent/app/cli/scaffold/templates/app/gateway/.config.yml,sha256=XnLQZMzzMMIwVycjyPN5QXsmRztkTFAna1kIHYuDfJQ,19
|
141
|
-
stoobly_agent/app/cli/scaffold/templates/app/gateway/.docker-compose.base.template.yml,sha256=
|
141
|
+
stoobly_agent/app/cli/scaffold/templates/app/gateway/.docker-compose.base.template.yml,sha256=QipWNy2mEbJuceiNfRbv6L3ARk1lMkD1gE4l_Z0PrPU,246
|
142
142
|
stoobly_agent/app/cli/scaffold/templates/app/gateway/mock/.docker-compose.mock.yml,sha256=CDL5x18-ues4F_ujqpNef_zJTG6PyDOkQ11cIHBOW5k,136
|
143
143
|
stoobly_agent/app/cli/scaffold/templates/app/gateway/record/.docker-compose.record.yml,sha256=eyLH2h33Peunus8M1sUKL9AALCG2ABhV_heiJKhvgwo,138
|
144
144
|
stoobly_agent/app/cli/scaffold/templates/app/gateway/test/.docker-compose.test.yml,sha256=oJO6i0lsuQaQeIH80yoPZo3Vs0LzUAH2WRl853yLq6g,136
|
@@ -196,15 +196,16 @@ stoobly_agent/app/cli/scaffold/templates/workflow/test/public/.gitignore,sha256=
|
|
196
196
|
stoobly_agent/app/cli/scaffold/validate_command.py,sha256=BEDcF5qPDbMjWe-SCAr5jxcrVMZlV3ciLa89TDDENmM,3787
|
197
197
|
stoobly_agent/app/cli/scaffold/validate_exceptions.py,sha256=Jtjl4OkbbSRWm0hy7Kf_50zcFh2J324HhNcnwJKH_Oc,54
|
198
198
|
stoobly_agent/app/cli/scaffold/workflow.py,sha256=KlbWT9CIo9EpZxKU1WVZtmodhxK7CpmLUHPNk4Mh6DA,1570
|
199
|
-
stoobly_agent/app/cli/scaffold/workflow_command.py,sha256=
|
199
|
+
stoobly_agent/app/cli/scaffold/workflow_command.py,sha256=sGe5uVr34P6IZ0qfCTgM8sQ7LkvdvymM2LmBzXpw1ZY,3353
|
200
200
|
stoobly_agent/app/cli/scaffold/workflow_config.py,sha256=ghnbcnCyb6ECdylUJCAJ6A8ulzaFY9bu7RvRuYeiRkk,901
|
201
201
|
stoobly_agent/app/cli/scaffold/workflow_copy_command.py,sha256=wi8qHH_M2e6jXIPuumx65Zd4Zt7hTBb6b3Z4vt4xYeQ,1320
|
202
202
|
stoobly_agent/app/cli/scaffold/workflow_create_command.py,sha256=-fwsr6_LvGT8BbBWdGY3Qd8cSQhBOSJiMr1r8s2R86w,3390
|
203
|
-
stoobly_agent/app/cli/scaffold/workflow_env.py,sha256=
|
203
|
+
stoobly_agent/app/cli/scaffold/workflow_env.py,sha256=shPjoX1SWe7K6pGpZvw2fPVHWd6j_azTe58jvOjGUns,607
|
204
204
|
stoobly_agent/app/cli/scaffold/workflow_log_command.py,sha256=Bke4lMOMxuDUFuAx9nlXHbKgYMO4KAg9ASHvjz4aVWc,1372
|
205
|
-
stoobly_agent/app/cli/scaffold/
|
205
|
+
stoobly_agent/app/cli/scaffold/workflow_namesapce.py,sha256=DXPCjfY6LAJDHy1ZlKVhVgp2aX97TmQK78lmgzBRN20,968
|
206
|
+
stoobly_agent/app/cli/scaffold/workflow_run_command.py,sha256=H9s0F8LaoB7ZLUVXWP6M6yPLYk5IE4JD8qgGXntwtMc,11138
|
206
207
|
stoobly_agent/app/cli/scaffold/workflow_validate_command.py,sha256=Uo_yo6rVR1ZR7xpvsQvlH48AyMBVLRupd4G-bRjzm_Q,5584
|
207
|
-
stoobly_agent/app/cli/scaffold_cli.py,sha256=
|
208
|
+
stoobly_agent/app/cli/scaffold_cli.py,sha256=v4b8jCopSbCUv8rpPqqeC-NeziqD8mWbiF3nOZWQ77Y,32598
|
208
209
|
stoobly_agent/app/cli/scenario_cli.py,sha256=3J1EiJOvunkfWrEkOsanw-XrKkOk78ij_GjBlE9p7CE,8229
|
209
210
|
stoobly_agent/app/cli/snapshot_cli.py,sha256=1Dw5JgDlmG6vctrawIRO7CdB73vAQk_wRBnPG2lVOrQ,11929
|
210
211
|
stoobly_agent/app/cli/trace_cli.py,sha256=K7E-vx3JUcqEDSWOdIOi_AieKNQz7dBfmRrVvKDkzFI,4605
|
@@ -215,6 +216,7 @@ stoobly_agent/app/cli/types/request.py,sha256=QthojE5sfx7OvKu-vVNnSUfGk8n4pLzuBQ
|
|
215
216
|
stoobly_agent/app/cli/types/scenario.py,sha256=28WxmOlbm2Bsek1uu7yc4hJGz-d5oHbYAro7LlFWRoc,81
|
216
217
|
stoobly_agent/app/cli/types/snapshot_migration.py,sha256=4_Re46FKjsflcTOO3qhNsbWWmdEU67SFsF-XE_FKG3M,1859
|
217
218
|
stoobly_agent/app/cli/types/test.py,sha256=1c458B7DFBWsEk5Q1CrZ2CUi84YzEzcs-W4qTcudwAk,714
|
219
|
+
stoobly_agent/app/cli/types/workflow_run_command.py,sha256=SQ5PGpoqIEQ7w9xeSQE1FBqelnVfsdlRXXaODDW4yPY,326
|
218
220
|
stoobly_agent/app/cli/validators/scaffold.py,sha256=Y2XQrN2RFMcBh228q6inTwZGoN0K5FmXO8JfrgKVwJA,1669
|
219
221
|
stoobly_agent/app/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
222
|
stoobly_agent/app/models/adapters/__init__.py,sha256=cEEE--Bvrvk6DAsHx_uPgFhLnZJETP4zSBtWjMqyIKc,233
|
@@ -751,8 +753,8 @@ stoobly_agent/test/mock_data/scaffold/docker-compose-local-service.yml,sha256=1W
|
|
751
753
|
stoobly_agent/test/mock_data/scaffold/index.html,sha256=qJwuYajKZ4ihWZrJQ3BNObV5kf1VGnnm_vqlPJzdqLE,258
|
752
754
|
stoobly_agent/test/mock_data/uspto.yaml,sha256=6U5se7C3o-86J4m9xpOk9Npias399f5CbfWzR87WKwE,7835
|
753
755
|
stoobly_agent/test/test_helper.py,sha256=m_oAI7tmRYCNZdKfNqISWhMv3e44tjeYViQ3nTUfnos,1007
|
754
|
-
stoobly_agent-1.9.
|
755
|
-
stoobly_agent-1.9.
|
756
|
-
stoobly_agent-1.9.
|
757
|
-
stoobly_agent-1.9.
|
758
|
-
stoobly_agent-1.9.
|
756
|
+
stoobly_agent-1.9.11.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
|
757
|
+
stoobly_agent-1.9.11.dist-info/METADATA,sha256=BhaA2CQUDiNOSEBokPAeKi22VSZyNFl6A8Aqx5oPGUg,3088
|
758
|
+
stoobly_agent-1.9.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
759
|
+
stoobly_agent-1.9.11.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
|
760
|
+
stoobly_agent-1.9.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|