stoobly-agent 0.34.13__py3-none-any.whl → 1.0.1__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 (132) hide show
  1. stoobly_agent/__init__.py +1 -1
  2. stoobly_agent/app/cli/__init__.py +1 -0
  3. stoobly_agent/app/cli/helpers/openapi_endpoint_adapter.py +9 -7
  4. stoobly_agent/app/cli/helpers/shell.py +28 -0
  5. stoobly_agent/app/cli/main_group.py +1 -1
  6. stoobly_agent/app/cli/scaffold/__init__.py +0 -0
  7. stoobly_agent/app/cli/scaffold/app.py +106 -0
  8. stoobly_agent/app/cli/scaffold/app_command.py +82 -0
  9. stoobly_agent/app/cli/scaffold/app_config.py +32 -0
  10. stoobly_agent/app/cli/scaffold/app_create_command.py +24 -0
  11. stoobly_agent/app/cli/scaffold/command.py +15 -0
  12. stoobly_agent/app/cli/scaffold/config.py +35 -0
  13. stoobly_agent/app/cli/scaffold/constants.py +35 -0
  14. stoobly_agent/app/cli/scaffold/docker/__init__.py +0 -0
  15. stoobly_agent/app/cli/scaffold/docker/app_builder.py +26 -0
  16. stoobly_agent/app/cli/scaffold/docker/builder.py +117 -0
  17. stoobly_agent/app/cli/scaffold/docker/constants.py +7 -0
  18. stoobly_agent/app/cli/scaffold/docker/service/__init__.py +0 -0
  19. stoobly_agent/app/cli/scaffold/docker/service/build_decorator.py +37 -0
  20. stoobly_agent/app/cli/scaffold/docker/service/builder.py +117 -0
  21. stoobly_agent/app/cli/scaffold/docker/service/set_gateway_ports.py +47 -0
  22. stoobly_agent/app/cli/scaffold/docker/service/types.py +4 -0
  23. stoobly_agent/app/cli/scaffold/docker/workflow/__init__.py +0 -0
  24. stoobly_agent/app/cli/scaffold/docker/workflow/build_decorator.py +28 -0
  25. stoobly_agent/app/cli/scaffold/docker/workflow/builder.py +259 -0
  26. stoobly_agent/app/cli/scaffold/docker/workflow/decorators_factory.py +17 -0
  27. stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +40 -0
  28. stoobly_agent/app/cli/scaffold/docker/workflow/reverse_proxy_decorator.py +51 -0
  29. stoobly_agent/app/cli/scaffold/env.py +49 -0
  30. stoobly_agent/app/cli/scaffold/service.py +25 -0
  31. stoobly_agent/app/cli/scaffold/service_command.py +50 -0
  32. stoobly_agent/app/cli/scaffold/service_config.py +207 -0
  33. stoobly_agent/app/cli/scaffold/service_create_command.py +77 -0
  34. stoobly_agent/app/cli/scaffold/service_workflow.py +18 -0
  35. stoobly_agent/app/cli/scaffold/templates/__init__.py +0 -0
  36. stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context +8 -0
  37. stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.proxy +35 -0
  38. stoobly_agent/app/cli/scaffold/templates/app/.Makefile +118 -0
  39. stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml +15 -0
  40. stoobly_agent/app/cli/scaffold/templates/app/Makefile +3 -0
  41. stoobly_agent/app/cli/scaffold/templates/app/build/.config.yml +1 -0
  42. stoobly_agent/app/cli/scaffold/templates/app/build/.docker-compose.base.yml +11 -0
  43. stoobly_agent/app/cli/scaffold/templates/app/build/mock/.docker-compose.mock.yml +22 -0
  44. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/.configure +5 -0
  45. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/.init +5 -0
  46. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/configure +1 -0
  47. stoobly_agent/app/cli/scaffold/templates/app/build/mock/bin/init +1 -0
  48. stoobly_agent/app/cli/scaffold/templates/app/build/record/.docker-compose.record.yml +22 -0
  49. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/.configure +5 -0
  50. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/.init +5 -0
  51. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/configure +1 -0
  52. stoobly_agent/app/cli/scaffold/templates/app/build/record/bin/init +1 -0
  53. stoobly_agent/app/cli/scaffold/templates/app/build/test/.docker-compose.test.yml +22 -0
  54. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/.configure +5 -0
  55. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/.init +5 -0
  56. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/configure +1 -0
  57. stoobly_agent/app/cli/scaffold/templates/app/build/test/bin/init +1 -0
  58. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/.config.yml +1 -0
  59. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/.docker-compose.base.yml +17 -0
  60. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/.docker-compose.mock.yml +31 -0
  61. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/.configure +10 -0
  62. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/.init +5 -0
  63. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/configure +1 -0
  64. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/bin/init +4 -0
  65. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/mock/docker-compose.yml +1 -0
  66. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/.docker-compose.record.yml +31 -0
  67. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/.configure +10 -0
  68. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/.init +5 -0
  69. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/configure +1 -0
  70. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/bin/init +4 -0
  71. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/record/docker-compose.yml +1 -0
  72. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/.docker-compose.test.yml +31 -0
  73. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/.configure +10 -0
  74. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/.init +3 -0
  75. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/configure +1 -0
  76. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/bin/init +4 -0
  77. stoobly_agent/app/cli/scaffold/templates/app/entrypoint/test/docker-compose.yml +1 -0
  78. stoobly_agent/app/cli/scaffold/templates/app/gateway/.config.yml +1 -0
  79. stoobly_agent/app/cli/scaffold/templates/app/gateway/.docker-compose.base.yml +11 -0
  80. stoobly_agent/app/cli/scaffold/templates/app/gateway/mock/.docker-compose.mock.yml +13 -0
  81. stoobly_agent/app/cli/scaffold/templates/app/gateway/record/.docker-compose.record.yml +13 -0
  82. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/.config.yml +1 -0
  83. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/.docker-compose.base.yml +5 -0
  84. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/.docker-compose.exec.yml +12 -0
  85. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.create +11 -0
  86. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.delete +12 -0
  87. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.disable +3 -0
  88. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.enable +10 -0
  89. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.reset +12 -0
  90. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.run +11 -0
  91. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.snapshot +12 -0
  92. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/exec/bin/.stop +11 -0
  93. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/mock/.docker-compose.mock.yml +12 -0
  94. stoobly_agent/app/cli/scaffold/templates/app/stoobly-ui/record/.docker-compose.record.yml +13 -0
  95. stoobly_agent/app/cli/scaffold/templates/constants.py +63 -0
  96. stoobly_agent/app/cli/scaffold/templates/factory.py +46 -0
  97. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/.configure +3 -0
  98. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/.init +3 -0
  99. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/configure +18 -0
  100. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/init +4 -0
  101. stoobly_agent/app/cli/scaffold/templates/workflow/mock/fixtures/.keep +0 -0
  102. stoobly_agent/app/cli/scaffold/templates/workflow/mock/fixtures.yml +5 -0
  103. stoobly_agent/app/cli/scaffold/templates/workflow/mock/lifecycle_hooks.py +12 -0
  104. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/.configure +3 -0
  105. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/.init +3 -0
  106. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/configure +29 -0
  107. stoobly_agent/app/cli/scaffold/templates/workflow/record/bin/init +4 -0
  108. stoobly_agent/app/cli/scaffold/templates/workflow/record/lifecycle_hooks.py +12 -0
  109. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/.configure +3 -0
  110. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/.init +3 -0
  111. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/configure +18 -0
  112. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/init +4 -0
  113. stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures/.keep +0 -0
  114. stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures.yml +5 -0
  115. stoobly_agent/app/cli/scaffold/templates/workflow/test/lifecycle_hooks.py +12 -0
  116. stoobly_agent/app/cli/scaffold/workflow.py +49 -0
  117. stoobly_agent/app/cli/scaffold/workflow_command.py +137 -0
  118. stoobly_agent/app/cli/scaffold/workflow_copy_command.py +45 -0
  119. stoobly_agent/app/cli/scaffold/workflow_create_command.py +94 -0
  120. stoobly_agent/app/cli/scaffold/workflow_log_command.py +21 -0
  121. stoobly_agent/app/cli/scaffold/workflow_run_command.py +134 -0
  122. stoobly_agent/app/cli/scaffold_cli.py +392 -0
  123. stoobly_agent/cli.py +3 -2
  124. stoobly_agent/config/data_dir.py +40 -14
  125. stoobly_agent/lib/logger.py +3 -2
  126. stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
  127. stoobly_agent/test/config/data_dir_test.py +4 -4
  128. {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.1.dist-info}/METADATA +8 -7
  129. {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.1.dist-info}/RECORD +132 -14
  130. {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.1.dist-info}/WHEEL +1 -1
  131. {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.1.dist-info}/LICENSE +0 -0
  132. {stoobly_agent-0.34.13.dist-info → stoobly_agent-1.0.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,12 @@
1
+ # This file defines lifecyle hooks for when Stoobly intercepts a request
2
+ from stoobly_agent.app.proxy.mock.context import MockContext
3
+
4
+ def handle_before_request(context: MockContext):
5
+ intercept_settings = context.intercept_settings
6
+ flow = context.flow
7
+ request = flow.request
8
+
9
+ # For example, uncomment the following
10
+ #print(f"Agent running in {intercept_settings.mode} mode with {intercept_settings.policy} policy")
11
+ #print(dir(request))
12
+
@@ -0,0 +1,49 @@
1
+ import os
2
+
3
+ from typing import List
4
+
5
+ from .app import App
6
+
7
+ class Workflow():
8
+
9
+ def __init__(self, workflow_name: str, app: App):
10
+ self.__app = app
11
+ self.__workflow_name = workflow_name
12
+
13
+ @property
14
+ def app(self):
15
+ return self.__app
16
+
17
+ @property
18
+ def workflow_name(self):
19
+ return self.__workflow_name
20
+
21
+ @property
22
+ def service(self):
23
+ return self._service
24
+
25
+ @service.setter
26
+ def service(self, v):
27
+ self._service = v
28
+
29
+ @property
30
+ def services(self):
31
+ return list(map(lambda path: os.path.basename(path), self.service_paths))
32
+
33
+ @property
34
+ def service_paths(self):
35
+ services_dir = os.path.join(self.app.scaffold_dir_path, self.app.namespace)
36
+
37
+ services = []
38
+ for filename in os.listdir(services_dir):
39
+ path = os.path.join(services_dir, filename)
40
+ if not os.path.isdir(path):
41
+ continue
42
+
43
+ services.append(path)
44
+
45
+ return services
46
+
47
+ def service_paths_from_services(self, services: List[str]):
48
+ app_namespace_path = self.app.namespace_path
49
+ return list(map(lambda service: os.path.join(app_namespace_path, service), services))
@@ -0,0 +1,137 @@
1
+ import os
2
+ import pdb
3
+ import yaml
4
+
5
+ from stoobly_agent.lib.logger import Logger
6
+
7
+ from .app import App
8
+ from .config import Config
9
+ from .constants import COMPOSE_TEMPLATE, CONFIG_FILE, ENV_FILE, FIXTURES_FOLDER_NAME
10
+ from .docker.constants import DOCKER_COMPOSE_CUSTOM
11
+ from .service_command import ServiceCommand
12
+
13
+ LOG_ID = 'WorkflowCommand'
14
+
15
+ class WorkflowCommand(ServiceCommand):
16
+
17
+ def __init__(self, app: App, **kwargs):
18
+ super().__init__(app, **kwargs)
19
+
20
+ self.__workflow_name = kwargs['workflow_name']
21
+
22
+ @property
23
+ def compose_path(self):
24
+ return os.path.join(
25
+ self.scaffold_dir_path,
26
+ self.compose_relative_path
27
+ )
28
+
29
+ @property
30
+ def compose_relative_path(self):
31
+ return os.path.join(
32
+ self.workflow_relative_path,
33
+ COMPOSE_TEMPLATE.format(workflow=self.workflow_name)
34
+ )
35
+
36
+ @property
37
+ def containers(self):
38
+ _containers = []
39
+ if not os.path.exists(self.compose_path):
40
+ return []
41
+
42
+ with open(self.compose_path, 'r') as fp:
43
+ config = yaml.safe_load(fp)
44
+ services = config.get('services')
45
+ if not isinstance(services, dict):
46
+ return []
47
+
48
+ for service in services:
49
+ _containers.append(f"{self.workflow_name}-{service}-1")
50
+
51
+ return _containers
52
+
53
+ @property
54
+ def custom_compose(self):
55
+ if os.path.exists(self.custom_compose_path):
56
+ with open(self.custom_compose_path, 'r') as fp:
57
+ compose = yaml.safe_load(fp)
58
+ if compose and not isinstance(compose, dict):
59
+ Logger.instance(LOG_ID).warn(f"Could not parse {self.custom_compose_path} as YAML")
60
+ return {}
61
+ return compose
62
+
63
+ @property
64
+ def custom_compose_relative_path(self):
65
+ return os.path.join(
66
+ self.workflow_relative_path,
67
+ DOCKER_COMPOSE_CUSTOM
68
+ )
69
+
70
+ @property
71
+ def custom_compose_path(self):
72
+ return os.path.join(
73
+ self.scaffold_dir_path,
74
+ self.custom_compose_relative_path
75
+ )
76
+
77
+ @property
78
+ def custom_services(self):
79
+ custom_compose = self.custom_compose
80
+
81
+ if not custom_compose:
82
+ return {}
83
+
84
+ services = custom_compose.get('services')
85
+ if not isinstance(services, dict):
86
+ return {}
87
+
88
+ return services
89
+
90
+ @property
91
+ def fixtures_dir_path(self):
92
+ return os.path.join(self.workflow_path, FIXTURES_FOLDER_NAME)
93
+
94
+ @property
95
+ def workflow_config(self):
96
+ return Config(self.workflow_config_path).read()
97
+
98
+ @property
99
+ def workflow_config_path(self):
100
+ return os.path.join(self.workflow_path, CONFIG_FILE)
101
+
102
+ @property
103
+ def workflow_env_path(self):
104
+ return os.path.join(self.workflow_path, ENV_FILE)
105
+
106
+ @property
107
+ def workflow_exists(self):
108
+ return os.path.exists(self.workflow_path)
109
+
110
+ @property
111
+ def workflow_name(self):
112
+ return self.__workflow_name
113
+
114
+ @property
115
+ def workflow_path(self):
116
+ return os.path.join(
117
+ self.scaffold_dir_path,
118
+ self.workflow_relative_path
119
+ )
120
+
121
+ @property
122
+ def workflow_relative_path(self):
123
+ return os.path.join(
124
+ self.service_relative_path,
125
+ self.workflow_name
126
+ )
127
+
128
+ @property
129
+ def workflow_templates_root_dir(self):
130
+ return os.path.join(self.templates_root_dir, 'workflow')
131
+
132
+ def env(self, _c: dict):
133
+ _config = self.app_config.read()
134
+ _config.update(self.service_config)
135
+ _config.update(self.workflow_config)
136
+ _config.update(_c)
137
+ return _config
@@ -0,0 +1,45 @@
1
+ import os
2
+ import pdb
3
+ import shutil
4
+
5
+ from .app import App
6
+ from .constants import COMPOSE_TEMPLATE, WORKFLOW_MOCK_TYPE, WORKFLOW_RECORD_TYPE, WORKFLOW_TEST_TYPE
7
+ from .service_workflow import ServiceWorkflow
8
+ from .workflow_command import WorkflowCommand
9
+
10
+ CORE_WORKFLOWS = [WORKFLOW_MOCK_TYPE, WORKFLOW_RECORD_TYPE, WORKFLOW_TEST_TYPE]
11
+
12
+ class WorkflowCopyCommand(WorkflowCommand):
13
+
14
+ def __init__(self, app: App, **kwargs):
15
+ super().__init__(app, **kwargs)
16
+
17
+ self.__force = not not kwargs.get('force')
18
+
19
+ @property
20
+ def force(self):
21
+ return self.__force
22
+
23
+ def copy(self, destination_workflow_name: str):
24
+ destination_workflow = ServiceWorkflow(self.service_name, destination_workflow_name, self.app)
25
+
26
+ # Create workflow folder
27
+ dest = os.path.join(destination_workflow.path)
28
+ if os.path.exists(dest) and self.force:
29
+ shutil.rmtree(dest)
30
+
31
+ if not os.path.exists(dest):
32
+ os.makedirs(dest)
33
+
34
+ self.app.copy_folders_and_hidden_files(self.workflow_path, dest)
35
+
36
+ compose_file_src = os.path.join(dest, COMPOSE_TEMPLATE.format(workflow=self.workflow_name))
37
+ compose_file_dest = os.path.join(dest, COMPOSE_TEMPLATE.format(workflow=destination_workflow_name))
38
+ os.rename(compose_file_src, compose_file_dest)
39
+
40
+ # Replace workflow name
41
+ with open(compose_file_dest, 'r+') as fp:
42
+ contents = fp.read()
43
+ fp.seek(0)
44
+ fp.write(contents.replace(self.workflow_name, destination_workflow_name))
45
+ fp.truncate()
@@ -0,0 +1,94 @@
1
+ import os
2
+ import pdb
3
+ import shutil
4
+
5
+ from typing import List, TypedDict, Union
6
+
7
+ from .app import App
8
+ from .constants import WORKFLOW_MOCK_TYPE, WORKFLOW_RECORD_TYPE, WORKFLOW_TEST_TYPE, WORKFLOW_TEMPLATE
9
+ from .docker.service.builder import ServiceBuilder
10
+ from .docker.workflow.mock_decorator import MockDecorator
11
+ from .docker.workflow.reverse_proxy_decorator import ReverseProxyDecorator
12
+ from .docker.workflow.builder import WorkflowBuilder
13
+ from .templates.factory import custom_files, maintained_files
14
+ from .workflow_command import WorkflowCommand
15
+
16
+ CORE_WORKFLOWS = [WORKFLOW_MOCK_TYPE, WORKFLOW_RECORD_TYPE, WORKFLOW_TEST_TYPE]
17
+
18
+ class BuildOptions(TypedDict):
19
+ builder_class: type
20
+ headless: bool
21
+ service_builder: ServiceBuilder
22
+ template: WORKFLOW_TEMPLATE
23
+ workflow_decorators: List[Union[MockDecorator, ReverseProxyDecorator]]
24
+
25
+ class WorkflowCreateCommand(WorkflowCommand):
26
+
27
+ def __init__(self, app: App, **kwargs):
28
+ super().__init__(app, **kwargs)
29
+
30
+ self.__env_vars: List[str] = kwargs.get('env') or []
31
+ self.__force = not not kwargs.get('force')
32
+
33
+ @property
34
+ def workflow_templates_path(self):
35
+ return self.build_workflow_templates_path(self.workflow_name)
36
+
37
+ @property
38
+ def env_vars(self):
39
+ return self.__env_vars
40
+
41
+ @property
42
+ def force(self):
43
+ return self.__force
44
+
45
+ def build(self, **kwargs: BuildOptions):
46
+ # Create workflow folder
47
+ dest = os.path.join(self.workflow_path)
48
+ if os.path.exists(dest) and self.force:
49
+ shutil.rmtree(dest)
50
+
51
+ if not os.path.exists(dest):
52
+ os.makedirs(dest)
53
+
54
+ # Create workflow maintained compose file
55
+ workflow_builder = self.__write_docker_compose_file(**kwargs)
56
+ self.__copy_templates(workflow_builder, kwargs.get('template'))
57
+
58
+ def build_workflow_templates_path(self, workflow_name: str):
59
+ return os.path.join(self.workflow_templates_root_dir, workflow_name)
60
+
61
+ def __copy_templates(self, workflow_builder: WorkflowBuilder, template: WORKFLOW_TEMPLATE = None):
62
+ if not template:
63
+ templates_path = self.workflow_templates_path
64
+ else:
65
+ templates_path = self.build_workflow_templates_path(template)
66
+
67
+ if not os.path.exists(templates_path):
68
+ return
69
+
70
+ # Maintained files are files that will always be overwritten
71
+ maintained_workflow_files = maintained_files(self.workflow_name, workflow_builder)
72
+ self.copy_files(templates_path, maintained_workflow_files, self.workflow_path)
73
+
74
+ # Custom files are files that may be modified by the user
75
+ custom_workflow_files = custom_files(self.workflow_name, workflow_builder)
76
+ self.copy_files_no_replace(templates_path, custom_workflow_files, self.workflow_path)
77
+
78
+ def __write_docker_compose_file(self, **kwargs: BuildOptions):
79
+ builder_class = kwargs.get('builder_class') or WorkflowBuilder
80
+ service_builder = kwargs.get('service_builder') or ServiceBuilder(self.service_config)
81
+ workflow_decorators: List[Union[MockDecorator, ReverseProxyDecorator]] = kwargs.get('workflow_decorators')
82
+
83
+ workflow_builder = builder_class(self.workflow_path, service_builder)
84
+ workflow_builder.with_env(list(self.env_vars))
85
+ workflow_builder.build_all()
86
+
87
+ if isinstance(workflow_decorators, list):
88
+ for workflow_decorator in workflow_decorators:
89
+ workflow_decorator(workflow_builder).decorate()
90
+
91
+ workflow_builder.write()
92
+ workflow_builder.initialize_custom_file()
93
+
94
+ return workflow_builder
@@ -0,0 +1,21 @@
1
+ import os
2
+ import pdb
3
+ import yaml
4
+
5
+ from .app import App
6
+ from .workflow_command import WorkflowCommand
7
+
8
+ class WorkflowLogCommand(WorkflowCommand):
9
+ def __init__(self, app: App, **kwargs):
10
+ super().__init__(app, **kwargs)
11
+
12
+ def all(self):
13
+ commands = []
14
+ containers = self.containers
15
+
16
+ for container in containers:
17
+ command = ['docker', 'logs', container]
18
+
19
+ commands.append(' '.join(command))
20
+
21
+ return commands
@@ -0,0 +1,134 @@
1
+ import os
2
+ import pdb
3
+
4
+ from stoobly_agent.config.data_dir import DataDir
5
+ from stoobly_agent.lib.logger import Logger
6
+
7
+ from .app import App
8
+ from .constants import APP_NETWORK_ENV, CERTS_DIR_ENV, CONTEXT_DIR_ENV, SERVICE_NAME_ENV, USER_ID_ENV, WORKFLOW_NAME_ENV
9
+ from .env import Env
10
+ from .workflow_command import WorkflowCommand
11
+
12
+ LOG_ID = 'WorkflowRunCommand'
13
+
14
+ class WorkflowRunCommand(WorkflowCommand):
15
+ def __init__(self, app: App, **kwargs):
16
+ super().__init__(app, **kwargs)
17
+
18
+ self.__current_working_dir = os.getcwd()
19
+ self.__certs_dir_path = app.certs_dir_path
20
+ self.__context_dir_path = app.context_dir_path
21
+ self.__extra_compose_path = kwargs.get('extra_compose_path')
22
+ self.__network = kwargs.get('network') or app.network
23
+
24
+ @property
25
+ def certs_dir_path(self):
26
+ if not self.__certs_dir_path:
27
+ data_dir = DataDir.instance()
28
+ dir_path = os.path.join(data_dir.tmp_dir_path, 'certs')
29
+ if not os.path.exists(dir_path):
30
+ os.mkdir(dir_path)
31
+
32
+ return self.__certs_dir_path
33
+
34
+ @property
35
+ def context_dir_path(self):
36
+ if not self.__context_dir_path:
37
+ data_dir = DataDir.instance()
38
+ return os.path.dirname(data_dir.path)
39
+
40
+ return self.__context_dir_path
41
+
42
+ @property
43
+ def current_working_dir(self):
44
+ return self.__current_working_dir
45
+
46
+ @current_working_dir.setter
47
+ def current_working_dir(self, v):
48
+ self.__current_working_dir = v
49
+
50
+ @property
51
+ def extra_compose_path(self):
52
+ return self.__extra_compose_path
53
+
54
+ @property
55
+ def network(self):
56
+ return self.__network
57
+
58
+ def create_network(self):
59
+ return f"docker network create {self.network} 2> /dev/null"
60
+
61
+ def up(self):
62
+ if not os.path.exists(self.compose_path):
63
+ return ''
64
+
65
+ command = ['COMPOSE_IGNORE_ORPHANS=true', 'docker', 'compose']
66
+
67
+ # Add docker compose file
68
+ command.append(f"-f {os.path.relpath(self.compose_path, self.__current_working_dir)}")
69
+
70
+ # Add custom docker compose file
71
+ custom_services = self.custom_services
72
+
73
+ if custom_services:
74
+ uses_profile = False
75
+ for service_name in custom_services:
76
+ service = custom_services[service_name]
77
+ profiles = service.get('profiles')
78
+ if isinstance(profiles, list):
79
+ if self.workflow_name in profiles:
80
+ uses_profile = True
81
+ break
82
+ if not uses_profile:
83
+ # TODO: looking into why warning does not print in docker
84
+ Logger.instance(LOG_ID).error(f"Missing {self.workflow_name} profile in custom compose file")
85
+
86
+ command.append(f"-f {os.path.relpath(self.custom_compose_path, self.__current_working_dir)}")
87
+
88
+ if self.extra_compose_path:
89
+ command.append(f"-f {os.path.relpath(self.extra_compose_path, self.__current_working_dir)}")
90
+
91
+ command.append(f"--profile {self.workflow_name}")
92
+ command.append('up')
93
+ command.append('-d')
94
+ command.append('--build')
95
+
96
+ self.write_env()
97
+
98
+ return ' '.join(command)
99
+
100
+ def down(self):
101
+ if not os.path.exists(self.compose_path):
102
+ return ''
103
+
104
+ command = ['docker', 'compose']
105
+
106
+ # Add docker compose file
107
+ command.append(f"-f {os.path.relpath(self.compose_path, os.getcwd())}")
108
+
109
+ # Add custom docker compose file
110
+ if self.custom_services:
111
+ command.append(f"-f {os.path.relpath(self.custom_compose_path, self.__current_working_dir)}")
112
+
113
+ if self.extra_compose_path:
114
+ command.append(f"-f {os.path.relpath(self.extra_compose_path, self.__current_working_dir)}")
115
+
116
+ command.append(f"--profile {self.workflow_name}")
117
+ command.append('down')
118
+
119
+ return ' '.join(command)
120
+
121
+ def write_env(self):
122
+ _config = {}
123
+ _config[CERTS_DIR_ENV] = self.certs_dir_path
124
+ _config[CONTEXT_DIR_ENV] = self.context_dir_path
125
+ _config[SERVICE_NAME_ENV] = self.service_name
126
+ _config[USER_ID_ENV] = os.getuid()
127
+ _config[WORKFLOW_NAME_ENV] = self.workflow_name
128
+
129
+ if self.network:
130
+ _config[APP_NETWORK_ENV] = self.network
131
+
132
+ env_vars = self.config(_config)
133
+ env_path = self.workflow_env_path
134
+ Env(env_path).write(env_vars)