cornflow 1.0.11__py3-none-any.whl → 1.1.0a1__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.
- cornflow/cli/service.py +4 -0
- cornflow/commands/__init__.py +1 -1
- cornflow/commands/schemas.py +31 -0
- cornflow/config.py +6 -0
- cornflow/endpoints/execution.py +2 -1
- cornflow/endpoints/login.py +16 -13
- cornflow/endpoints/user.py +2 -2
- cornflow/migrations/versions/991b98e24225_.py +33 -0
- cornflow/models/user.py +4 -0
- cornflow/schemas/execution.py +8 -1
- cornflow/schemas/solution_log.py +11 -5
- cornflow/schemas/user.py +3 -0
- cornflow/shared/authentication/auth.py +1 -1
- cornflow/shared/licenses.py +17 -54
- cornflow/tests/custom_test_case.py +17 -3
- cornflow/tests/integration/test_cornflowclient.py +20 -14
- cornflow/tests/unit/test_cases.py +95 -6
- cornflow/tests/unit/test_dags.py +48 -1
- cornflow/tests/unit/test_example_data.py +3 -0
- cornflow/tests/unit/test_executions.py +98 -8
- cornflow/tests/unit/test_instances.py +43 -5
- cornflow/tests/unit/test_main_alarms.py +8 -8
- cornflow/tests/unit/test_schemas.py +12 -1
- cornflow/tests/unit/test_token.py +17 -0
- cornflow/tests/unit/test_users.py +16 -0
- {cornflow-1.0.11.dist-info → cornflow-1.1.0a1.dist-info}/METADATA +2 -2
- {cornflow-1.0.11.dist-info → cornflow-1.1.0a1.dist-info}/RECORD +30 -29
- {cornflow-1.0.11.dist-info → cornflow-1.1.0a1.dist-info}/WHEEL +0 -0
- {cornflow-1.0.11.dist-info → cornflow-1.1.0a1.dist-info}/entry_points.txt +0 -0
- {cornflow-1.0.11.dist-info → cornflow-1.1.0a1.dist-info}/top_level.txt +0 -0
@@ -201,8 +201,29 @@ class TestCasesRawDataEndpoint(CustomTestCase):
|
|
201
201
|
self.payload.pop("solution")
|
202
202
|
self.items_to_check = ["name", "description", "schema", "data"]
|
203
203
|
_id = self.create_new_row(self.url, self.model, self.payload)
|
204
|
+
keys_to_check = [
|
205
|
+
"data",
|
206
|
+
"solution_checks",
|
207
|
+
"updated_at",
|
208
|
+
"id",
|
209
|
+
"schema",
|
210
|
+
"data_hash",
|
211
|
+
"path",
|
212
|
+
"solution_hash",
|
213
|
+
"user_id",
|
214
|
+
"indicators",
|
215
|
+
"solution",
|
216
|
+
"is_dir",
|
217
|
+
"description",
|
218
|
+
"name",
|
219
|
+
"checks",
|
220
|
+
"created_at",
|
221
|
+
]
|
204
222
|
data = self.get_one_row(
|
205
|
-
self.url + "/" + str(_id) + "/data/",
|
223
|
+
self.url + "/" + str(_id) + "/data/",
|
224
|
+
payload={},
|
225
|
+
check_payload=False,
|
226
|
+
keys_to_check=keys_to_check,
|
206
227
|
)
|
207
228
|
self.assertIsNone(data["solution"])
|
208
229
|
|
@@ -293,7 +314,21 @@ class TestCaseListEndpoint(BaseTestCases.ListFilters):
|
|
293
314
|
self.url = CASE_URL
|
294
315
|
|
295
316
|
def test_get_rows(self):
|
296
|
-
|
317
|
+
keys_to_check = [
|
318
|
+
"data_hash",
|
319
|
+
"created_at",
|
320
|
+
"is_dir",
|
321
|
+
"path",
|
322
|
+
"schema",
|
323
|
+
"description",
|
324
|
+
"solution_hash",
|
325
|
+
"id",
|
326
|
+
"user_id",
|
327
|
+
"updated_at",
|
328
|
+
"name",
|
329
|
+
"indicators",
|
330
|
+
]
|
331
|
+
self.get_rows(self.url, self.payloads, keys_to_check=keys_to_check)
|
297
332
|
|
298
333
|
|
299
334
|
class TestCaseDetailEndpoint(BaseTestCases.DetailEndpoint):
|
@@ -365,7 +400,19 @@ class TestCaseToInstanceEndpoint(CustomTestCase):
|
|
365
400
|
)
|
366
401
|
|
367
402
|
payload = response.json
|
368
|
-
|
403
|
+
keys_to_check = [
|
404
|
+
"id",
|
405
|
+
"schema",
|
406
|
+
"data_hash",
|
407
|
+
"executions",
|
408
|
+
"user_id",
|
409
|
+
"description",
|
410
|
+
"name",
|
411
|
+
"created_at",
|
412
|
+
]
|
413
|
+
result = self.get_one_row(
|
414
|
+
INSTANCE_URL + payload["id"] + "/", payload, keys_to_check=keys_to_check
|
415
|
+
)
|
369
416
|
dif = self.response_items.symmetric_difference(result.keys())
|
370
417
|
self.assertEqual(len(dif), 0)
|
371
418
|
|
@@ -382,7 +429,23 @@ class TestCaseToInstanceEndpoint(CustomTestCase):
|
|
382
429
|
]
|
383
430
|
self.response_items = set(self.items_to_check)
|
384
431
|
|
385
|
-
|
432
|
+
keys_to_check = [
|
433
|
+
"data",
|
434
|
+
"id",
|
435
|
+
"schema",
|
436
|
+
"data_hash",
|
437
|
+
"user_id",
|
438
|
+
"description",
|
439
|
+
"name",
|
440
|
+
"checks",
|
441
|
+
"created_at",
|
442
|
+
]
|
443
|
+
|
444
|
+
result = self.get_one_row(
|
445
|
+
INSTANCE_URL + payload["id"] + "/data/",
|
446
|
+
payload,
|
447
|
+
keys_to_check=keys_to_check,
|
448
|
+
)
|
386
449
|
dif = self.response_items.symmetric_difference(result.keys())
|
387
450
|
self.assertEqual(len(dif), 0)
|
388
451
|
|
@@ -539,11 +602,37 @@ class TestCaseDataEndpoint(CustomTestCase):
|
|
539
602
|
]
|
540
603
|
|
541
604
|
def test_get_data(self):
|
542
|
-
|
605
|
+
keys_to_check = [
|
606
|
+
"data",
|
607
|
+
"solution_checks",
|
608
|
+
"updated_at",
|
609
|
+
"id",
|
610
|
+
"schema",
|
611
|
+
"data_hash",
|
612
|
+
"path",
|
613
|
+
"solution_hash",
|
614
|
+
"user_id",
|
615
|
+
"indicators",
|
616
|
+
"solution",
|
617
|
+
"is_dir",
|
618
|
+
"description",
|
619
|
+
"name",
|
620
|
+
"checks",
|
621
|
+
"created_at",
|
622
|
+
]
|
623
|
+
self.get_one_row(
|
624
|
+
self.url + str(self.payload["id"]) + "/data/",
|
625
|
+
self.payload,
|
626
|
+
keys_to_check=keys_to_check,
|
627
|
+
)
|
543
628
|
|
544
629
|
def test_get_no_data(self):
|
545
630
|
self.get_one_row(
|
546
|
-
self.url + str(500) + "/data/",
|
631
|
+
self.url + str(500) + "/data/",
|
632
|
+
{},
|
633
|
+
expected_status=404,
|
634
|
+
check_payload=False,
|
635
|
+
keys_to_check=["error"],
|
547
636
|
)
|
548
637
|
|
549
638
|
def test_get_compressed_data(self):
|
cornflow/tests/unit/test_dags.py
CHANGED
@@ -24,6 +24,7 @@ from cornflow.tests.const import (
|
|
24
24
|
LOGIN_URL,
|
25
25
|
SIGNUP_URL,
|
26
26
|
USER_URL,
|
27
|
+
EXECUTION_URL,
|
27
28
|
)
|
28
29
|
from cornflow.tests.unit.test_executions import TestExecutionsDetailEndpointMock
|
29
30
|
from cornflow_client import get_pulp_jsonschema, get_empty_schema
|
@@ -90,13 +91,31 @@ class TestDagDetailEndpoint(TestExecutionsDetailEndpointMock):
|
|
90
91
|
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
91
92
|
with open(CASE_PATH) as f:
|
92
93
|
payload = json.load(f)
|
94
|
+
|
95
|
+
log_json = {
|
96
|
+
"time": 10.3,
|
97
|
+
"solver": "dummy",
|
98
|
+
"status": "feasible",
|
99
|
+
"status_code": 2,
|
100
|
+
"sol_code": 1,
|
101
|
+
"some_other_key": "this should be excluded",
|
102
|
+
}
|
103
|
+
|
93
104
|
data = dict(
|
94
105
|
data=payload["data"],
|
95
106
|
state=EXEC_STATE_CORRECT,
|
107
|
+
log_json={
|
108
|
+
"time": 10.3,
|
109
|
+
"solver": "dummy",
|
110
|
+
"status": "feasible",
|
111
|
+
"status_code": 2,
|
112
|
+
"sol_code": 1,
|
113
|
+
"some_other_key": "this should be excluded",
|
114
|
+
},
|
96
115
|
)
|
97
116
|
payload_to_check = {**self.payload, **data}
|
98
117
|
token = self.create_service_user()
|
99
|
-
|
118
|
+
self.update_row(
|
100
119
|
url=DAG_URL + idx + "/",
|
101
120
|
payload_to_check=payload_to_check,
|
102
121
|
change=data,
|
@@ -104,19 +123,46 @@ class TestDagDetailEndpoint(TestExecutionsDetailEndpointMock):
|
|
104
123
|
check_payload=False,
|
105
124
|
)
|
106
125
|
|
126
|
+
data = self.get_one_row(
|
127
|
+
url=EXECUTION_URL + idx + "/log/",
|
128
|
+
token=token,
|
129
|
+
check_payload=False,
|
130
|
+
payload=self.payload,
|
131
|
+
expected_status=200,
|
132
|
+
)
|
133
|
+
|
134
|
+
for key in data["log"]:
|
135
|
+
self.assertEqual(data["log"][key], log_json[key])
|
136
|
+
|
137
|
+
self.assertNotIn("some_other_key", data["log"].keys())
|
138
|
+
|
107
139
|
def test_get_dag(self):
|
108
140
|
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
109
141
|
token = self.create_service_user()
|
142
|
+
keys_to_check = ["id", "data", "solution_data", "config"]
|
110
143
|
data = self.get_one_row(
|
111
144
|
url=DAG_URL + idx + "/",
|
112
145
|
token=token,
|
113
146
|
check_payload=False,
|
114
147
|
payload=self.payload,
|
148
|
+
keys_to_check=keys_to_check,
|
115
149
|
)
|
150
|
+
keys_to_check = [
|
151
|
+
"data",
|
152
|
+
"id",
|
153
|
+
"schema",
|
154
|
+
"data_hash",
|
155
|
+
"user_id",
|
156
|
+
"description",
|
157
|
+
"name",
|
158
|
+
"checks",
|
159
|
+
"created_at",
|
160
|
+
]
|
116
161
|
instance_data = self.get_one_row(
|
117
162
|
url=INSTANCE_URL + self.payload["instance_id"] + "/data/",
|
118
163
|
payload=dict(),
|
119
164
|
check_payload=False,
|
165
|
+
keys_to_check=keys_to_check,
|
120
166
|
)
|
121
167
|
self.assertEqual(data["data"], instance_data["data"])
|
122
168
|
self.assertEqual(data["config"], self.payload["config"])
|
@@ -130,6 +176,7 @@ class TestDagDetailEndpoint(TestExecutionsDetailEndpointMock):
|
|
130
176
|
check_payload=False,
|
131
177
|
payload=self.payload,
|
132
178
|
expected_status=403,
|
179
|
+
keys_to_check=["error"],
|
133
180
|
)
|
134
181
|
|
135
182
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
|
3
3
|
"""
|
4
|
+
|
4
5
|
# General imports
|
5
6
|
import json
|
6
7
|
|
@@ -40,11 +41,13 @@ class TestExampleDataEndpoint(CustomTestCase):
|
|
40
41
|
@patch("cornflow.endpoints.example_data.Airflow.from_config")
|
41
42
|
def test_get_example(self, airflow_init):
|
42
43
|
af_client = self.patch_af_client(airflow_init)
|
44
|
+
keys_to_check = ["name", "examples"]
|
43
45
|
example = self.get_one_row(
|
44
46
|
self.url + "{}/".format(self.schema_name),
|
45
47
|
{},
|
46
48
|
expected_status=200,
|
47
49
|
check_payload=False,
|
50
|
+
keys_to_check=keys_to_check,
|
48
51
|
)
|
49
52
|
self.assertIn("examples", example)
|
50
53
|
self.assertIn("name", example)
|
@@ -43,6 +43,21 @@ class TestExecutionsListEndpoint(BaseTestCases.ListFilters):
|
|
43
43
|
self.bad_payload = load_file_fk(BAD_EXECUTION_PATH)
|
44
44
|
self.payloads = [load_file_fk(f) for f in EXECUTIONS_LIST]
|
45
45
|
self.solution = load_file_fk(EXECUTION_SOLUTION_PATH)
|
46
|
+
self.keys_to_check = [
|
47
|
+
"data_hash",
|
48
|
+
"created_at",
|
49
|
+
"config",
|
50
|
+
"state",
|
51
|
+
"message",
|
52
|
+
"schema",
|
53
|
+
"description",
|
54
|
+
"id",
|
55
|
+
"user_id",
|
56
|
+
"log",
|
57
|
+
"instance_id",
|
58
|
+
"name",
|
59
|
+
"indicators",
|
60
|
+
]
|
46
61
|
|
47
62
|
def test_new_execution(self):
|
48
63
|
self.create_new_row(self.url, self.model, payload=self.payload)
|
@@ -115,13 +130,13 @@ class TestExecutionsListEndpoint(BaseTestCases.ListFilters):
|
|
115
130
|
self.assertTrue("error" in response.json)
|
116
131
|
|
117
132
|
def test_get_executions(self):
|
118
|
-
self.get_rows(self.url, self.payloads)
|
133
|
+
self.get_rows(self.url, self.payloads, keys_to_check=self.keys_to_check)
|
119
134
|
|
120
135
|
def test_get_no_executions(self):
|
121
136
|
self.get_no_rows(self.url)
|
122
137
|
|
123
138
|
def test_get_executions_superadmin(self):
|
124
|
-
self.get_rows(self.url, self.payloads)
|
139
|
+
self.get_rows(self.url, self.payloads, keys_to_check=self.keys_to_check)
|
125
140
|
token = self.create_service_user()
|
126
141
|
rows = self.client.get(
|
127
142
|
self.url, follow_redirects=True, headers=self.get_header_with_auth(token)
|
@@ -275,15 +290,42 @@ class TestExecutionsDetailEndpoint(
|
|
275
290
|
|
276
291
|
def test_create_delete_instance_load(self):
|
277
292
|
idx = self.create_new_row(self.url + "?run=0", self.model, self.payload)
|
293
|
+
keys_to_check = [
|
294
|
+
"message",
|
295
|
+
"id",
|
296
|
+
"schema",
|
297
|
+
"data_hash",
|
298
|
+
"config",
|
299
|
+
"instance_id",
|
300
|
+
"user_id",
|
301
|
+
"indicators",
|
302
|
+
"description",
|
303
|
+
"name",
|
304
|
+
"created_at",
|
305
|
+
"state",
|
306
|
+
]
|
278
307
|
execution = self.get_one_row(
|
279
|
-
self.url + idx,
|
308
|
+
self.url + idx,
|
309
|
+
payload={**self.payload, **dict(id=idx)},
|
310
|
+
keys_to_check=keys_to_check,
|
280
311
|
)
|
281
312
|
self.delete_row(self.url + idx + "/")
|
313
|
+
keys_to_check = [
|
314
|
+
"id",
|
315
|
+
"schema",
|
316
|
+
"description",
|
317
|
+
"name",
|
318
|
+
"user_id",
|
319
|
+
"executions",
|
320
|
+
"created_at",
|
321
|
+
"data_hash",
|
322
|
+
]
|
282
323
|
instance = self.get_one_row(
|
283
324
|
INSTANCE_URL + execution["instance_id"] + "/",
|
284
325
|
payload={},
|
285
326
|
expected_status=200,
|
286
327
|
check_payload=False,
|
328
|
+
keys_to_check=keys_to_check,
|
287
329
|
)
|
288
330
|
executions = [execution["id"] for execution in instance["executions"]]
|
289
331
|
self.assertFalse(idx in executions)
|
@@ -351,20 +393,41 @@ class TestExecutionsDataEndpoint(TestExecutionsDetailEndpointMock):
|
|
351
393
|
super().setUp()
|
352
394
|
self.response_items = {"id", "name", "data"}
|
353
395
|
self.items_to_check = ["name"]
|
396
|
+
self.keys_to_check = [
|
397
|
+
"created_at",
|
398
|
+
"checks",
|
399
|
+
"instance_id",
|
400
|
+
"schema",
|
401
|
+
"data",
|
402
|
+
"user_id",
|
403
|
+
"message",
|
404
|
+
"data_hash",
|
405
|
+
"log",
|
406
|
+
"config",
|
407
|
+
"description",
|
408
|
+
"state",
|
409
|
+
"name",
|
410
|
+
"id",
|
411
|
+
]
|
354
412
|
|
355
413
|
def test_get_one_execution(self):
|
356
414
|
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
357
415
|
self.url = EXECUTION_URL + idx + "/data/"
|
358
416
|
payload = dict(self.payload)
|
359
417
|
payload["id"] = idx
|
360
|
-
self.get_one_row(self.url, payload)
|
418
|
+
self.get_one_row(self.url, payload, keys_to_check=self.keys_to_check)
|
361
419
|
|
362
420
|
def test_get_one_execution_superadmin(self):
|
363
421
|
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
364
422
|
payload = dict(self.payload)
|
365
423
|
payload["id"] = idx
|
366
424
|
token = self.create_service_user()
|
367
|
-
self.get_one_row(
|
425
|
+
self.get_one_row(
|
426
|
+
EXECUTION_URL + idx + "/data/",
|
427
|
+
payload,
|
428
|
+
token=token,
|
429
|
+
keys_to_check=self.keys_to_check,
|
430
|
+
)
|
368
431
|
|
369
432
|
|
370
433
|
class TestExecutionsLogEndpoint(TestExecutionsDetailEndpointMock):
|
@@ -372,19 +435,42 @@ class TestExecutionsLogEndpoint(TestExecutionsDetailEndpointMock):
|
|
372
435
|
super().setUp()
|
373
436
|
self.response_items = {"id", "name", "log", "indicators"}
|
374
437
|
self.items_to_check = ["name"]
|
438
|
+
self.keys_to_check = [
|
439
|
+
"created_at",
|
440
|
+
"id",
|
441
|
+
"log_text",
|
442
|
+
"instance_id",
|
443
|
+
"state",
|
444
|
+
"message",
|
445
|
+
"description",
|
446
|
+
"data_hash",
|
447
|
+
"name",
|
448
|
+
"log",
|
449
|
+
"schema",
|
450
|
+
"user_id",
|
451
|
+
"config",
|
452
|
+
"indicators",
|
453
|
+
]
|
375
454
|
|
376
455
|
def test_get_one_execution(self):
|
377
456
|
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
378
457
|
payload = dict(self.payload)
|
379
458
|
payload["id"] = idx
|
380
|
-
self.get_one_row(
|
459
|
+
self.get_one_row(
|
460
|
+
EXECUTION_URL + idx + "/log/", payload, keys_to_check=self.keys_to_check
|
461
|
+
)
|
381
462
|
|
382
463
|
def test_get_one_execution_superadmin(self):
|
383
464
|
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
384
465
|
payload = dict(self.payload)
|
385
466
|
payload["id"] = idx
|
386
467
|
token = self.create_service_user()
|
387
|
-
self.get_one_row(
|
468
|
+
self.get_one_row(
|
469
|
+
EXECUTION_URL + idx + "/log/",
|
470
|
+
payload,
|
471
|
+
token=token,
|
472
|
+
keys_to_check=self.keys_to_check,
|
473
|
+
)
|
388
474
|
|
389
475
|
|
390
476
|
class TestExecutionsStatusEndpoint(TestExecutionsDetailEndpointMock):
|
@@ -400,8 +486,12 @@ class TestExecutionsStatusEndpoint(TestExecutionsDetailEndpointMock):
|
|
400
486
|
idx = self.create_new_row(EXECUTION_URL, self.model, self.payload)
|
401
487
|
payload = dict(self.payload)
|
402
488
|
payload["id"] = idx
|
489
|
+
keys_to_check = ["state", "message", "id", "data_hash"]
|
403
490
|
data = self.get_one_row(
|
404
|
-
EXECUTION_URL + idx + "/status/",
|
491
|
+
EXECUTION_URL + idx + "/status/",
|
492
|
+
payload,
|
493
|
+
check_payload=False,
|
494
|
+
keys_to_check=keys_to_check,
|
405
495
|
)
|
406
496
|
self.assertEqual(data["state"], 1)
|
407
497
|
|
@@ -36,6 +36,15 @@ class TestInstancesListEndpoint(BaseTestCases.ListFilters):
|
|
36
36
|
|
37
37
|
self.payload = load_file(INSTANCE_PATH)
|
38
38
|
self.payloads = [load_file(f) for f in INSTANCES_LIST]
|
39
|
+
self.keys_to_check = [
|
40
|
+
"data_hash",
|
41
|
+
"created_at",
|
42
|
+
"schema",
|
43
|
+
"description",
|
44
|
+
"id",
|
45
|
+
"user_id",
|
46
|
+
"name",
|
47
|
+
]
|
39
48
|
|
40
49
|
def test_new_instance(self):
|
41
50
|
self.create_new_row(self.url, self.model, self.payload)
|
@@ -65,10 +74,10 @@ class TestInstancesListEndpoint(BaseTestCases.ListFilters):
|
|
65
74
|
self.assertTrue("error" in response.json)
|
66
75
|
|
67
76
|
def test_get_instances(self):
|
68
|
-
self.get_rows(self.url, self.payloads)
|
77
|
+
self.get_rows(self.url, self.payloads, keys_to_check=self.keys_to_check)
|
69
78
|
|
70
79
|
def test_get_instances_superadmin(self):
|
71
|
-
self.get_rows(self.url, self.payloads)
|
80
|
+
self.get_rows(self.url, self.payloads, keys_to_check=self.keys_to_check)
|
72
81
|
token = self.create_service_user()
|
73
82
|
rows = self.client.get(
|
74
83
|
self.url, follow_redirects=True, headers=self.get_header_with_auth(token)
|
@@ -173,7 +182,20 @@ class TestInstancesDataEndpoint(TestInstancesDetailEndpointBase):
|
|
173
182
|
def test_get_one_instance(self):
|
174
183
|
idx = self.create_new_row(self.url, self.model, self.payload)
|
175
184
|
payload = {**self.payload, **dict(id=idx)}
|
176
|
-
|
185
|
+
keys_to_check = [
|
186
|
+
"data",
|
187
|
+
"id",
|
188
|
+
"schema",
|
189
|
+
"data_hash",
|
190
|
+
"user_id",
|
191
|
+
"description",
|
192
|
+
"name",
|
193
|
+
"checks",
|
194
|
+
"created_at",
|
195
|
+
]
|
196
|
+
result = self.get_one_row(
|
197
|
+
INSTANCE_URL + idx + "/data/", payload, keys_to_check=keys_to_check
|
198
|
+
)
|
177
199
|
dif = self.response_items.symmetric_difference(result.keys())
|
178
200
|
self.assertEqual(len(dif), 0)
|
179
201
|
|
@@ -208,6 +230,7 @@ class TestInstancesDataEndpoint(TestInstancesDetailEndpointBase):
|
|
208
230
|
expected_status=404,
|
209
231
|
check_payload=False,
|
210
232
|
token=token,
|
233
|
+
keys_to_check=["error"],
|
211
234
|
)
|
212
235
|
|
213
236
|
def test_get_none_instance_planner_all(self):
|
@@ -232,8 +255,23 @@ class TestAccessPlannerUsers(CustomTestCase):
|
|
232
255
|
idx = self.create_new_row(self.url, self.model, self.payload)
|
233
256
|
token = self.create_planner()
|
234
257
|
payload = {**self.payload, **dict(id=idx)}
|
235
|
-
|
236
|
-
|
258
|
+
keys_to_check = [
|
259
|
+
"data",
|
260
|
+
"id",
|
261
|
+
"schema",
|
262
|
+
"data_hash",
|
263
|
+
"user_id",
|
264
|
+
"description",
|
265
|
+
"name",
|
266
|
+
"checks",
|
267
|
+
"created_at",
|
268
|
+
]
|
269
|
+
self.get_one_row(
|
270
|
+
INSTANCE_URL + idx + "/data/",
|
271
|
+
payload,
|
272
|
+
token=token,
|
273
|
+
keys_to_check=keys_to_check,
|
274
|
+
)
|
237
275
|
|
238
276
|
def test_get_all_instance_planner(self):
|
239
277
|
# Test planner users can access objects of other users
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
|
3
3
|
"""
|
4
|
+
|
4
5
|
import json
|
5
6
|
|
6
7
|
# Imports from internal modules
|
@@ -19,7 +20,7 @@ class TestMainAlarmsEndpoint(CustomTestCase):
|
|
19
20
|
payload = {
|
20
21
|
"name": "Alarm 1",
|
21
22
|
"description": "Description Alarm 1",
|
22
|
-
"criticality": 1
|
23
|
+
"criticality": 1,
|
23
24
|
}
|
24
25
|
self.id_alarm = self.client.post(
|
25
26
|
ALARMS_URL,
|
@@ -32,7 +33,7 @@ class TestMainAlarmsEndpoint(CustomTestCase):
|
|
32
33
|
payload = {
|
33
34
|
"message": "Message Main Alarm 1",
|
34
35
|
"criticality": 1,
|
35
|
-
"id_alarm": self.id_alarm
|
36
|
+
"id_alarm": self.id_alarm,
|
36
37
|
}
|
37
38
|
self.create_new_row(self.url, self.model, payload)
|
38
39
|
|
@@ -41,23 +42,22 @@ class TestMainAlarmsEndpoint(CustomTestCase):
|
|
41
42
|
{
|
42
43
|
"message": "Message Main Alarm 1",
|
43
44
|
"criticality": 1,
|
44
|
-
"id_alarm": self.id_alarm
|
45
|
+
"id_alarm": self.id_alarm,
|
45
46
|
},
|
46
47
|
{
|
47
48
|
"message": "Message Main Alarm 2",
|
48
49
|
"criticality": 2,
|
49
50
|
"schema": "solve_model_dag",
|
50
|
-
"id_alarm": self.id_alarm
|
51
|
+
"id_alarm": self.id_alarm,
|
51
52
|
},
|
52
53
|
]
|
54
|
+
keys_to_check = ["schema", "id_alarm", "criticality", "id", "message"]
|
53
55
|
rows = self.get_rows(
|
54
|
-
self.url,
|
55
|
-
data,
|
56
|
-
check_data=False
|
56
|
+
self.url, data, check_data=False, keys_to_check=keys_to_check
|
57
57
|
)
|
58
58
|
rows_data = list(rows.json)
|
59
59
|
for i in range(len(data)):
|
60
60
|
for key in self.get_keys_to_check(data[i]):
|
61
61
|
self.assertIn(key, rows_data[i])
|
62
62
|
if key in data[i]:
|
63
|
-
self.assertEqual(rows_data[i][key], data[i][key])
|
63
|
+
self.assertEqual(rows_data[i][key], data[i][key])
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
|
3
3
|
"""
|
4
|
+
|
4
5
|
# General imports
|
5
6
|
import unittest
|
6
7
|
|
@@ -159,11 +160,20 @@ class TestSchemaEndpoint(CustomTestCase):
|
|
159
160
|
self.schema_name = "solve_model_dag"
|
160
161
|
|
161
162
|
def test_get_schema(self):
|
163
|
+
keys_to_check = [
|
164
|
+
"solution_checks",
|
165
|
+
"instance_checks",
|
166
|
+
"config",
|
167
|
+
"solution",
|
168
|
+
"name",
|
169
|
+
"instance",
|
170
|
+
]
|
162
171
|
schemas = self.get_one_row(
|
163
172
|
self.url + "{}/".format(self.schema_name),
|
164
173
|
{},
|
165
174
|
expected_status=200,
|
166
175
|
check_payload=False,
|
176
|
+
keys_to_check=keys_to_check,
|
167
177
|
)
|
168
178
|
self.assertIn("instance", schemas)
|
169
179
|
self.assertIn("solution", schemas)
|
@@ -178,7 +188,7 @@ class TestNewSchemaEndpointOpen(CustomTestCase):
|
|
178
188
|
self.url = SCHEMA_URL
|
179
189
|
|
180
190
|
def test_get_all_schemas(self):
|
181
|
-
schemas = self.get_one_row(self.url, {}, 200, False)
|
191
|
+
schemas = self.get_one_row(self.url, {}, 200, False, keys_to_check=["name"])
|
182
192
|
dags = [{"name": dag} for dag in ["solve_model_dag", "gc", "timer"]]
|
183
193
|
|
184
194
|
self.assertEqual(dags, schemas)
|
@@ -205,6 +215,7 @@ class TestNewSchemaEndpointNotOpen(CustomTestCase):
|
|
205
215
|
{},
|
206
216
|
expected_status=403,
|
207
217
|
check_payload=False,
|
218
|
+
keys_to_check=["error"],
|
208
219
|
)
|
209
220
|
self.assertEqual(
|
210
221
|
{"error": "User does not have permission to access this dag"}, schema
|
@@ -41,6 +41,23 @@ class TestCheckToken(CheckTokenTestCase.TokenEndpoint):
|
|
41
41
|
self.assertEqual(200, self.response.status_code)
|
42
42
|
self.assertEqual(1, self.response.json["valid"])
|
43
43
|
|
44
|
+
def test_token_duration(self):
|
45
|
+
durations = [0.000000000001, 1]
|
46
|
+
asserts = [0, 1]
|
47
|
+
payload = self.data
|
48
|
+
for i in range(2):
|
49
|
+
current_app.config["TOKEN_DURATION"] = durations[i]
|
50
|
+
self.token = self.client.post(
|
51
|
+
LOGIN_URL,
|
52
|
+
data=json.dumps(payload),
|
53
|
+
follow_redirects=True,
|
54
|
+
headers={"Content-Type": "application/json"},
|
55
|
+
).json["token"]
|
56
|
+
|
57
|
+
self.get_check_token()
|
58
|
+
self.assertEqual(200, self.response.status_code)
|
59
|
+
self.assertEqual(asserts[i], self.response.json["valid"])
|
60
|
+
|
44
61
|
def test_get_invalid_token(self):
|
45
62
|
self.token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2Mzk4MjAwNzMsImlhdCI6MTYzOTczMzY3Mywic3ViIjoxfQ"
|
46
63
|
self.token += ".KzAYFDSrAJoCrnxGqKL2v6fE3oxT2muBgYztF1wcuN8"
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import json
|
2
2
|
|
3
|
+
from flask import current_app
|
3
4
|
from flask_testing import TestCase
|
5
|
+
from datetime import datetime, timedelta
|
4
6
|
from cornflow.app import create_app
|
5
7
|
from cornflow.commands.access import access_init_command
|
6
8
|
from cornflow.commands.dag import register_deployed_dags_command_test
|
@@ -359,6 +361,20 @@ class TestUserEndpoint(TestCase):
|
|
359
361
|
self.assertEqual(200, response.status_code)
|
360
362
|
self.assertIsNotNone(response.json["token"])
|
361
363
|
|
364
|
+
def test_change_password_rotation(self):
|
365
|
+
current_app.config["PWD_ROTATION_TIME"] = 1 # in days
|
366
|
+
payload = {"pwd_last_change": (datetime.utcnow() - timedelta(days=2)).strftime("%Y-%m-%dT%H:%M:%SZ")}
|
367
|
+
self.modify_info(self.planner, self.planner, payload)
|
368
|
+
response = self.log_in(self.planner)
|
369
|
+
self.assertEqual(True, response.json["change_password"])
|
370
|
+
|
371
|
+
payload = {"password": "Newtestpassword1!"}
|
372
|
+
self.modify_info(self.planner, self.planner, payload)
|
373
|
+
self.planner.update(payload)
|
374
|
+
print(self.planner)
|
375
|
+
response = self.log_in(self.planner)
|
376
|
+
self.assertEqual(False, response.json["change_password"])
|
377
|
+
|
362
378
|
|
363
379
|
class TestUserModel(TestCase):
|
364
380
|
def create_app(self):
|