argus-alm 0.12.2__tar.gz → 0.12.4b1__tar.gz

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 (92) hide show
  1. argus_alm-0.12.4b1/PKG-INFO +129 -0
  2. argus_alm-0.12.4b1/README.md +109 -0
  3. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/cli.py +1 -1
  4. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/admin_api.py +26 -0
  5. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/api.py +26 -1
  6. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/main.py +21 -0
  7. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/testrun_api.py +132 -1
  8. argus_alm-0.12.4b1/argus/backend/controller/view_api.py +162 -0
  9. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/models/web.py +16 -0
  10. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/core.py +28 -5
  11. argus_alm-0.12.4b1/argus/backend/plugins/driver_matrix_tests/controller.py +63 -0
  12. argus_alm-0.12.4b1/argus/backend/plugins/driver_matrix_tests/model.py +421 -0
  13. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/driver_matrix_tests/raw_types.py +27 -0
  14. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/driver_matrix_tests/service.py +18 -0
  15. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/driver_matrix_tests/udt.py +14 -13
  16. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/generic/model.py +6 -3
  17. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/loader.py +2 -2
  18. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/controller.py +31 -0
  19. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/plugin.py +2 -1
  20. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/service.py +101 -3
  21. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/testrun.py +8 -2
  22. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/types.py +18 -0
  23. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/udt.py +6 -0
  24. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sirenada/model.py +1 -1
  25. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/argus_service.py +116 -11
  26. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/build_system_monitor.py +37 -7
  27. argus_alm-0.12.4b1/argus/backend/service/jenkins_service.py +238 -0
  28. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/release_manager.py +14 -0
  29. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/stats.py +179 -21
  30. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/testrun.py +44 -5
  31. argus_alm-0.12.4b1/argus/backend/service/views.py +258 -0
  32. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/template_filters.py +7 -0
  33. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/common.py +14 -2
  34. argus_alm-0.12.4b1/argus/client/driver_matrix_tests/cli.py +110 -0
  35. argus_alm-0.12.4b1/argus/client/driver_matrix_tests/client.py +79 -0
  36. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/sct/client.py +34 -0
  37. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/pyproject.toml +3 -2
  38. argus_alm-0.12.2/PKG-INFO +0 -206
  39. argus_alm-0.12.2/README.md +0 -187
  40. argus_alm-0.12.2/argus/backend/plugins/driver_matrix_tests/controller.py +0 -24
  41. argus_alm-0.12.2/argus/backend/plugins/driver_matrix_tests/model.py +0 -173
  42. argus_alm-0.12.2/argus/backend/service/jenkins_service.py +0 -63
  43. argus_alm-0.12.2/argus/client/driver_matrix_tests/client.py +0 -216
  44. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/LICENSE +0 -0
  45. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/__init__.py +0 -0
  46. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/.gitkeep +0 -0
  47. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/__init__.py +0 -0
  48. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/__init__.py +0 -0
  49. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/admin.py +0 -0
  50. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/auth.py +0 -0
  51. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/client_api.py +0 -0
  52. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/notification_api.py +0 -0
  53. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/notifications.py +0 -0
  54. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/team.py +0 -0
  55. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/controller/team_ui.py +0 -0
  56. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/db.py +0 -0
  57. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/error_handlers.py +0 -0
  58. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/events/event_processors.py +0 -0
  59. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/models/__init__.py +0 -0
  60. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/__init__.py +0 -0
  61. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/driver_matrix_tests/plugin.py +0 -0
  62. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/generic/plugin.py +0 -0
  63. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/generic/types.py +0 -0
  64. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sct/resource_setup.py +0 -0
  65. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sirenada/plugin.py +0 -0
  66. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/plugins/sirenada/types.py +0 -0
  67. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/admin.py +0 -0
  68. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/client_service.py +0 -0
  69. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/event_service.py +0 -0
  70. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/notification_manager.py +0 -0
  71. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/team_manager_service.py +0 -0
  72. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/service/user.py +0 -0
  73. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/config.py +0 -0
  74. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/encoders.py +0 -0
  75. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/enums.py +0 -0
  76. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/logsetup.py +0 -0
  77. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/module_loaders.py +0 -0
  78. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/backend/util/send_email.py +0 -0
  79. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/__init__.py +0 -0
  80. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/base.py +0 -0
  81. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/generic/cli.py +0 -0
  82. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/generic/client.py +0 -0
  83. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/sct/types.py +0 -0
  84. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/client/sirenada/client.py +0 -0
  85. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/.gitkeep +0 -0
  86. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/argus_json.py +0 -0
  87. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/cloud_types.py +0 -0
  88. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/config.py +0 -0
  89. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/db_types.py +0 -0
  90. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/interface.py +0 -0
  91. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/testrun.py +0 -0
  92. {argus_alm-0.12.2 → argus_alm-0.12.4b1}/argus/db/utils.py +0 -0
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.1
2
+ Name: argus-alm
3
+ Version: 0.12.4b1
4
+ Summary: Argus
5
+ Home-page: https://github.com/scylladb/argus
6
+ License: Apache-2.0
7
+ Author: Alexey Kartashov
8
+ Author-email: alexey.kartashov@scylladb.com
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Dist: click (>=8.1.3,<9.0.0)
16
+ Requires-Dist: requests (>=2.26.0,<3.0.0)
17
+ Project-URL: Repository, https://github.com/scylladb/argus
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Argus
21
+
22
+ ## Description
23
+
24
+ Argus is a test tracking system intended to provide observability into automated test pipelines which use long-running resources. It allows observation of a test status, its events and its allocated resources. It also allows easy comparison between particular runs of a specific test.
25
+
26
+ ## Installation notes
27
+
28
+ ### Development
29
+
30
+ For development setup instructions, see [dev-setup.md](./docs/dev-setup.md).
31
+
32
+ ### Prerequisites
33
+
34
+ - Python >=3.10.0 (system-wide or pyenv)
35
+
36
+ - NodeJS >=16 (with npm)
37
+
38
+ - Yarn (can be installed globally with `npm -g install yarn`)
39
+
40
+ - nginx
41
+
42
+ - poetry >=1.2.0b1
43
+
44
+ ### From source
45
+
46
+ #### Production
47
+
48
+ Perform the following steps:
49
+
50
+ Create a user that will be used by uwsgi:
51
+
52
+ ```bash
53
+ useradd -m -s /bin/bash argus
54
+ sudo -iu argus
55
+ ```
56
+
57
+ (Optional) Install pyenv and create a virtualenv for this user:
58
+
59
+ ```bash
60
+ pyenv install 3.10.0
61
+ pyenv virtualenv argus
62
+ pyenv activate argus
63
+ ```
64
+
65
+ Clone the project into a directory somewhere where user has full write permissions
66
+
67
+ ```bash
68
+ git clone https://github.com/scylladb/argus ~/app
69
+ cd ~/app
70
+ ```
71
+
72
+ Install project dependencies:
73
+
74
+ ```bash
75
+ poetry install --with default,dev,web-backend,docker-image
76
+ yarn install
77
+ ```
78
+
79
+ Compile frontend files from `/frontend` into `/public/dist`
80
+
81
+ ```bash
82
+ yarn webpack
83
+ ```
84
+
85
+ Create a `argus.local.yaml` configuration file (used to configure database connection) and a `argus_web.yaml` (used for webapp secrets) in your application install directory.
86
+
87
+ ```bash
88
+ cp argus_web.example.yaml argus_web.yaml
89
+ cp argus.yaml argus.local.yaml
90
+ ```
91
+
92
+ Open `argus.local.yaml` and add the database connection information (contact_points, user, password and keyspace name).
93
+
94
+ Open `argus_web.yaml` and change the `SECRET_KEY` value to something secure, like a sha512 digest of random bytes. Fill out GITHUB_* variables with their respective values.
95
+
96
+ Copy nginx configuration file from `docs/configs/argus.nginx.conf` to nginx virtual hosts directory:
97
+
98
+ Ubuntu:
99
+
100
+ ```bash
101
+ sudo cp docs/configs/argus.nginx.conf /etc/nginx/sites-available/argus
102
+ sudo ln -s /etc/nginx/sites-enabled/argus /etc/nginx/sites-available/argus
103
+ ```
104
+
105
+ RHEL/Centos/Alma/Fedora:
106
+
107
+ ```bash
108
+ sudo cp docs/configs/argus.nginx.conf /etc/nginx/conf.d/argus.conf
109
+ ```
110
+
111
+ Adjust the webhost settings in that file as necessary, particularly `listen` and `server_name` directives.
112
+
113
+ Copy systemd service file from `docs/config/argus.service` to `/etc/systemd/system` directory:
114
+
115
+ ```bash
116
+ sudo cp docs/config/argus.service /etc/systemd/system
117
+ ```
118
+
119
+ Open it and adjust the path to the `start_argus.sh` script in the `ExecStart=` directive and the user/group, then reload systemd daemon configuration and enable (and optionally start) the service.
120
+
121
+ WARNING: `start_argus.sh` assumes pyenv is installed into `~/.pyenv`
122
+
123
+ ```bash
124
+ sudo systemctl daemon-reload
125
+ sudo systemctl enable --now argus.service
126
+ ```
127
+
128
+
129
+
@@ -0,0 +1,109 @@
1
+ # Argus
2
+
3
+ ## Description
4
+
5
+ Argus is a test tracking system intended to provide observability into automated test pipelines which use long-running resources. It allows observation of a test status, its events and its allocated resources. It also allows easy comparison between particular runs of a specific test.
6
+
7
+ ## Installation notes
8
+
9
+ ### Development
10
+
11
+ For development setup instructions, see [dev-setup.md](./docs/dev-setup.md).
12
+
13
+ ### Prerequisites
14
+
15
+ - Python >=3.10.0 (system-wide or pyenv)
16
+
17
+ - NodeJS >=16 (with npm)
18
+
19
+ - Yarn (can be installed globally with `npm -g install yarn`)
20
+
21
+ - nginx
22
+
23
+ - poetry >=1.2.0b1
24
+
25
+ ### From source
26
+
27
+ #### Production
28
+
29
+ Perform the following steps:
30
+
31
+ Create a user that will be used by uwsgi:
32
+
33
+ ```bash
34
+ useradd -m -s /bin/bash argus
35
+ sudo -iu argus
36
+ ```
37
+
38
+ (Optional) Install pyenv and create a virtualenv for this user:
39
+
40
+ ```bash
41
+ pyenv install 3.10.0
42
+ pyenv virtualenv argus
43
+ pyenv activate argus
44
+ ```
45
+
46
+ Clone the project into a directory somewhere where user has full write permissions
47
+
48
+ ```bash
49
+ git clone https://github.com/scylladb/argus ~/app
50
+ cd ~/app
51
+ ```
52
+
53
+ Install project dependencies:
54
+
55
+ ```bash
56
+ poetry install --with default,dev,web-backend,docker-image
57
+ yarn install
58
+ ```
59
+
60
+ Compile frontend files from `/frontend` into `/public/dist`
61
+
62
+ ```bash
63
+ yarn webpack
64
+ ```
65
+
66
+ Create a `argus.local.yaml` configuration file (used to configure database connection) and a `argus_web.yaml` (used for webapp secrets) in your application install directory.
67
+
68
+ ```bash
69
+ cp argus_web.example.yaml argus_web.yaml
70
+ cp argus.yaml argus.local.yaml
71
+ ```
72
+
73
+ Open `argus.local.yaml` and add the database connection information (contact_points, user, password and keyspace name).
74
+
75
+ Open `argus_web.yaml` and change the `SECRET_KEY` value to something secure, like a sha512 digest of random bytes. Fill out GITHUB_* variables with their respective values.
76
+
77
+ Copy nginx configuration file from `docs/configs/argus.nginx.conf` to nginx virtual hosts directory:
78
+
79
+ Ubuntu:
80
+
81
+ ```bash
82
+ sudo cp docs/configs/argus.nginx.conf /etc/nginx/sites-available/argus
83
+ sudo ln -s /etc/nginx/sites-enabled/argus /etc/nginx/sites-available/argus
84
+ ```
85
+
86
+ RHEL/Centos/Alma/Fedora:
87
+
88
+ ```bash
89
+ sudo cp docs/configs/argus.nginx.conf /etc/nginx/conf.d/argus.conf
90
+ ```
91
+
92
+ Adjust the webhost settings in that file as necessary, particularly `listen` and `server_name` directives.
93
+
94
+ Copy systemd service file from `docs/config/argus.service` to `/etc/systemd/system` directory:
95
+
96
+ ```bash
97
+ sudo cp docs/config/argus.service /etc/systemd/system
98
+ ```
99
+
100
+ Open it and adjust the path to the `start_argus.sh` script in the `ExecStart=` directive and the user/group, then reload systemd daemon configuration and enable (and optionally start) the service.
101
+
102
+ WARNING: `start_argus.sh` assumes pyenv is installed into `~/.pyenv`
103
+
104
+ ```bash
105
+ sudo systemctl daemon-reload
106
+ sudo systemctl enable --now argus.service
107
+ ```
108
+
109
+
@@ -22,7 +22,7 @@ def sync_models_command():
22
22
  LOGGER.info("Synchronizing plugin type %s...", user_type.__name__)
