argus-alm 0.14.2__py3-none-any.whl → 0.15.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. argus/_version.py +21 -0
  2. argus/backend/.gitkeep +0 -0
  3. argus/backend/__init__.py +0 -0
  4. argus/backend/cli.py +57 -0
  5. argus/backend/controller/__init__.py +0 -0
  6. argus/backend/controller/admin.py +20 -0
  7. argus/backend/controller/admin_api.py +355 -0
  8. argus/backend/controller/api.py +589 -0
  9. argus/backend/controller/auth.py +67 -0
  10. argus/backend/controller/client_api.py +109 -0
  11. argus/backend/controller/main.py +316 -0
  12. argus/backend/controller/notification_api.py +72 -0
  13. argus/backend/controller/notifications.py +13 -0
  14. argus/backend/controller/planner_api.py +194 -0
  15. argus/backend/controller/team.py +129 -0
  16. argus/backend/controller/team_ui.py +19 -0
  17. argus/backend/controller/testrun_api.py +513 -0
  18. argus/backend/controller/view_api.py +188 -0
  19. argus/backend/controller/views_widgets/__init__.py +0 -0
  20. argus/backend/controller/views_widgets/graphed_stats.py +54 -0
  21. argus/backend/controller/views_widgets/graphs.py +68 -0
  22. argus/backend/controller/views_widgets/highlights.py +135 -0
  23. argus/backend/controller/views_widgets/nemesis_stats.py +26 -0
  24. argus/backend/controller/views_widgets/summary.py +43 -0
  25. argus/backend/db.py +98 -0
  26. argus/backend/error_handlers.py +41 -0
  27. argus/backend/events/event_processors.py +34 -0
  28. argus/backend/models/__init__.py +0 -0
  29. argus/backend/models/argus_ai.py +24 -0
  30. argus/backend/models/github_issue.py +60 -0
  31. argus/backend/models/plan.py +24 -0
  32. argus/backend/models/result.py +187 -0
  33. argus/backend/models/runtime_store.py +58 -0
  34. argus/backend/models/view_widgets.py +25 -0
  35. argus/backend/models/web.py +403 -0
  36. argus/backend/plugins/__init__.py +0 -0
  37. argus/backend/plugins/core.py +248 -0
  38. argus/backend/plugins/driver_matrix_tests/controller.py +66 -0
  39. argus/backend/plugins/driver_matrix_tests/model.py +429 -0
  40. argus/backend/plugins/driver_matrix_tests/plugin.py +21 -0
  41. argus/backend/plugins/driver_matrix_tests/raw_types.py +62 -0
  42. argus/backend/plugins/driver_matrix_tests/service.py +61 -0
  43. argus/backend/plugins/driver_matrix_tests/udt.py +42 -0
  44. argus/backend/plugins/generic/model.py +86 -0
  45. argus/backend/plugins/generic/plugin.py +15 -0
  46. argus/backend/plugins/generic/types.py +14 -0
  47. argus/backend/plugins/loader.py +39 -0
  48. argus/backend/plugins/sct/controller.py +224 -0
  49. argus/backend/plugins/sct/plugin.py +37 -0
  50. argus/backend/plugins/sct/resource_setup.py +177 -0
  51. argus/backend/plugins/sct/service.py +682 -0
  52. argus/backend/plugins/sct/testrun.py +288 -0
  53. argus/backend/plugins/sct/udt.py +100 -0
  54. argus/backend/plugins/sirenada/model.py +118 -0
  55. argus/backend/plugins/sirenada/plugin.py +16 -0
  56. argus/backend/service/admin.py +26 -0
  57. argus/backend/service/argus_service.py +696 -0
  58. argus/backend/service/build_system_monitor.py +185 -0
  59. argus/backend/service/client_service.py +127 -0
  60. argus/backend/service/event_service.py +18 -0
  61. argus/backend/service/github_service.py +233 -0
  62. argus/backend/service/jenkins_service.py +269 -0
  63. argus/backend/service/notification_manager.py +159 -0
  64. argus/backend/service/planner_service.py +608 -0
  65. argus/backend/service/release_manager.py +229 -0
  66. argus/backend/service/results_service.py +690 -0
  67. argus/backend/service/stats.py +610 -0
  68. argus/backend/service/team_manager_service.py +82 -0
  69. argus/backend/service/test_lookup.py +172 -0
  70. argus/backend/service/testrun.py +489 -0
  71. argus/backend/service/user.py +308 -0
  72. argus/backend/service/views.py +219 -0
  73. argus/backend/service/views_widgets/__init__.py +0 -0
  74. argus/backend/service/views_widgets/graphed_stats.py +180 -0
  75. argus/backend/service/views_widgets/highlights.py +374 -0
  76. argus/backend/service/views_widgets/nemesis_stats.py +34 -0
  77. argus/backend/template_filters.py +27 -0
  78. argus/backend/tests/__init__.py +0 -0
  79. argus/backend/tests/client_service/__init__.py +0 -0
  80. argus/backend/tests/client_service/test_submit_results.py +79 -0
  81. argus/backend/tests/conftest.py +180 -0
  82. argus/backend/tests/results_service/__init__.py +0 -0
  83. argus/backend/tests/results_service/test_best_results.py +178 -0
  84. argus/backend/tests/results_service/test_cell.py +65 -0
  85. argus/backend/tests/results_service/test_chartjs_additional_functions.py +259 -0
  86. argus/backend/tests/results_service/test_create_chartjs.py +220 -0
  87. argus/backend/tests/results_service/test_result_metadata.py +100 -0
  88. argus/backend/tests/results_service/test_results_service.py +203 -0
  89. argus/backend/tests/results_service/test_validation_rules.py +213 -0
  90. argus/backend/tests/view_widgets/__init__.py +0 -0
  91. argus/backend/tests/view_widgets/test_highlights_api.py +532 -0
  92. argus/backend/util/common.py +65 -0
  93. argus/backend/util/config.py +38 -0
  94. argus/backend/util/encoders.py +56 -0
  95. argus/backend/util/logsetup.py +80 -0
  96. argus/backend/util/module_loaders.py +30 -0
  97. argus/backend/util/send_email.py +91 -0
  98. argus/client/base.py +1 -3
  99. argus/client/driver_matrix_tests/cli.py +17 -8
  100. argus/client/generic/cli.py +4 -2
  101. argus/client/generic/client.py +1 -0
  102. argus/client/generic_result.py +48 -9
  103. argus/client/sct/client.py +1 -3
  104. argus/client/sirenada/client.py +4 -1
  105. argus/client/tests/__init__.py +0 -0
  106. argus/client/tests/conftest.py +19 -0
  107. argus/client/tests/test_package.py +45 -0
  108. argus/client/tests/test_results.py +224 -0
  109. argus/common/sct_types.py +3 -0
  110. argus/common/sirenada_types.py +1 -1
  111. {argus_alm-0.14.2.dist-info → argus_alm-0.15.2.dist-info}/METADATA +43 -19
  112. argus_alm-0.15.2.dist-info/RECORD +122 -0
  113. {argus_alm-0.14.2.dist-info → argus_alm-0.15.2.dist-info}/WHEEL +2 -1
  114. argus_alm-0.15.2.dist-info/entry_points.txt +3 -0
  115. argus_alm-0.15.2.dist-info/top_level.txt +1 -0
  116. argus_alm-0.14.2.dist-info/RECORD +0 -20
  117. argus_alm-0.14.2.dist-info/entry_points.txt +0 -4
  118. {argus_alm-0.14.2.dist-info → argus_alm-0.15.2.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,86 @@
1
+ from datetime import datetime
2
+ import re
3
+ from uuid import UUID
4
+ from cassandra.cqlengine import columns
5
+ from cassandra.cqlengine.models import Model
6
+ from argus.backend.db import ScyllaCluster
7
+ from argus.backend.models.web import ArgusRelease
8
+ from argus.backend.plugins.core import PluginModelBase
9
+ from argus.backend.plugins.generic.types import GenericRunFinishRequest, GenericRunSubmitRequest
10
+ from argus.common.enums import TestStatus
11
+
12
+
13
+ class GenericPluginException(Exception):
14
+ pass
15
+
16
+
17
+ class GenericRun(PluginModelBase):
18
+ _plugin_name = "generic"
19
+ __table_name__ = "generic_run"
20
+ logs = columns.Map(key_type=columns.Text(), value_type=columns.Text())
21
+ started_by = columns.Text()
22
+ # TODO: Legacy field name, should be renamed to product_version and abstracted
23
+ scylla_version = columns.Text()
24
+
25
+ @classmethod
26
+ def _stats_query(cls) -> str:
27
+ return ("SELECT id, test_id, group_id, release_id, status, start_time, build_job_url, build_id, "
28
+ f"assignee, end_time, investigation_status, heartbeat, scylla_version FROM {cls.table_name()} WHERE build_id IN ? PER PARTITION LIMIT 15")
29
+
30
+ @classmethod
31
+ def get_distinct_product_versions(cls, release: ArgusRelease, cluster: ScyllaCluster = None) -> list[str]:
32
+ if not cluster:
33
+ cluster = ScyllaCluster.get()
34
+ statement = cluster.prepare(f"SELECT scylla_version FROM {cls.table_name()} WHERE release_id = ?")
35
+ rows = cluster.session.execute(query=statement, parameters=(release.id,))
36
+ unique_versions = {r["scylla_version"] for r in rows if r["scylla_version"]}
37
+
38
+ return sorted(list(unique_versions), reverse=True)
39
+
40
+ def submit_product_version(self, version: str):
41
+ pattern = re.compile(r"((?P<short>[\w.~]+)-(?P<build>(0\.)?(?P<date>[0-9]{8,8})\.(?P<commit>\w+).*))")
42
+ if match := pattern.search(version):
43
+ self.scylla_version = match.group("short")
44
+ try:
45
+ new_assignee = self.get_assignment(match.group("short"))
46
+ except Model.DoesNotExist:
47
+ new_assignee = None
48
+ if new_assignee:
49
+ self.assignee = new_assignee
50
+ self.set_full_version(version)
51
+
52
+ @classmethod
53
+ def load_test_run(cls, run_id: UUID) -> 'GenericRun':
54
+ return cls.get(id=run_id)
55
+
56
+ @classmethod
57
+ def submit_run(cls, request_data: GenericRunSubmitRequest) -> 'GenericRun':
58
+ try:
59
+ run = cls.get(id=request_data["run_id"])
60
+ raise GenericPluginException(
61
+ f"Run with UUID {request_data['run_id']} already exists.", request_data["run_id"])
62
+ except cls.DoesNotExist:
63
+ pass
64
+ run = cls()
65
+ run.start_time = datetime.utcnow()
66
+ run.build_id = request_data["build_id"]
67
+ run.started_by = request_data["started_by"]
68
+ run.id = request_data["run_id"]
69
+ run.build_job_url = request_data["build_url"]
70
+ run.assign_categories()
71
+ try:
72
+ run.assignee = run.get_scheduled_assignee()
73
+ except Model.DoesNotExist:
74
+ run.assignee = None
75
+ if version := request_data.get("scylla_version"):
76
+ run.submit_product_version(version)
77
+ run.status = TestStatus.RUNNING.value
78
+ run.save()
79
+
80
+ return run
81
+
82
+ def finish_run(self, payload: GenericRunFinishRequest = None):
83
+ self.end_time = datetime.utcnow()
84
+ self.status = TestStatus(payload["status"]).value
85
+ if version := payload.get("scylla_version"):
86
+ self.submit_product_version(version)
@@ -0,0 +1,15 @@
1
+ from flask import Blueprint
2
+
3
+ from argus.backend.plugins.core import PluginInfoBase, PluginModelBase
4
+ from argus.backend.plugins.generic.model import GenericRun
5
+
6
+
7
+ class PluginInfo(PluginInfoBase):
8
+ name: str = "generic"
9
+ model: PluginModelBase = GenericRun
10
+ controller: Blueprint = None
11
+ all_models = [
12
+ GenericRun
13
+ ]
14
+ all_types = [
15
+ ]
@@ -0,0 +1,14 @@
1
+ from typing import TypedDict
2
+
3
+
4
+ class GenericRunSubmitRequest(TypedDict):
5
+ build_id: str
6
+ build_url: str
7
+ run_id: str
8
+ started_by: str
9
+ scylla_version: str | None
10
+
11
+
12
+ class GenericRunFinishRequest(TypedDict):
13
+ status: str
14
+ scylla_version: str | None
@@ -0,0 +1,39 @@
1
+ from pathlib import Path
2
+ import typing
3
+ from argus.backend.plugins.core import PluginInfoBase
4
+ from argus.backend.plugins.core import PluginModelBase
5
+
6
+
7
+ class PluginModule(typing.Protocol):
8
+ PluginInfo: PluginInfoBase
9
+
10
+
11
+ def plugin_loader() -> dict[str, PluginInfoBase]:
12
+ loader_path = Path(__file__).parent
13
+ plugin_dirs = [p for p in loader_path.glob("*") if p.is_dir()]
14
+ modules = {}
15
+ parent_module = ".".join(__name__.split(".")[:-1])
16
+ for directory in plugin_dirs:
17
+ if (plugin_path := directory / "plugin.py").exists():
18
+ rel_path = str(plugin_path.relative_to(loader_path))
19
+ module_path = rel_path.replace("/", ".").replace(".py", "")
20
+ module: PluginModule = __import__(
21
+ f"{parent_module}.{module_path}",
22
+ globals=globals(),
23
+ fromlist=("PluginInfo",)
24
+ )
25
+ plugin = module.PluginInfo
26
+ modules[plugin.name] = plugin
27
+
28
+ return modules
29
+
30
+
31
+ AVAILABLE_PLUGINS = plugin_loader()
32
+
33
+
34
+ def all_plugin_models(include_all=False) -> list[PluginModelBase]:
35
+ return [model for plugin in AVAILABLE_PLUGINS.values() for model in plugin.all_models if issubclass(model, PluginModelBase) or include_all]
36
+
37
+
38
+ def all_plugin_types():
39
+ return [user_type for plugin in AVAILABLE_PLUGINS.values() for user_type in plugin.all_types]
@@ -0,0 +1,224 @@
1
+ from flask import Blueprint, request
2
+
3
+ from argus.backend.error_handlers import handle_api_exception
4
+ from argus.backend.service.user import api_login_required
5
+ from argus.backend.plugins.sct.service import SCTService
6
+ from argus.backend.util.common import get_payload
7
+
8
+ bp = Blueprint("sct_api", __name__, url_prefix="/sct")
9
+ bp.register_error_handler(Exception, handle_api_exception)
10
+
11
+
12
+ @bp.route("/<string:run_id>/packages/submit", methods=["POST"])
13
+ @api_login_required
14
+ def sct_submit_packages(run_id: str):
15
+ payload = get_payload(request)
16
+ result = SCTService.submit_packages(run_id=run_id, packages=payload["packages"])
17
+ return {
18
+ "status": "ok",
19
+ "response": result
20
+ }
21
+
22
+
23
+ @bp.route("/<string:run_id>/screenshots/submit", methods=["POST"])
24
+ @api_login_required
25
+ def sct_submit_screenshots(run_id: str):
26
+ payload = get_payload(request)
27
+ result = SCTService.submit_screenshots(run_id=run_id, screenshot_links=payload["screenshot_links"])
28
+ return {
29
+ "status": "ok",
30
+ "response": result
31
+ }
32
+
33
+
34
+ @bp.route("/<string:run_id>/sct_runner/set", methods=["POST"])
35
+ @api_login_required
36
+ def sct_set_runner(run_id: str):
37
+ payload = get_payload(request)
38
+ result = SCTService.set_sct_runner(
39
+ run_id=run_id,
40
+ public_ip=payload["public_ip"],
41
+ private_ip=payload["private_ip"],
42
+ region=payload["region"],
43
+ backend=payload["backend"],
44
+ name=payload.get("name")
45
+ )
46
+ return {
47
+ "status": "ok",
48
+ "response": result
49
+ }
50
+
51
+
52
+ @bp.route("/<string:run_id>/resource/create", methods=["POST"])
53
+ @api_login_required
54
+ def sct_resource_create(run_id: str):
55
+ payload = get_payload(request)
56
+ result = SCTService.create_resource(run_id=run_id, resource_details=payload["resource"])
57
+ return {
58
+ "status": "ok",
59
+ "response": result
60
+ }
61
+
62
+
63
+ @bp.route("/<string:run_id>/resource/<string:resource_name>/terminate", methods=["POST"])
64
+ @api_login_required
65
+ def sct_resource_terminate(run_id: str, resource_name: str):
66
+ payload = get_payload(request)
67
+ result = SCTService.terminate_resource(run_id=run_id, resource_name=resource_name, reason=payload["reason"])
68
+ return {
69
+ "status": "ok",
70
+ "response": result
71
+ }
72
+
73
+
74
+ @bp.route("/<string:run_id>/resource/<string:resource_name>/shards", methods=["POST"])
75
+ @api_login_required
76
+ def sct_resource_update_shards(run_id: str, resource_name: str):
77
+ payload = get_payload(request)
78
+ result = SCTService.update_resource_shards(run_id=run_id, resource_name=resource_name, new_shards=payload["shards"])
79
+ return {
80
+ "status": "ok",
81
+ "response": result
82
+ }
83
+
84
+
85
+ @bp.route("/<string:run_id>/resource/<string:resource_name>/update", methods=["POST"])
86
+ @api_login_required
87
+ def sct_resource_update(run_id: str, resource_name: str):
88
+ payload = get_payload(request)
89
+ result = SCTService.update_resource(run_id=run_id, resource_name=resource_name, update_data=payload["update_data"])
90
+ return {
91
+ "status": "ok",
92
+ "response": result
93
+ }
94
+
95
+
96
+ @bp.route("/<string:run_id>/nemesis/submit", methods=["POST"])
97
+ @api_login_required
98
+ def sct_nemesis_submit(run_id: str):
99
+ payload = get_payload(request)
100
+ result = SCTService.submit_nemesis(run_id=run_id, nemesis_details=payload["nemesis"])
101
+ return {
102
+ "status": "ok",
103
+ "response": result
104
+ }
105
+
106
+
107
+ @bp.route("/<string:run_id>/nemesis/finalize", methods=["POST"])
108
+ @api_login_required
109
+ def sct_nemesis_finalize(run_id: str):
110
+ payload = get_payload(request)
111
+ result = SCTService.finalize_nemesis(run_id=run_id, nemesis_details=payload["nemesis"])
112
+ return {
113
+ "status": "ok",
114
+ "response": result
115
+ }
116
+
117
+
118
+ @bp.route("/<string:run_id>/events/submit", methods=["POST"])
119
+ @api_login_required
120
+ def sct_events_submit(run_id: str):
121
+ payload = get_payload(request)
122
+ result = SCTService.submit_events(run_id=run_id, events=payload["events"])
123
+ return {
124
+ "status": "ok",
125
+ "response": result
126
+ }
127
+
128
+
129
+ @bp.route("/<string:run_id>/gemini/submit", methods=["POST"])
130
+ @api_login_required
131
+ def sct_gemini_results_submit(run_id: str):
132
+ payload = get_payload(request)
133
+ result = SCTService.submit_gemini_results(run_id=run_id, gemini_data=payload["gemini_data"])
134
+ return {
135
+ "status": "ok",
136
+ "response": result
137
+ }
138
+
139
+
140
+ @bp.route("/<string:run_id>/performance/submit", methods=["POST"])
141
+ @api_login_required
142
+ def sct_performance_results_submit(run_id: str):
143
+ payload = get_payload(request)
144
+ result = SCTService.submit_performance_results(run_id=run_id, performance_results=payload["performance_results"])
145
+ return {
146
+ "status": "ok",
147
+ "response": result
148
+ }
149
+
150
+
151
+ @bp.route("/<string:run_id>/performance/history", methods=["GET"])
152
+ @api_login_required
153
+ def sct_get_performance_history(run_id: str):
154
+ result = SCTService.get_performance_history_for_test(run_id=run_id)
155
+ return {
156
+ "status": "ok",
157
+ "response": result
158
+ }
159
+
160
+
161
+ @bp.route("/release/<string:release_name>/kernels", methods=["GET"])
162
+ @api_login_required
163
+ def sct_get_kernel_report(release_name: str):
164
+ result = SCTService.get_scylla_version_kernels_report(release_name=release_name)
165
+ return {
166
+ "status": "ok",
167
+ "response": result
168
+ }
169
+
170
+
171
+ @bp.route("/<string:run_id>/junit/submit", methods=["POST"])
172
+ @api_login_required
173
+ def sct_submit_junit_report(run_id: str):
174
+ payload = get_payload(request)
175
+ result = SCTService.junit_submit(run_id, payload["file_name"], payload["content"])
176
+ return {
177
+ "status": "ok",
178
+ "response": result
179
+ }
180
+
181
+
182
+ @bp.route("/<string:run_id>/junit/get_all", methods=["GET"])
183
+ @api_login_required
184
+ def sct_get_junit_reports(run_id: str):
185
+ result = SCTService.junit_get_all(run_id)
186
+ return {
187
+ "status": "ok",
188
+ "response": result
189
+ }
190
+
191
+
192
+ @bp.route("/<string:run_id>/similar_events", methods=["GET"])
193
+ @api_login_required
194
+ def sct_get_similar_events(run_id: str):
195
+ result = SCTService.get_similar_events(run_id=run_id)
196
+ return {
197
+ "status": "ok",
198
+ "response": result
199
+ }
200
+
201
+
202
+ @bp.route("/similar_runs_info", methods=["POST"])
203
+ @api_login_required
204
+ def sct_get_similar_runs_info():
205
+ """Get build IDs and issues for a list of run IDs"""
206
+ data = request.get_json()
207
+ if not data or "run_ids" not in data:
208
+ return {
209
+ "status": "error",
210
+ "response": "Missing run_ids parameter"
211
+ }, 400
212
+
213
+ run_ids = data["run_ids"]
214
+ if not isinstance(run_ids, list):
215
+ return {
216
+ "status": "error",
217
+ "response": "run_ids must be a list"
218
+ }, 400
219
+
220
+ result = SCTService.get_similar_runs_info(run_ids=run_ids)
221
+ return {
222
+ "status": "ok",
223
+ "response": result
224
+ }
@@ -0,0 +1,37 @@
1
+ from flask import Blueprint
2
+
3
+ from argus.backend.plugins.sct.testrun import SCTJunitReports, SCTTestRun
4
+ from argus.backend.plugins.sct.controller import bp as sct_bp
5
+ from argus.backend.plugins.core import PluginInfoBase, PluginModelBase
6
+ from argus.backend.plugins.sct.udt import (
7
+ CloudInstanceDetails,
8
+ CloudNodesInfo,
9
+ CloudResource,
10
+ CloudSetupDetails,
11
+ EventsBySeverity,
12
+ NemesisRunInfo,
13
+ NodeDescription,
14
+ PackageVersion,
15
+ PerformanceHDRHistogram,
16
+ )
17
+
18
+
19
+ class PluginInfo(PluginInfoBase):
20
+ name: str = "scylla-cluster-tests"
21
+ model: PluginModelBase = SCTTestRun
22
+ controller: Blueprint = sct_bp
23
+ all_models = [
24
+ SCTTestRun,
25
+ SCTJunitReports,
26
+ ]
27
+ all_types = [
28
+ NemesisRunInfo,
29
+ NodeDescription,
30
+ EventsBySeverity,
31
+ CloudResource,
32
+ CloudSetupDetails,
33
+ CloudNodesInfo,
34
+ CloudInstanceDetails,
35
+ PackageVersion,
36
+ PerformanceHDRHistogram,
37
+ ]
@@ -0,0 +1,177 @@
1
+ import logging
2
+ from argus.backend.plugins.sct.udt import CloudNodesInfo, CloudSetupDetails
3
+
4
+ LOGGER = logging.getLogger(__name__)
5
+
6
+
7
+ def _get_node_amounts(config: dict) -> tuple[int, int]:
8
+ num_db_node = config.get("n_db_nodes")
9
+ num_db_node = sum([int(i) for i in num_db_node.split()]) if isinstance(num_db_node, str) else num_db_node
10
+ num_loaders = config.get("n_loaders")
11
+ num_loaders = sum([int(i) for i in num_loaders.split()]) if isinstance(num_loaders, str) else num_loaders
12
+
13
+ return num_db_node, num_loaders
14
+
15
+
16
+ def _prepare_aws_resource_setup(sct_config: dict) -> CloudSetupDetails:
17
+ num_db_nodes, n_loaders = _get_node_amounts(sct_config)
18
+ db_node_setup = CloudNodesInfo(image_id=sct_config.get("ami_id_db_scylla"),
19
+ instance_type=sct_config.get("instance_type_db"),
20
+ node_amount=num_db_nodes,
21
+ post_behaviour=sct_config.get("post_behavior_db_nodes"))
22
+ loader_node_setup = CloudNodesInfo(image_id=sct_config.get("ami_id_loader"),
23
+ instance_type=sct_config.get("instance_type_loader"),
24
+ node_amount=n_loaders,
25
+ post_behaviour=sct_config.get("post_behavior_loader_nodes"))
26
+ monitor_node_setup = CloudNodesInfo(image_id=sct_config.get("ami_id_monitor"),
27
+ instance_type=sct_config.get("instance_type_monitor"),
28
+ node_amount=sct_config.get("n_monitor_nodes"),
29
+ post_behaviour=sct_config.get("post_behavior_monitor_nodes"))
30
+ cloud_setup = CloudSetupDetails(db_node=db_node_setup, loader_node=loader_node_setup,
31
+ monitor_node=monitor_node_setup, backend=sct_config.get("cluster_backend"))
32
+
33
+ return cloud_setup
34
+
35
+
36
+ def _prepare_gce_resource_setup(sct_config: dict) -> CloudSetupDetails:
37
+ num_db_nodes, n_loaders = _get_node_amounts(sct_config)
38
+ db_node_setup = CloudNodesInfo(image_id=sct_config.get("gce_image_db"),
39
+ instance_type=sct_config.get("gce_instance_type_db"),
40
+ node_amount=num_db_nodes,
41
+ post_behaviour=sct_config.get("post_behavior_db_nodes"))
42
+ loader_node_setup = CloudNodesInfo(image_id=sct_config.get("gce_image_loader"),
43
+ instance_type=sct_config.get("gce_instance_type_loader"),
44
+ node_amount=n_loaders,
45
+ post_behaviour=sct_config.get("post_behavior_loader_nodes"))
46
+ monitor_node_setup = CloudNodesInfo(image_id=sct_config.get("gce_image_monitor"),
47
+ instance_type=sct_config.get("gce_instance_type_monitor"),
48
+ node_amount=sct_config.get("n_monitor_nodes"),
49
+ post_behaviour=sct_config.get("post_behavior_monitor_nodes"))
50
+ cloud_setup = CloudSetupDetails(db_node=db_node_setup, loader_node=loader_node_setup,
51
+ monitor_node=monitor_node_setup, backend=sct_config.get("cluster_backend"))
52
+
53
+ return cloud_setup
54
+
55
+
56
+ def _prepare_azure_resource_setup(sct_config: dict) -> CloudSetupDetails:
57
+ num_db_nodes, n_loaders = _get_node_amounts(sct_config)
58
+ db_node_setup = CloudNodesInfo(image_id=sct_config.get("azure_image_db"),
59
+ instance_type=sct_config.get("azure_instance_type_db"),
60
+ node_amount=num_db_nodes,
61
+ post_behaviour=sct_config.get("post_behavior_db_nodes"))
62
+ loader_node_setup = CloudNodesInfo(image_id=sct_config.get("azure_image_loader"),
63
+ instance_type=sct_config.get("azure_instance_type_loader"),
64
+ node_amount=n_loaders,
65
+ post_behaviour=sct_config.get("post_behavior_loader_nodes"))
66
+ monitor_node_setup = CloudNodesInfo(image_id=sct_config.get("azure_image_monitor"),
67
+ instance_type=sct_config.get("azure_instance_type_monitor"),
68
+ node_amount=sct_config.get("n_monitor_nodes"),
69
+ post_behaviour=sct_config.get("post_behavior_monitor_nodes"))
70
+ cloud_setup = CloudSetupDetails(db_node=db_node_setup, loader_node=loader_node_setup,
71
+ monitor_node=monitor_node_setup, backend=sct_config.get("cluster_backend"))
72
+
73
+ return cloud_setup
74
+
75
+
76
+ def _prepare_unknown_resource_setup(sct_config: dict) -> CloudSetupDetails:
77
+ LOGGER.error("Unknown backend encountered: %s", sct_config.get("cluster_backend"))
78
+ db_node_setup = CloudNodesInfo(image_id="UNKNOWN",
79
+ instance_type="UNKNOWN",
80
+ node_amount=-1,
81
+ post_behaviour="UNKNOWN")
82
+ loader_node_setup = CloudNodesInfo(image_id="UNKNOWN",
83
+ instance_type="UNKNOWN",
84
+ node_amount=-1,
85
+ post_behaviour="UNKNOWN")
86
+ monitor_node_setup = CloudNodesInfo(image_id="UNKNOWN",
87
+ instance_type="UNKNOWN",
88
+ node_amount=-1,
89
+ post_behaviour="UNKNOWN")
90
+ cloud_setup = CloudSetupDetails(db_node=db_node_setup, loader_node=loader_node_setup,
91
+ monitor_node=monitor_node_setup, backend=sct_config.get("cluster_backend"))
92
+
93
+ return cloud_setup
94
+
95
+
96
+ def _prepare_bare_metal_resource_setup(sct_config: dict) -> CloudSetupDetails:
97
+ db_node_setup = CloudNodesInfo(image_id="bare_metal",
98
+ instance_type="bare_metal",
99
+ node_amount=sct_config.get("n_db_nodes"),
100
+ post_behaviour=sct_config.get("post_behavior_db_nodes"))
101
+ loader_node_setup = CloudNodesInfo(image_id="bare_metal",
102
+ instance_type="bare_metal",
103
+ node_amount=sct_config.get("n_loaders"),
104
+ post_behaviour=sct_config.get("post_behavior_loader_nodes"))
105
+ monitor_node_setup = CloudNodesInfo(image_id="bare_metal",
106
+ instance_type="bare_metal",
107
+ node_amount=sct_config.get("n_monitor_nodes"),
108
+ post_behaviour=sct_config.get("post_behavior_monitor_nodes"))
109
+ cloud_setup = CloudSetupDetails(db_node=db_node_setup, loader_node=loader_node_setup,
110
+ monitor_node=monitor_node_setup, backend=sct_config.get("cluster_backend"))
111
+
112
+ return cloud_setup
113
+
114
+
115
+ def _prepare_k8s_gce_minikube_resource_setup(sct_config: dict) -> CloudSetupDetails:
116
+ cloud_setup = _prepare_gce_resource_setup(sct_config)
117
+
118
+ image_id = sct_config.get("scylla_version")
119
+ cloud_setup.db_node.image_id = f"scylladb/scylladb:{image_id}"
120
+ cloud_setup.db_node.instance_type = sct_config.get("gce_instance_type_minikube")
121
+
122
+ return cloud_setup
123
+
124
+
125
+ def _prepare_k8s_gke_resource_setup(sct_config: dict) -> CloudSetupDetails:
126
+ cloud_setup = _prepare_gce_resource_setup(sct_config)
127
+ image_id = sct_config.get("scylla_version")
128
+ cloud_setup.db_node.image_id = f"scylladb/scylladb:{image_id}"
129
+ cloud_setup.monitor_node.image_id = sct_config.get("mgmt_docker_image")
130
+ cloud_setup.loader_node.image_id = f"scylladb/scylladb:{image_id}"
131
+
132
+ return cloud_setup
133
+
134
+
135
+ def _prepare_k8s_eks_resource_setup(sct_config: dict) -> CloudSetupDetails:
136
+ cloud_setup = _prepare_aws_resource_setup(sct_config)
137
+
138
+ return cloud_setup
139
+
140
+
141
+ def _prepare_docker_resource_setup(sct_config: dict) -> CloudSetupDetails:
142
+ db_node_setup = CloudNodesInfo(image_id=sct_config.get('docker_image'),
143
+ instance_type="docker",
144
+ node_amount=sct_config.get("n_db_nodes"),
145
+ post_behaviour=sct_config.get("post_behavior_db_nodes"))
146
+ loader_node_setup = CloudNodesInfo(image_id=sct_config.get('docker_image'),
147
+ instance_type="docker",
148
+ node_amount=sct_config.get("n_loaders"),
149
+ post_behaviour=sct_config.get("post_behavior_loader_nodes"))
150
+ monitor_node_setup = CloudNodesInfo(image_id=sct_config.get('docker_image'),
151
+ instance_type="docker",
152
+ node_amount=sct_config.get("n_monitor_nodes"),
153
+ post_behaviour=sct_config.get("post_behavior_monitor_nodes"))
154
+ cloud_setup = CloudSetupDetails(db_node=db_node_setup, loader_node=loader_node_setup,
155
+ monitor_node=monitor_node_setup, backend=sct_config.get("cluster_backend"))
156
+
157
+ return cloud_setup
158
+
159
+
160
+ class ResourceSetup:
161
+ BACKEND_MAP = {
162
+ "aws": _prepare_aws_resource_setup,
163
+ "aws-siren": _prepare_aws_resource_setup,
164
+ "azure": _prepare_azure_resource_setup,
165
+ "gce": _prepare_gce_resource_setup,
166
+ "gce-siren": _prepare_gce_resource_setup,
167
+ "k8s-eks": _prepare_k8s_eks_resource_setup,
168
+ "k8s-gke": _prepare_k8s_gke_resource_setup,
169
+ "k8s-gce-minikube": _prepare_k8s_gce_minikube_resource_setup,
170
+ "baremetal": _prepare_bare_metal_resource_setup,
171
+ "docker": _prepare_docker_resource_setup,
172
+ "unknown": _prepare_unknown_resource_setup,
173
+ }
174
+
175
+ @classmethod
176
+ def get_resource_setup(cls, backend: str, sct_config: dict) -> CloudSetupDetails:
177
+ return cls.BACKEND_MAP.get(backend, _prepare_unknown_resource_setup)(sct_config)