argus-alm 0.12.9__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. argus/client/base.py +1 -1
  2. argus/client/driver_matrix_tests/cli.py +2 -2
  3. argus/client/driver_matrix_tests/client.py +1 -1
  4. argus/client/generic/cli.py +2 -2
  5. argus/client/generic_result.py +3 -2
  6. argus/client/sct/client.py +3 -3
  7. argus/client/sirenada/client.py +1 -1
  8. {argus_alm-0.12.9.dist-info → argus_alm-0.13.0.dist-info}/METADATA +2 -4
  9. argus_alm-0.13.0.dist-info/RECORD +20 -0
  10. argus/backend/.gitkeep +0 -0
  11. argus/backend/cli.py +0 -41
  12. argus/backend/controller/__init__.py +0 -0
  13. argus/backend/controller/admin.py +0 -20
  14. argus/backend/controller/admin_api.py +0 -354
  15. argus/backend/controller/api.py +0 -529
  16. argus/backend/controller/auth.py +0 -67
  17. argus/backend/controller/client_api.py +0 -108
  18. argus/backend/controller/main.py +0 -274
  19. argus/backend/controller/notification_api.py +0 -72
  20. argus/backend/controller/notifications.py +0 -13
  21. argus/backend/controller/team.py +0 -126
  22. argus/backend/controller/team_ui.py +0 -18
  23. argus/backend/controller/testrun_api.py +0 -482
  24. argus/backend/controller/view_api.py +0 -162
  25. argus/backend/db.py +0 -100
  26. argus/backend/error_handlers.py +0 -21
  27. argus/backend/events/event_processors.py +0 -34
  28. argus/backend/models/__init__.py +0 -0
  29. argus/backend/models/result.py +0 -138
  30. argus/backend/models/web.py +0 -389
  31. argus/backend/plugins/__init__.py +0 -0
  32. argus/backend/plugins/core.py +0 -225
  33. argus/backend/plugins/driver_matrix_tests/controller.py +0 -63
  34. argus/backend/plugins/driver_matrix_tests/model.py +0 -421
  35. argus/backend/plugins/driver_matrix_tests/plugin.py +0 -22
  36. argus/backend/plugins/driver_matrix_tests/raw_types.py +0 -62
  37. argus/backend/plugins/driver_matrix_tests/service.py +0 -60
  38. argus/backend/plugins/driver_matrix_tests/udt.py +0 -42
  39. argus/backend/plugins/generic/model.py +0 -79
  40. argus/backend/plugins/generic/plugin.py +0 -16
  41. argus/backend/plugins/generic/types.py +0 -13
  42. argus/backend/plugins/loader.py +0 -40
  43. argus/backend/plugins/sct/controller.py +0 -185
  44. argus/backend/plugins/sct/plugin.py +0 -38
  45. argus/backend/plugins/sct/resource_setup.py +0 -178
  46. argus/backend/plugins/sct/service.py +0 -491
  47. argus/backend/plugins/sct/testrun.py +0 -272
  48. argus/backend/plugins/sct/udt.py +0 -101
  49. argus/backend/plugins/sirenada/model.py +0 -113
  50. argus/backend/plugins/sirenada/plugin.py +0 -17
  51. argus/backend/service/admin.py +0 -27
  52. argus/backend/service/argus_service.py +0 -688
  53. argus/backend/service/build_system_monitor.py +0 -188
  54. argus/backend/service/client_service.py +0 -122
  55. argus/backend/service/event_service.py +0 -18
  56. argus/backend/service/jenkins_service.py +0 -240
  57. argus/backend/service/notification_manager.py +0 -150
  58. argus/backend/service/release_manager.py +0 -230
  59. argus/backend/service/results_service.py +0 -317
  60. argus/backend/service/stats.py +0 -540
  61. argus/backend/service/team_manager_service.py +0 -83
  62. argus/backend/service/testrun.py +0 -559
  63. argus/backend/service/user.py +0 -307
  64. argus/backend/service/views.py +0 -258
  65. argus/backend/template_filters.py +0 -27
  66. argus/backend/tests/__init__.py +0 -0
  67. argus/backend/tests/argus_web.test.yaml +0 -39
  68. argus/backend/tests/conftest.py +0 -44
  69. argus/backend/tests/results_service/__init__.py +0 -0
  70. argus/backend/tests/results_service/test_best_results.py +0 -70
  71. argus/backend/util/common.py +0 -65
  72. argus/backend/util/config.py +0 -38
  73. argus/backend/util/encoders.py +0 -41
  74. argus/backend/util/logsetup.py +0 -81
  75. argus/backend/util/module_loaders.py +0 -30
  76. argus/backend/util/send_email.py +0 -91
  77. argus/client/generic_result_old.py +0 -143
  78. argus/db/.gitkeep +0 -0
  79. argus/db/argus_json.py +0 -14
  80. argus/db/cloud_types.py +0 -125
  81. argus/db/config.py +0 -135
  82. argus/db/db_types.py +0 -139
  83. argus/db/interface.py +0 -370
  84. argus/db/testrun.py +0 -740
  85. argus/db/utils.py +0 -15
  86. argus_alm-0.12.9.dist-info/RECORD +0 -96
  87. /argus/{backend → common}/__init__.py +0 -0
  88. /argus/{backend/util → common}/enums.py +0 -0
  89. /argus/{backend/plugins/sct/types.py → common/sct_types.py} +0 -0
  90. /argus/{backend/plugins/sirenada/types.py → common/sirenada_types.py} +0 -0
  91. {argus_alm-0.12.9.dist-info → argus_alm-0.13.0.dist-info}/LICENSE +0 -0
  92. {argus_alm-0.12.9.dist-info → argus_alm-0.13.0.dist-info}/WHEEL +0 -0
  93. {argus_alm-0.12.9.dist-info → argus_alm-0.13.0.dist-info}/entry_points.txt +0 -0