23
23
  sync_type(ks_name=cluster.config["SCYLLA_KEYSPACE_NAME"], type_model=user_type)
24
24
  LOGGER.info("Synchronizing plugin models...")
25
- for model in all_plugin_models():
25
+ for model in all_plugin_models(True):
26
26
  LOGGER.info("Synchronizing plugin model %s...", model.__name__)
27
27
  sync_table(model=model, keyspaces=[cluster.config["SCYLLA_KEYSPACE_NAME"]])
28
28
 
@@ -261,3 +261,29 @@ def get_tests_for_group():
261
261
  "status": "ok",
262
262
  "response": tests
263
263
  }
264
+
265
+
266
+ @bp.route("/release/test/state/toggle", methods=["POST"])
267
+ @check_roles(UserRoles.Admin)
268
+ @api_login_required
269
+ def quick_toggle_test_enabled():
270
+
271
+ payload = get_payload(request)
272
+ res = ReleaseManagerService().toggle_test_enabled(test_id=payload["entityId"], new_state=payload["state"])
273
+ return {
274
+ "status": "ok",
275
+ "response": res
276
+ }
277
+
278
+
279
+ @bp.route("/release/group/state/toggle", methods=["POST"])
280
+ @check_roles(UserRoles.Admin)
281
+ @api_login_required
282
+ def quick_toggle_group_enabled():
283
+
284
+ payload = get_payload(request)
285
+ res = ReleaseManagerService().toggle_group_enabled(group_id=payload["entityId"], new_state=payload["state"])
286
+ return {
287
+ "status": "ok",
288
+ "response": res
289
+ }
@@ -12,7 +12,8 @@ from argus.backend.controller.notification_api import bp as notifications_bp
12
12
  from argus.backend.controller.client_api import bp as client_bp
13
13
  from argus.backend.controller.testrun_api import bp as testrun_bp
14
14
  from argus.backend.controller.team import bp as team_bp
15
- from argus.backend.service.argus_service import ArgusService
15
+ from argus.backend.controller.view_api import bp as view_bp
16
+ from argus.backend.service.argus_service import ArgusService, ScheduleUpdateRequest
16
17
  from argus.backend.service.user import UserService, api_login_required
17
18
  from argus.backend.service.stats import ReleaseStatsCollector
18
19
  from argus.backend.models.web import ArgusRelease, ArgusGroup, ArgusTest, User, UserOauthToken
@@ -23,6 +24,7 @@ bp.register_blueprint(notifications_bp)
23
24
  bp.register_blueprint(client_bp)
24
25
  bp.register_blueprint(testrun_bp)
25
26
  bp.register_blueprint(team_bp)
27
+ bp.register_blueprint(view_bp)
26
28
  bp.register_error_handler(Exception, handle_api_exception)
27
29
  LOGGER = logging.getLogger(__name__)
28
30
 
@@ -227,6 +229,8 @@ def release_schedules_submit():
227
229
  groups=payload["groups"],
228
230
  assignees=payload["assignees"],
229
231
  tag=payload["tag"],
232
+ comments=payload.get("comments"),
233
+ group_ids=payload.get("groupIds"),
230
234
  )