argus/backend/db.py DELETED
@@ -1,100 +0,0 @@
1
- from functools import cached_property
2
- import logging
3
- from typing import Optional
4
- from flask import g, Flask
5
- # pylint: disable=no-name-in-module
6
- from cassandra.policies import WhiteListRoundRobinPolicy
7
- from cassandra import ConsistencyLevel
8
- from cassandra.cluster import ExecutionProfile, EXEC_PROFILE_DEFAULT, Cluster
9
- from cassandra.cluster import PreparedStatement
10
- from cassandra.cqlengine.management import sync_table, sync_type
11
- from cassandra.cqlengine import connection
12
- from cassandra.query import dict_factory
13
- from cassandra.auth import PlainTextAuthProvider
14
- from argus.backend.util.config import Config
15
-
16
- from argus.backend.models.web import USED_MODELS, USED_TYPES
17
-
18
- LOGGER = logging.getLogger(__name__)
19
-
20
-
21
- class ScyllaCluster:
22
- # pylint: disable=too-many-instance-attributes
23
- APP_INSTANCE: Optional['ScyllaCluster'] = None
24
-
25
- def __init__(self, config=None):
26
- if not config:
27
- config = Config.load_yaml_config()
28
- self.config = config
29
- self.auth_provider = PlainTextAuthProvider(
30
- username=config["SCYLLA_USERNAME"], password=config["SCYLLA_PASSWORD"])
31
- self.lb_policy = WhiteListRoundRobinPolicy(hosts=config["SCYLLA_CONTACT_POINTS"])
32
- self.execution_profile = ExecutionProfile(
33
- load_balancing_policy=self.lb_policy, consistency_level=ConsistencyLevel.QUORUM)
34
- connection.setup(hosts=config["SCYLLA_CONTACT_POINTS"], default_keyspace=config["SCYLLA_KEYSPACE_NAME"],
35
- auth_provider=self.auth_provider,
36
- protocol_version=4,
37
- execution_profiles={EXEC_PROFILE_DEFAULT: self.execution_profile})
38
- self.cluster: Cluster = connection.get_cluster(connection='default')
39
- self.prepared_statements = {}
40
- self.read_exec_profile = ExecutionProfile(
41
- consistency_level=ConsistencyLevel.ONE,
42
- row_factory=dict_factory,
43
- load_balancing_policy=self.lb_policy
44
- )
45
- self.read_named_tuple_exec_profile = ExecutionProfile(
46
- consistency_level=ConsistencyLevel.ONE,
47
- load_balancing_policy=self.lb_policy
48
- )
49
- self.cluster.add_execution_profile("read_fast", self.read_exec_profile)
50
- self.cluster.add_execution_profile("read_fast_named_tuple", self.read_named_tuple_exec_profile)
51
-
52
- @cached_property
53
- def session(self):
54
- return self.cluster.connect(keyspace=self.config["SCYLLA_KEYSPACE_NAME"])
55
-
56
- @classmethod
57
- def get(cls, config: dict = None) -> 'ScyllaCluster':
58
- if cls.APP_INSTANCE:
59
- return cls.APP_INSTANCE
60
-
61
- cls.APP_INSTANCE = cls(config)
62
- return cls.APP_INSTANCE
63
-
64
- @classmethod
65
- def shutdown(cls):
66
- if cls.APP_INSTANCE:
67
- cls.APP_INSTANCE.cluster.shutdown()
68
- cls.APP_INSTANCE = None
69
-
70
- def prepare(self, query: str) -> PreparedStatement:
71
- if not (statement := self.prepared_statements.get(query)):
72
- LOGGER.info("Unprepared statement %s, preparing...", query)
73
- statement = self.session.prepare(query=query)
74
- self.prepared_statements[query] = statement
75
- return statement
76
-
77
- def sync_core_tables(self):
78
- for udt in USED_TYPES:
79
- LOGGER.info("Syncing type: %s..", udt.__name__)
80
- sync_type(ks_name=self.config["SCYLLA_KEYSPACE_NAME"], type_model=udt)
81
- LOGGER.info("Core Types synchronized.")
82
- for model in USED_MODELS:
83
- LOGGER.info("Syncing model: %s..", model.__name__)
84
- sync_table(model, keyspaces=[self.config["SCYLLA_KEYSPACE_NAME"]])
85
- LOGGER.info("Core Models synchronized.")
86
-
87
- @classmethod
88
- def get_session(cls):
89
- cluster = cls.get()
90
- if 'scylla_session' not in g:
91
- g.scylla_session = cluster.session # pylint: disable=assigning-non-slot
92
- return g.scylla_session
93
-
94
- @classmethod
95
- def close_session(cls, error=None): # pylint: disable=unused-argument
96
- g.pop("scylla_session", None)
97
-
98
- @classmethod
99
- def attach_to_app(cls, app: Flask):
100
- app.teardown_appcontext(cls.close_session)
@@ -1,21 +0,0 @@
1
- import logging
2
- from traceback import format_exception
3
- from flask import request
4
-
5
- LOGGER = logging.getLogger(__name__)
6
-
7
-
8
- class APIException(Exception):
9
- pass
10
-
11
-
12
- def handle_api_exception(exception: Exception):
13
- LOGGER.error("Exception in %s\n%s", request.endpoint, "".join(format_exception(exception)))
14
-
15
- return {
16
- "status": "error",
17
- "response": {
18
- "exception": exception.__class__.__name__,
19
- "arguments": exception.args
20
- }
21
- }
@@ -1,34 +0,0 @@
1
- from argus.backend.models.web import ArgusEventTypes
2
-
3
-
4
- def event_process_posted_comment(event: dict) -> dict:
5
- return event["message"].format(**event)
6
-
7
-
8
- def event_process_status_changed(event: dict) -> dict:
9
- return event["message"].format(**event)
10
-
11
-
12
- def event_process_investigation_status_changed(event: dict) -> dict:
13
- return event["message"].format(**event)
14
-
15
-
16
- def event_process_assignee_changed(event: dict) -> dict:
17
- return event["message"].format(**event)
18
-
19
-
20
- def event_process_issue_added(event: dict) -> dict:
21
- return event["message"].format(**event)
22
-
23
-
24
- EVENT_PROCESSORS = {
25
- ArgusEventTypes.AssigneeChanged: event_process_assignee_changed,
26
- ArgusEventTypes.TestRunStatusChanged: event_process_status_changed,
27
- ArgusEventTypes.TestRunCommentPosted: event_process_posted_comment,
28
- ArgusEventTypes.TestRunCommentUpdated: event_process_posted_comment,
29
- ArgusEventTypes.TestRunCommentDeleted: event_process_posted_comment,
30
- ArgusEventTypes.TestRunIssueAdded: event_process_issue_added,
31
- ArgusEventTypes.TestRunIssueRemoved: event_process_issue_added,
32
- ArgusEventTypes.TestRunInvestigationStatusChanged: event_process_investigation_status_changed,
33
- ArgusEventTypes.TestRunBatchInvestigationStatusChange: event_process_investigation_status_changed,
34
- }
File without changes
@@ -1,138 +0,0 @@
1
- import math
2
- from datetime import datetime, timezone
3
-
4
- from cassandra.cqlengine import columns
5
- from cassandra.cqlengine.models import Model
6
- from cassandra.cqlengine.usertype import UserType
7
-
8
- class ValidationRules(UserType):
9
- valid_from = columns.DateTime()
10
- best_pct = columns.Double() # max value limit relative to best result in percent unit
11
- best_abs = columns.Double() # max value limit relative to best result in absolute unit
12
- fixed_limit = columns.Double() # fixed limit
13
-
14
- class ColumnMetadata(UserType):
15
- name = columns.Ascii()
16
- unit = columns.Text()
17
- type = columns.Ascii()
18
- higher_is_better = columns.Boolean() # used for tracking best results, if None - no tracking
19
-
20
-
21
- class ArgusGenericResultMetadata(Model):
22
- __table_name__ = "generic_result_metadata_v1"
23
- test_id = columns.UUID(partition_key=True)
24
- name = columns.Text(required=True, primary_key=True)
25
- description = columns.Text()
26
- columns_meta = columns.List(value_type=columns.UserDefinedType(ColumnMetadata))
27
- validation_rules = columns.Map(key_type=columns.Ascii(), value_type=columns.List(columns.UserDefinedType(ValidationRules)))
28
- rows_meta = columns.List(value_type=columns.Ascii())
29
-
30
- def __init__(self, **kwargs):
31
- kwargs["columns_meta"] = [ColumnMetadata(**col) for col in kwargs.pop('columns_meta', [])]
32
- validation_rules = kwargs.pop('validation_rules', {})
33
-
34
- if validation_rules:
35
- for column, rule in validation_rules.items():
36
- if not isinstance(rule, list):
37
- rule['valid_from'] = datetime.now(timezone.utc)
38
- validation_rules[column] = [rule]
39
- kwargs["validation_rules"] = {k: [ValidationRules(**rules) for rules in v] for k, v in validation_rules.items()}
40
- super().__init__(**kwargs)
41
-
42
- def update_validation_rules(self, key: str, new_rule_dict: dict) -> bool:
43
- """
44
- Checks if the most recent ValidationRule for the given key matches the new_rule_dict.
45
- If not, adds the new rule to the list with the current timestamp.
46
-
47
- :param key: The key (column name) in the validation_rules map to update.
48
- :param new_rule_dict: A dictionary containing the new validation rule values.
49
- :return: True if a new rule was added, False if the existing rule matches.
50
- """
51
- rules_list = self.validation_rules.get(key, [])
52
- most_recent_rule = None
53
-
54
- if rules_list:
55
- most_recent_rule = rules_list[-1]
56
-
57
- fields_to_compare = [field for field in ValidationRules._fields if field != 'valid_from']
58
- rules_match = True
59
- if most_recent_rule:
60
- for field in fields_to_compare:
61
- db_value = getattr(most_recent_rule, field)
62
- new_value = new_rule_dict.get(field)
63
- if db_value is None and new_value is None:
64
- continue
65
- if db_value is None or new_value is None:
66
- rules_match = False
67
- break
68
- if not math.isclose(db_value, new_value, rel_tol=1e-9, abs_tol=0.0):
69
- rules_match = False
70
- break
71
- else:
72
- rules_match = False
73
-
74
- if not rules_match:
75
- new_rule = ValidationRules(
76
- valid_from=datetime.now(timezone.utc),
77
- best_pct=new_rule_dict.get('best_pct'),
78
- best_abs=new_rule_dict.get('best_abs'),
79
- fixed_limit=new_rule_dict.get('fixed_limit')
80
- )
81
- rules_list.append(new_rule)
82
- self.validation_rules = self.validation_rules or {}
83
- self.validation_rules.update({key: rules_list})
84
- return True
85
-
86
- return False # Existing rule matches
87
-
88
- def update_if_changed(self, new_data: dict) -> "ArgusGenericResultMetadata":
89
- """
90
- Updates table metadata if changed column/description or new rows were added.
91
- See that rows can only be added, not removed once was sent.
92
- Columns may be removed, but data in results table persists.
93
- """
94
- updated = False
95
- for field, value in new_data.items():
96
- if field == "columns_meta":
97
- value = [ColumnMetadata(**col) for col in value]
98
- if self.columns_meta != value:
99
- self.columns_meta = value
100
- updated = True
101
- elif field == "rows_meta":
102
- added_rows = []
103
- for row in value:
104
- if row not in self.rows_meta:
105
- added_rows.append(row)
106
- updated = True
107
- self.rows_meta += added_rows
108
- elif field == "validation_rules":
109
- if any([self.update_validation_rules(key, rules) for key, rules in value.items()]):
110
- updated = True
111
- elif getattr(self, field) != value:
112
- setattr(self, field, value)
113
- updated = True
114
-
115
- if updated:
116
- self.save()
117
- return self
118
-
119
- class ArgusGenericResultData(Model):
120
- __table_name__ = "generic_result_data_v1"
121
- test_id = columns.UUID(partition_key=True)
122
- name = columns.Text(partition_key=True)
123
- run_id = columns.UUID(primary_key=True)
124
- column = columns.Ascii(primary_key=True, index=True)
125
- row = columns.Ascii(primary_key=True, index=True)
126
- sut_timestamp = columns.DateTime() # for sorting
127
- value = columns.Double()
128
- value_text = columns.Text()
129
- status = columns.Ascii()
130
-
131
- class ArgusBestResultData(Model):
132
- __table_name__ = "generic_result_best_v1"
133
- test_id = columns.UUID(partition_key=True)
134
- name = columns.Text(partition_key=True)
135
- key = columns.Ascii(primary_key=True) # represents pair column:row
136
- result_date = columns.DateTime(primary_key=True, clustering_order="DESC")
137
- value = columns.Double()
138
- run_id = columns.UUID()
@@ -1,389 +0,0 @@
1
- from uuid import UUID, uuid1, uuid4
2
- from datetime import datetime
3
- from enum import Enum, IntEnum, auto
4
- from cassandra.cqlengine.models import Model
5
- from cassandra.cqlengine.usertype import UserType
6
- from cassandra.cqlengine import columns
7
- from cassandra.util import uuid_from_time, unix_time_from_uuid1 # pylint: disable=no-name-in-module
8
-
9
- from argus.backend.models.result import ArgusGenericResultMetadata, ArgusGenericResultData, ArgusBestResultData
10
-
11
-
12
- def uuid_now():
13
- return uuid_from_time(datetime.utcnow())
14
-
15
- # pylint: disable=invalid-name
16
-
17
-
18
- class ArgusTestException(Exception):
19
- pass
20
-
21
-
22
- class UserRoles(str, Enum):
23
- User = "ROLE_USER"
24
- Manager = "ROLE_MANAGER"
25
- Admin = "ROLE_ADMIN"
26
-
27
-
28
- class User(Model):
29
- id = columns.UUID(primary_key=True, default=uuid4)
30
- username = columns.Text(index=True)
31
- full_name = columns.Text()
32
- password = columns.Text()
33
- email = columns.Text(index=True)
34
- registration_date = columns.DateTime()
35
- roles = columns.List(value_type=columns.Text)
36
- picture_id = columns.UUID(default=None)
37
- api_token = columns.Text(index=True)
38
-
39
- def __hash__(self) -> int:
40
- return hash(self.id)
41
-
42
- def is_manager(self) -> bool:
43
- # pylint: disable=unsupported-membership-test
44
- return UserRoles.Manager in self.roles
45
-
46
- def is_admin(self) -> bool:
47
- # pylint: disable=unsupported-membership-test
48
- return UserRoles.Admin in self.roles
49
-
50
- def set_as_admin(self) -> None:
51
- # pylint: disable=unsupported-membership-test
52
- if UserRoles.Admin not in self.roles:
53
- self.roles.append(UserRoles.Admin.value)
54
-
55
- def set_as_manager(self) -> None:
56
- # pylint: disable=unsupported-membership-test
57
- if UserRoles.Manager not in self.roles:
58
- self.roles.append(UserRoles.Manager.value)
59
-
60
- def get_id(self):
61
- return str(self.id)
62
-
63
- @classmethod
64
- def exists(cls, user_id: UUID):
65
- try:
66
- user = cls.get(id=user_id)
67
- if user:
68
- return user
69
- except cls.DoesNotExist:
70
- pass
71
- return None
72
-
73
- @classmethod
74
- def exists_by_name(cls, name: str):
75
- try:
76
- user = cls.get(username=name)
77
- if user:
78
- return user
79
- except cls.DoesNotExist:
80
- pass
81
- return None
82
-
83
- def __str__(self):
84
- return f"User('{self.id}','{self.username}')"
85
-
86
- def to_json(self):
87
- return {
88
- "id": str(self.id),
89
- "username": self.username,
90
- "full_name": self.full_name,
91
- "picture_id": self.picture_id
92
- }
93
-
94
-
95
- class Team(Model):
96
- id = columns.UUID(primary_key=True, default=uuid4)
97
- name = columns.Text(required=True)
98
- leader = columns.UUID(index=True, required=True)
99
- members = columns.List(value_type=columns.UUID)
100
- motd = columns.Text()
101
-
102
- class UserOauthToken(Model):
103
- id = columns.UUID(primary_key=True, default=uuid4)
104
- user_id = columns.UUID(index=True, required=True)
105
- kind = columns.Text(required=True, index=True)
106
- token = columns.Text(required=True)
107
-
108
-
109
- class ArgusRelease(Model):
110
- __table_name__ = "argus_release_v2"
111
- id = columns.UUID(primary_key=True, default=uuid4)
112
- name = columns.Text(index=True, required=True)
113
- pretty_name = columns.Text()
114
- description = columns.Text()
115
- github_repo_url = columns.Text()
116
- valid_version_regex = columns.Text()
117
- assignee = columns.List(value_type=columns.UUID)
118
- picture_id = columns.UUID()
119
- enabled = columns.Boolean(default=lambda: True)
120
- perpetual = columns.Boolean(default=lambda: False)
121
- dormant = columns.Boolean(default=lambda: False)
122
-
123
- def __eq__(self, other):
124
- if isinstance(other, ArgusRelease):
125
- return self.name == other.name
126
- else:
127
- return super().__eq__(other)
128
-
129
-
130
- class ArgusGroup(Model):
131
- __table_name__ = "argus_group_v2"
132
- id = columns.UUID(primary_key=True, default=uuid4)
133
- release_id = columns.UUID(required=True, index=True)
134
- name = columns.Text(required=True, index=True)
135
- pretty_name = columns.Text()
136
- description = columns.Text()
137
- assignee = columns.List(value_type=columns.UUID)
138
- build_system_id = columns.Text()
139
- enabled = columns.Boolean(default=lambda: True)
140
-
141
- def __hash__(self) -> int:
142
- return hash((self.id, self.release_id))
143
-
144
- def __eq__(self, other):
145
- if isinstance(other, ArgusGroup):
146
- return self.name == other.name and self.release_id == other.release_id
147
- else:
148
- return super().__eq__(other)
149
-
150
-
151
- class ArgusUserView(Model):
152
- id = columns.UUID(primary_key=True, partition_key=True, default=uuid4)
153
- name = columns.Text(required=True, index=True)
154
- display_name = columns.Text()
155
- description = columns.Text()
156
- user_id = columns.UUID(required=True, index=True)
157
- tests = columns.List(value_type=columns.UUID, default=lambda: [])
158
- release_ids = columns.List(value_type=columns.UUID, default=lambda: [])
159
- group_ids = columns.List(value_type=columns.UUID, default=lambda: [])
160
- created = columns.DateTime(default=datetime.utcnow)
161
- last_updated = columns.DateTime(default=datetime.utcnow)
162
- widget_settings = columns.Text(required=True)
163
-
164
-
165
- class ArgusTest(Model):
166
- __table_name__ = "argus_test_v2"
167
- id = columns.UUID(primary_key=True, default=uuid4)
168
- group_id = columns.UUID(required=True, index=True)
169
- release_id = columns.UUID(required=True, index=True)
170
- name = columns.Text(required=True, index=True)
171
- pretty_name = columns.Text()
172
- description = columns.Text()
173
- assignee = columns.List(value_type=columns.UUID)
174
- build_system_id = columns.Text(index=True)
175
- enabled = columns.Boolean(default=lambda: True)
176
- build_system_url = columns.Text()
177
- plugin_name = columns.Text()
178
-
179
- def __eq__(self, other):
180
- if isinstance(other, ArgusTest):
181
- return self.name == other.name and self.group_id == other.group_id and self.release_id == other.release_id
182
- else:
183
- return super().__eq__(other)
184
-
185
- def validate_build_system_id(self):
186
- try:
187
- t = ArgusTest.get(build_system_id=self.build_system_id)
188
- if t.id != self.id:
189
- raise ArgusTestException("Build Id is already used by another test", t.id, self.id)
190
- except ArgusTest.DoesNotExist:
191
- pass
192
-
193
-
194
- class ArgusTestRunComment(Model):
195
- id = columns.UUID(primary_key=True, default=uuid4, partition_key=True)
196
- test_run_id = columns.UUID(required=True, index=True)
197
- user_id = columns.UUID(required=True, index=True)
198
- release_id = columns.UUID(required=True, index=True)
199
- test_id = columns.UUID(required=True, index=True)
200
- posted_at = columns.Integer(
201
- required=True, clustering_order="desc", primary_key=True)
202
- message = columns.Text(min_length=1, max_length=65535)
203
- mentions = columns.List(value_type=columns.UUID, default=[])
204
- reactions = columns.Map(key_type=columns.Text, value_type=columns.Integer)
205
-
206
-
207
- class ArgusEventTypes(str, Enum):
208
- AssigneeChanged = "ARGUS_ASSIGNEE_CHANGE"
209
- TestRunStatusChanged = "ARGUS_TEST_RUN_STATUS_CHANGE"
210
- TestRunInvestigationStatusChanged = "ARGUS_TEST_RUN_INVESTIGATION_STATUS_CHANGE"
211
- TestRunBatchInvestigationStatusChange = "ARGUS_TEST_RUN_INVESTIGATION_BATCH_STATUS_CHANGE"
212
- TestRunCommentPosted = "ARGUS_TEST_RUN_COMMENT_POSTED"
213
- TestRunCommentUpdated = "ARGUS_TEST_RUN_COMMENT_UPDATED"
214
- TestRunCommentDeleted = "ARGUS_TEST_RUN_COMMENT_DELETED"
215
- TestRunIssueAdded = "ARGUS_TEST_RUN_ISSUE_ADDED"
216
- TestRunIssueRemoved = "ARGUS_TEST_RUN_ISSUE_REMOVED"
217
-
218
-
219
- class ArgusEvent(Model):
220
- id = columns.UUID(primary_key=True, default=uuid4, partition_key=True)
221
- release_id = columns.UUID(index=True)
222
- group_id = columns.UUID(index=True)
223
- test_id = columns.UUID(index=True)
224
- run_id = columns.UUID(index=True)
225
- user_id = columns.UUID(index=True)
226
- kind = columns.Text(required=True, index=True)
227
- body = columns.Text(required=True)
228
- created_at = columns.DateTime(required=True)
229
-
230
-
231
- class ArgusNotificationTypes(str, Enum):
232
- Mention = "TYPE_MENTION"
233
- StatusChange = "TYPE_STATUS_CHANGE"
234
- AssigneeChange = "TYPE_ASSIGNEE_CHANGE"
235
- ScheduleChange = "TYPE_SCHEDULE_CHANGE"
236
-
237
-
238
- class ArgusNotificationSourceTypes(str, Enum):
239
- TestRun = "TEST_RUN"
240
- Schedule = "SCHEDULE"
241
- Comment = "COMMENT"
242
-
243
-
244
- class ArgusNotificationState(IntEnum):
245
- UNREAD = auto()
246
- READ = auto()
247
-
248
-
249
- class ArgusNotification(Model):
250
- receiver = columns.UUID(primary_key=True, partition_key=True)
251
- id = columns.TimeUUID(primary_key=True, clustering_order="DESC", default=uuid_now)
252
- type = columns.Text(required=True)
253
- state = columns.SmallInt(required=True, default=lambda: ArgusNotificationState.UNREAD)
254
- sender = columns.UUID(required=True)
255
- source_type = columns.Text(required=True)
256
- source_id = columns.UUID(required=True)
257
- title = columns.Text(required=True, max_length=1024)
258
- content = columns.Text(required=True, max_length=65535)
259
-
260
- def to_dict_short_summary(self) -> dict:
261
- return {
262
- "receiver": self.receiver,
263
- "sender": self.sender,
264
- "id": self.id,
265
- "created": unix_time_from_uuid1(self.id) * 1000,
266
- "title": self.title,
267
- "state": self.state,
268
- }
269
-
270
- def to_dict(self) -> dict:
271
- return {
272
- "receiver": self.receiver,
273
- "sender": self.sender,
274
- "id": self.id,
275
- "created": unix_time_from_uuid1(self.id) * 1000,
276
- "title": self.title,
277
- "type": self.type,
278
- "content": self.content,
279
- "source": self.source_type,
280
- "source_id": self.source_id,
281
- "state": self.state,
282
- }
283
-
284
-
285
- class ArgusGithubIssue(Model):
286
- # pylint: disable=too-many-instance-attributes
287
- id = columns.UUID(primary_key=True, default=uuid4, partition_key=True)
288
- added_on = columns.DateTime(default=datetime.utcnow)
289
- release_id = columns.UUID(index=True)
290
- group_id = columns.UUID(index=True)
291
- test_id = columns.UUID(index=True)
292
- run_id = columns.UUID(index=True)
293
- user_id = columns.UUID(index=True)
294
- type = columns.Text()
295
- owner = columns.Text()
296
- repo = columns.Text()
297
- issue_number = columns.Integer()
298
- last_status = columns.Text()
299
- title = columns.Text()
300
- url = columns.Text()
301
-
302
- def __hash__(self) -> int:
303
- return hash((self.owner, self.repo, self.issue_number))
304
-
305
- def __eq__(self, other):
306
- if isinstance(other, ArgusGithubIssue):
307
- return self.owner == other.owner and self.repo == other.repo and self.issue_number == other.issue_number
308
- return super().__eq__(other)
309
-
310
- def __ne__(self, other):
311
- return not self == other
312
-
313
-
314
- class ArgusSchedule(Model):
315
- __table_name__ = "argus_schedule_v4"
316
- release_id = columns.UUID(primary_key=True, required=True)
317
- id = columns.TimeUUID(primary_key=True, default=uuid1, clustering_order="DESC")
318
- period_start = columns.DateTime(required=True, default=datetime.utcnow)
319
- period_end = columns.DateTime(required=True, primary_key=True, clustering_order="DESC")
320
- tag = columns.Text(default="")
321
-
322
-
323
- class ArgusScheduleAssignee(Model):
324
- __table_name__ = "argus_schedule_user_v3"
325
- assignee = columns.UUID(primary_key=True)
326
- id = columns.TimeUUID(primary_key=True, default=uuid1,
327
- clustering_order="DESC")
328
- schedule_id = columns.TimeUUID(required=True, index=True)
329
- release_id = columns.UUID(required=True)
330
-
331
-
332
- class ArgusScheduleTest(Model):
333
- __table_name__ = "argus_schedule_test_v5"
334
- test_id = columns.UUID(primary_key=True, required=True)
335
- id = columns.TimeUUID(primary_key=True, default=uuid1,
336
- clustering_order="DESC")
337
- schedule_id = columns.TimeUUID(required=True, index=True)
338
- release_id = columns.UUID(partition_key=True)
339
-
340
-
341
- class ArgusScheduleGroup(Model):
342
- __table_name__ = "argus_schedule_group_v3"
343
- group_id = columns.UUID(partition_key=True, required=True)
344
- id = columns.TimeUUID(primary_key=True, default=uuid1,
345
- clustering_order="DESC")
346
- schedule_id = columns.TimeUUID(required=True, index=True)
347
- release_id = columns.UUID(partition_key=True)
348
-
349
-
350
- class ReleasePlannerComment(Model):
351
- __table_name__ = "argus_planner_comment_v2"
352
- release = columns.UUID(primary_key=True)
353
- group = columns.UUID(primary_key=True)
354
- test = columns.UUID(primary_key=True)
355
- comment = columns.Text(default=lambda: "")
356
-
357
-
358
- class WebFileStorage(Model):
359
- id = columns.UUID(primary_key=True, default=uuid4)
360
- filepath = columns.Text(min_length=1)
361
- filename = columns.Text(min_length=1)
362
-
363
-
364
- USED_MODELS: list[Model] = [
365
- User,
366
- UserOauthToken,
367
- Team,
368
- WebFileStorage,
369
- ArgusRelease,
370
- ArgusUserView,
371
- ArgusGroup,
372
- ArgusTest,
373
- ArgusTestRunComment,
374
- ArgusEvent,
375
- ArgusGithubIssue,
376
- ReleasePlannerComment,
377
- ArgusNotification,
378
- ArgusSchedule,
379
- ArgusScheduleAssignee,
380
- ArgusScheduleGroup,
381
- ArgusScheduleTest,
382
- ArgusGenericResultMetadata,
383
- ArgusGenericResultData,
384
- ArgusBestResultData,
385
- ]
386
-
387
- USED_TYPES: list[UserType] = [
388
-
389
- ]
File without changes