231
235
 
232
236
  return jsonify({
@@ -251,6 +255,27 @@ def release_schedules_delete():
251
255
  })
252
256
 
253
257
 
258
+ @bp.route("/release/schedules/update", methods=["POST"])
259
+ @api_login_required
260
+ def release_schedule_update():
261
+ payload = get_payload(request)
262
+ req = ScheduleUpdateRequest(**payload)
263
+ service = ArgusService()
264
+ update_result = service.update_schedule(
265
+ release_id=req.release_id,
266
+ schedule_id=req.schedule_id,
267
+ old_tests=req.old_tests,
268
+ new_tests=req.new_tests,
269
+ comments=req.comments,
270
+ assignee=req.assignee
271
+ )
272
+
273
+ return jsonify({
274
+ "status": "ok",
275
+ "response": update_result
276
+ })
277
+
278
+
254
279
  @bp.route("/groups", methods=["GET"])
255
280
  @api_login_required
256
281
  def argus_groups():
@@ -1,3 +1,5 @@
1
+ import datetime
2
+ import json
1
3
  import logging
2
4
  from uuid import UUID
3
5
  from flask import (
@@ -8,6 +10,7 @@ from argus.backend.controller.team_ui import bp as teams_bp
8
10
  from argus.backend.service.argus_service import ArgusService
9
11
  from argus.backend.models.web import WebFileStorage
10
12
  from argus.backend.service.user import UserService, login_required
13
+ from argus.backend.service.views import UserViewService
11
14
 
12
15
  LOGGER = logging.getLogger(__name__)
13
16
 
@@ -55,6 +58,24 @@ def releases():
55
58
  return render_template("releases.html.j2", releases=all_releases)
56
59
 
57
60
 
61
+ @bp.route("/views")
62
+ @login_required
63
+ def views():
64
+ service = UserViewService()
65
+ all_views = service.get_all_views()
66
+ return render_template("views.html.j2", views=sorted(all_views, key=lambda view: view.created or datetime.datetime.fromtimestamp(0), reverse=True))
67
+
68
+
69
+ @bp.route("/view/<string:view_name>")
70
+ @login_required
71
+ def view_dashboard(view_name: str):
72
+ service = UserViewService()
73
+ view = service.get_view_by_name(view_name=view_name)
74
+ data_json = view
75
+ view["widget_settings"] = json.loads(view["widget_settings"])
76
+ return render_template("view_dashboard.html.j2", data=data_json)
77
+
78
+
58
79
  @bp.route("/alert_debug")
59
80
  @login_required
60
81
  def alert_debug():
@@ -6,6 +6,7 @@ from flask import (
6
6
  )
7
7
 
8
8
  from argus.backend.error_handlers import handle_api_exception
9
+ from argus.backend.models.web import ArgusTest
9
10
  from argus.backend.service.jenkins_service import JenkinsService
10
11
  from argus.backend.service.testrun import TestRunService
11
12
  from argus.backend.service.user import api_login_required
@@ -288,6 +289,22 @@ def ignore_jobs():
288
289
  }
289
290
 
290
291
 
292
+ @bp.route("/get_runs_by_test_id_run_id", methods=["POST"])
293
+ @api_login_required
294
+ def get_runs_by_test_id_run_id():
295
+ payload: list[tuple[UUID, UUID]] = get_payload(request)
296
+ service = TestRunService()
297
+
298
+ result = service.resolve_run_build_id_and_number_multiple(payload)
299
+
300
+ return {
301
+ "status": "ok",
302
+ "response": {
303
+ "runs": result
304
+ }
305
+ }
306
+
307
+
291
308
  @bp.route("/jenkins/params", methods=["POST"])
292
309
  @api_login_required
293
310
  def get_jenkins_job_params():
@@ -336,4 +353,118 @@ def get_queue_info():
336
353
  "response": {
337
354
  "queueItem": result
338
355
  }
339
- }
356
+ }
357
+
358
+
359
+ @bp.route("/jenkins/clone/targets")
360
+ @api_login_required
361
+ def get_clone_targets():
362
+ test_id = request.args.get("testId")
363
+ if not test_id:
364
+ raise Exception("No testId provided")
365
+ service = JenkinsService()
366
+ result = service.get_releases_for_clone(test_id)
367
+
368
+ return {
369
+ "status": "ok",
370
+ "response": {
371
+ "targets": result
372
+ }
373
+ }
374
+
375
+
376
+ @bp.route("/jenkins/clone/groups")
377
+ @api_login_required
378
+ def get_groups_for_target():
379
+ target_id = request.args.get("targetId")
380
+ if not target_id:
381
+ raise Exception("No targetId provided")
382
+ service = JenkinsService()
383
+ result = service.get_groups_for_release(target_id)
384
+
385
+ return {
386
+ "status": "ok",
387
+ "response": {
388
+ "groups": result
389
+ }
390
+ }
391
+
392
+
393
+ @bp.route("/jenkins/clone/create", methods=["POST"])
394
+ @api_login_required
395
+ def clone_jenkins_job():
396
+
397
+ payload = get_payload(request)
398
+ service = JenkinsService()
399
+
400
+ result = service.clone_job(
401
+ current_test_id=payload["currentTestId"],
402
+ new_name=payload["newName"],
403
+ target=payload["target"],
404
+ group=payload["group"],
405
+ advanced_settings=payload["advancedSettings"],
406
+ )
407
+
408
+ return {
409
+ "status": "ok",
410
+ "response": result
411
+ }
412
+
413
+
414
+ @bp.route("/jenkins/clone/build", methods=["POST"])
415
+ @api_login_required
416
+ def clone_build_jenkins_job():
417
+
418
+ payload = get_payload(request)
419
+ service = JenkinsService()
420
+
421
+ result = service.clone_build_job(build_id=payload["buildId"], params=payload["parameters"])
422
+
423
+ return {
424
+ "status": "ok",
425
+ "response": result
426
+ }
427
+
428
+
429
+ @bp.route("/jenkins/clone/settings")
430
+ @api_login_required
431
+ def get_clone_job_advanced_settings():
432
+ build_id = request.args.get("buildId")
433
+ if not build_id:
434
+ raise Exception("No testId provided")
435
+ service = JenkinsService()
436
+ result = service.get_advanced_settings(build_id)
437
+
438
+ return {
439
+ "status": "ok",
440
+ "response": result
441
+ }
442
+
443
+
444
+ @bp.route("/jenkins/clone/settings/change", methods=["POST"])
445
+ @api_login_required
446
+ def set_job_settings():
447
+ payload = get_payload(request)
448
+ service = JenkinsService()
449
+ test = ArgusTest.get(build_system_id=payload["buildId"])
450
+ result = service.adjust_job_settings(build_id=test.build_system_id, plugin_name=test.plugin_name, settings=payload["settings"])
451
+
452
+ return {
453
+ "status": "ok",
454
+ "response": result
455
+ }
456
+
457
+
458
+ @bp.route("/jenkins/clone/settings/validate", methods=["POST"])
459
+ @api_login_required
460
+ def clone_validate_new_settings():
461
+
462
+ payload = get_payload(request)
463
+ service = JenkinsService()
464
+
465
+ result = service.verify_job_settings(build_id=payload["buildId"], new_settings=payload["newSettings"])
466
+
467
+ return {
468
+ "status": "ok",
469
+ "response": result
470
+ }
@@ -0,0 +1,162 @@
1
+ import logging
2
+ from uuid import UUID
3
+ from flask import (
4
+ Blueprint,
5
+ jsonify,
6
+ request,
7
+ )
8
+ from argus.backend.error_handlers import handle_api_exception
9
+ from argus.backend.models.web import User
10
+ from argus.backend.service.stats import ViewStatsCollector
11
+ from argus.backend.service.user import api_login_required
12
+ from argus.backend.service.views import UserViewService
13
+ from argus.backend.util.common import get_payload
14
+
15
+ bp = Blueprint('view_api', __name__, url_prefix='/views')
16
+ LOGGER = logging.getLogger(__name__)
17
+ bp.register_error_handler(Exception, handle_api_exception)
18
+
19
+
20
+ class ViewApiException(Exception):
21
+ pass
22
+
23
+
24
+ @bp.route("/", methods=["GET"])
25
+ @api_login_required
26
+ def index():
27
+ return {
28
+ "status": "ok",
29
+ "response": {
30
+ "version": "v1",
31
+ }
32
+ }
33
+
34
+
35
+ @bp.route("/create", methods=["POST"])
36
+ @api_login_required
37
+ def create_view():
38
+ payload = get_payload(request)
39
+ service = UserViewService()
40
+ view = service.create_view(
41
+ name=payload["name"],
42
+ items=payload["items"],
43
+ widget_settings=payload["settings"],
44
+ description=payload.get("description"),
45
+ display_name=payload.get("displayName")
46
+ )
47
+ return {
48
+ "status": "ok",
49
+ "response": view
50
+ }
51
+
52
+
53
+ @bp.route("/get", methods=["GET"])
54
+ @api_login_required
55
+ def get_view():
56
+ view_id = request.args.get("viewId")
57
+ if not view_id:
58
+ raise ViewApiException("No viewId provided.")
59
+ service = UserViewService()
60
+ view = service.get_view(UUID(view_id))
61
+ return {
62
+ "status": "ok",
63
+ "response": view
64
+ }
65
+
66
+
67
+ @bp.route("/all", methods=["GET"])
68
+ @api_login_required
69
+ def get_all_views():
70
+ user_id = request.args.get("userId")
71
+ if user_id:
72
+ user = User.get(id=user_id)
73
+ else:
74
+ user = None
75
+ service = UserViewService()
76
+ views = service.get_all_views(user)
77
+ return {
78
+ "status": "ok",
79
+ "response": views
80
+ }
81
+
82
+
83
+ @bp.route("/update", methods=["POST"])
84
+ @api_login_required
85
+ def update_view():
86
+ payload = get_payload(request)
87
+ service = UserViewService()
88
+ res = service.update_view(view_id=payload["viewId"], update_data=payload["updateData"])
89
+ return {
90
+ "status": "ok",
91
+ "response": res
92
+ }
93
+
94
+
95
+ @bp.route("/delete", methods=["POST"])
96
+ @api_login_required
97
+ def delete_view():
98
+ payload = get_payload(request)
99
+ service = UserViewService()
100
+ res = service.delete_view(payload["viewId"])
101
+ return {
102
+ "status": "ok",
103
+ "response": res
104
+ }
105
+
106
+
107
+ @bp.route("/search", methods=["GET"])
108
+ @api_login_required
109
+ def search_tests():
110
+ query = request.args.get("query")
111
+ service = UserViewService()
112
+ if query:
113
+ res = service.test_lookup(query)
114
+ else:
115
+ res = []
116
+ return {
117
+ "status": "ok",
118
+ "response": {
119
+ "hits": res,
120
+ "total": len(res)
121
+ }
122
+ }
123
+
124
+ @bp.route("/stats", methods=["GET"])
125
+ @api_login_required
126
+ def view_stats():
127
+ view_id = request.args.get("viewId")
128
+ if not view_id:
129
+ raise ViewApiException("No view id provided.")
130
+ limited = bool(int(request.args.get("limited", 0)))
131
+ version = request.args.get("productVersion", None)
132
+ include_no_version = bool(int(request.args.get("includeNoVersion", True)))
133
+ force = bool(int(request.args.get("force", 0)))
134
+ collector = ViewStatsCollector(view_id=view_id, filter=version)
135
+ stats = collector.collect(limited=limited, force=force, include_no_version=include_no_version)
136
+
137
+ res = jsonify({
138
+ "status": "ok",
139
+ "response": stats
140
+ })
141
+ res.cache_control.max_age = 300
142
+ return res
143
+
144
+ @bp.route("/<string:view_id>/versions", methods=["GET"])
145
+ @api_login_required
146
+ def view_versions(view_id: str):
147
+ service = UserViewService()
148
+ res = service.get_versions_for_view(view_id)
149
+ return {
150
+ "status": "ok",
151
+ "response": res
152
+ }
153
+
154
+ @bp.route("/<string:view_id>/resolve", methods=["GET"])
155
+ @api_login_required
156
+ def view_resolve(view_id: str):
157
+ service = UserViewService()
158
+ res = service.resolve_view_for_edit(view_id)
159
+ return {
160
+ "status": "ok",
161
+ "response": res
162
+ }