cornflow 1.2.3a5__py3-none-any.whl → 1.3.0rc1__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/app.py +24 -8
- cornflow/cli/service.py +93 -43
- cornflow/commands/auxiliar.py +4 -1
- cornflow/commands/dag.py +7 -7
- cornflow/commands/permissions.py +13 -7
- cornflow/commands/views.py +3 -0
- cornflow/config.py +26 -6
- cornflow/endpoints/__init__.py +27 -0
- cornflow/endpoints/case.py +37 -21
- cornflow/endpoints/dag.py +5 -5
- cornflow/endpoints/data_check.py +8 -7
- cornflow/endpoints/example_data.py +4 -2
- cornflow/endpoints/execution.py +215 -127
- cornflow/endpoints/health.py +30 -11
- cornflow/endpoints/instance.py +3 -3
- cornflow/endpoints/login.py +9 -2
- cornflow/endpoints/permission.py +1 -2
- cornflow/endpoints/schemas.py +3 -3
- cornflow/endpoints/signup.py +17 -11
- cornflow/migrations/versions/999b98e24225.py +34 -0
- cornflow/migrations/versions/cef1df240b27_.py +34 -0
- cornflow/models/__init__.py +2 -1
- cornflow/models/dag.py +8 -9
- cornflow/models/dag_permissions.py +3 -3
- cornflow/models/execution.py +2 -3
- cornflow/models/permissions.py +1 -0
- cornflow/models/user.py +1 -1
- cornflow/schemas/execution.py +14 -1
- cornflow/schemas/health.py +1 -1
- cornflow/shared/authentication/auth.py +14 -1
- cornflow/shared/authentication/decorators.py +32 -2
- cornflow/shared/const.py +58 -1
- cornflow/shared/exceptions.py +2 -1
- cornflow/tests/base_test_execution.py +798 -0
- cornflow/tests/const.py +1 -0
- cornflow/tests/integration/test_commands.py +2 -2
- cornflow/tests/integration/test_cornflowclient.py +2 -1
- cornflow/tests/unit/test_apiview.py +7 -1
- cornflow/tests/unit/test_cases.py +1 -1
- cornflow/tests/unit/test_cli.py +6 -3
- cornflow/tests/unit/test_commands.py +7 -6
- cornflow/tests/unit/test_dags.py +3 -3
- cornflow/tests/unit/test_example_data.py +1 -1
- cornflow/tests/unit/test_executions.py +115 -535
- cornflow/tests/unit/test_get_resources.py +103 -0
- cornflow/tests/unit/test_health.py +84 -3
- cornflow/tests/unit/test_main_alarms.py +1 -1
- cornflow/tests/unit/test_roles.py +2 -1
- cornflow/tests/unit/test_schema_from_models.py +1 -1
- cornflow/tests/unit/test_schemas.py +1 -1
- cornflow/tests/unit/test_sign_up.py +181 -6
- cornflow/tests/unit/tools.py +93 -10
- {cornflow-1.2.3a5.dist-info → cornflow-1.3.0rc1.dist-info}/METADATA +3 -3
- {cornflow-1.2.3a5.dist-info → cornflow-1.3.0rc1.dist-info}/RECORD +57 -53
- {cornflow-1.2.3a5.dist-info → cornflow-1.3.0rc1.dist-info}/WHEEL +0 -0
- {cornflow-1.2.3a5.dist-info → cornflow-1.3.0rc1.dist-info}/entry_points.txt +0 -0
- {cornflow-1.2.3a5.dist-info → cornflow-1.3.0rc1.dist-info}/top_level.txt +0 -0
@@ -3,542 +3,122 @@ Unit test for the executions endpoints
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
# Import from libraries
|
6
|
-
import json
|
7
6
|
from unittest.mock import patch
|
8
7
|
|
8
|
+
from cornflow.app import create_app
|
9
|
+
from cornflow.tests import base_test_execution
|
10
|
+
|
9
11
|
# Import from internal modules
|
10
|
-
from cornflow.
|
11
|
-
from cornflow.tests.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
class
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
@patch("cornflow.endpoints.execution.Airflow")
|
122
|
-
def test_new_execution_with_solution_bad(self, af_client_class):
|
123
|
-
patch_af_client(af_client_class)
|
124
|
-
patch_af_client(af_client_class)
|
125
|
-
self.payload["data"] = {"message": "THIS IS NOT A VALID SOLUTION"}
|
126
|
-
response = self.create_new_row(
|
127
|
-
EXECUTION_URL,
|
128
|
-
self.model,
|
129
|
-
payload=self.payload,
|
130
|
-
check_payload=False,
|
131
|
-
expected_status=400,
|
132
|
-
)
|
133
|
-
self.assertIn("error", response)
|
134
|
-
self.assertIn("jsonschema_errors", response)
|
135
|
-
|
136
|
-
def test_new_execution_no_instance(self):
|
137
|
-
payload = dict(self.payload)
|
138
|
-
payload["instance_id"] = "bad_id"
|
139
|
-
response = self.client.post(
|
140
|
-
self.url,
|
141
|
-
data=json.dumps(payload),
|
142
|
-
follow_redirects=True,
|
143
|
-
headers=self.get_header_with_auth(self.token),
|
144
|
-
)
|
145
|
-
self.assertEqual(404, response.status_code)
|
146
|
-
self.assertTrue("error" in response.json)
|
147
|
-
|
148
|
-
def test_get_executions(self):
|
149
|
-
self.get_rows(self.url, self.payloads, keys_to_check=self.keys_to_check)
|
150
|
-
|
151
|
-
def test_get_no_executions(self):
|
152
|
-
self.get_no_rows(self.url)
|
153
|
-
|
154
|
-
def test_get_executions_superadmin(self):
|
155
|
-
self.get_rows(self.url, self.payloads, keys_to_check=self.keys_to_check)
|
156
|
-
token = self.create_service_user()
|
157
|
-
rows = self.client.get(
|
158
|
-
self.url, follow_redirects=True, headers=self.get_header_with_auth(token)
|
159
|
-
)
|
160
|
-
self.assertEqual(len(rows.json), len(self.payloads))
|
161
|
-
|
162
|
-
|
163
|
-
class TestExecutionRelaunchEndpoint(CustomTestCase):
|
164
|
-
def setUp(self):
|
165
|
-
super().setUp()
|
166
|
-
|
167
|
-
with open(INSTANCE_PATH) as f:
|
168
|
-
payload = json.load(f)
|
169
|
-
fk_id = self.create_new_row(INSTANCE_URL, InstanceModel, payload)
|
170
|
-
self.url = EXECUTION_URL_NORUN
|
171
|
-
self.model = ExecutionModel
|
172
|
-
|
173
|
-
def load_file_fk(_file):
|
174
|
-
with open(_file) as f:
|
175
|
-
temp = json.load(f)
|
176
|
-
temp["instance_id"] = fk_id
|
177
|
-
return temp
|
178
|
-
|
179
|
-
self.payload = load_file_fk(EXECUTION_PATH)
|
180
|
-
|
181
|
-
def test_relaunch_execution(self):
|
182
|
-
idx = self.create_new_row(self.url, self.model, payload=self.payload)
|
183
|
-
|
184
|
-
# Add solution checks to see if they are deleted correctly
|
185
|
-
token = self.create_service_user()
|
186
|
-
self.update_row(
|
187
|
-
url=DAG_URL + idx + "/",
|
188
|
-
payload_to_check=dict(),
|
189
|
-
change=dict(solution_schema="_data_checks", checks=dict(check_1=[])),
|
190
|
-
token=token,
|
191
|
-
check_payload=False,
|
192
|
-
)
|
193
|
-
|
194
|
-
url = EXECUTION_URL + idx + "/relaunch/?run=0"
|
195
|
-
self.payload["config"]["warmStart"] = False
|
196
|
-
response = self.client.post(
|
197
|
-
url,
|
198
|
-
data=json.dumps({"config": self.payload["config"]}),
|
199
|
-
follow_redirects=True,
|
200
|
-
headers=self.get_header_with_auth(self.token),
|
201
|
-
)
|
202
|
-
self.assertEqual(201, response.status_code)
|
203
|
-
|
204
|
-
url = EXECUTION_URL + idx + "/data"
|
205
|
-
row = self.client.get(
|
206
|
-
url, follow_redirects=True, headers=self.get_header_with_auth(self.token)
|
207
|
-
).json
|
208
|
-
|
209
|
-
self.assertEqual(row["config"], self.payload["config"])
|
210
|
-
self.assertIsNone(row["checks"])
|
211
|
-
|
212
|
-
@patch("cornflow.endpoints.execution.Airflow")
|
213
|
-
def test_relaunch_execution_run(self, af_client_class):
|
214
|
-
patch_af_client(af_client_class)
|
215
|
-
|
216
|
-
idx = self.create_new_row(self.url, self.model, payload=self.payload)
|
217
|
-
|
218
|
-
# Add solution checks to see if they are deleted correctly
|
219
|
-
token = self.create_service_user()
|
220
|
-
self.update_row(
|
221
|
-
url=DAG_URL + idx + "/",
|
222
|
-
payload_to_check=dict(),
|
223
|
-
change=dict(solution_schema="_data_checks", checks=dict(check_1=[])),
|
224
|
-
token=token,
|
225
|
-
check_payload=False,
|
226
|
-
)
|
227
|
-
|
228
|
-
url = EXECUTION_URL + idx + "/relaunch/"
|
229
|
-
self.payload["config"]["warmStart"] = False
|
230
|
-
response = self.client.post(
|
231
|
-
url,
|
232
|
-
data=json.dumps({"config": self.payload["config"]}),
|
233
|
-
follow_redirects=True,
|
234
|
-
headers=self.get_header_with_auth(self.token),
|
235
|
-
)
|
236
|
-
self.assertEqual(201, response.status_code)
|
237
|
-
|
238
|
-
url = EXECUTION_URL + idx + "/data"
|
239
|
-
row = self.client.get(
|
240
|
-
url, follow_redirects=True, headers=self.get_header_with_auth(self.token)
|
241
|
-
).json
|
242
|
-
|
243
|
-
self.assertEqual(row["config"], self.payload["config"])
|
244
|
-
self.assertIsNone(row["checks"])
|
245
|
-
|
246
|
-
def test_relaunch_invalid_execution(self):
|
247
|
-
idx = "thisIsAnInvalidExecutionId"
|
248
|
-
url = EXECUTION_URL + idx + "/relaunch/?run=0"
|
249
|
-
self.payload["config"]["warmStart"] = False
|
250
|
-
response = self.client.post(
|
251
|
-
url,
|
252
|
-
data=json.dumps({"config": self.payload["config"]}),
|
253
|
-
follow_redirects=True,
|
254
|
-
headers=self.get_header_with_auth(self.token),
|
255
|
-
)
|
256
|
-
self.assertEqual(404, response.status_code)
|
257
|
-
|
258
|
-
|
259
|
-
class TestExecutionsDetailEndpointMock(CustomTestCase):
|
260
|
-
def setUp(self):
|
261
|
-
super().setUp()
|
262
|
-
with open(INSTANCE_PATH) as f:
|
263
|
-
payload = json.load(f)
|
264
|
-
fk_id = self.create_new_row(INSTANCE_URL, InstanceModel, payload)
|
265
|
-
self.model = ExecutionModel
|
266
|
-
self.response_items = {
|
267
|
-
"id",
|
268
|
-
"name",
|
269
|
-
"description",
|
270
|
-
"created_at",
|
271
|
-
"instance_id",
|
272
|
-
"data_hash",
|
273
|
-
"message",
|
274
|
-
"state",
|
275
|
-
"config",
|
276
|
-
"schema",
|
277
|
-
"user_id",
|
278
|
-
"indicators",
|
279
|
-
"username",
|
280
|
-
"updated_at"
|
281
|
-
}
|
282
|
-
# we only check the following because this endpoint does not return data
|
283
|
-
self.items_to_check = ["name", "description"]
|
284
|
-
self.url = EXECUTION_URL
|
285
|
-
with open(EXECUTION_PATH) as f:
|
286
|
-
self.payload = json.load(f)
|
287
|
-
self.payload["instance_id"] = fk_id
|
288
|
-
|
289
|
-
|
290
|
-
class TestExecutionsDetailEndpoint(
|
291
|
-
TestExecutionsDetailEndpointMock, BaseTestCases.DetailEndpoint
|
12
|
+
from cornflow.tests.const import EXECUTION_URL
|
13
|
+
from cornflow.tests.unit.tools import patch_af_client, patch_db_client
|
14
|
+
|
15
|
+
|
16
|
+
class AirflowPatcher:
|
17
|
+
@property
|
18
|
+
def orchestrator_patch_target(self):
|
19
|
+
return "cornflow.endpoints.execution.Airflow"
|
20
|
+
|
21
|
+
@property
|
22
|
+
def orchestrator_patch_fn(self):
|
23
|
+
return patch_af_client
|
24
|
+
|
25
|
+
def create_app(self):
|
26
|
+
return super().create_app()
|
27
|
+
|
28
|
+
|
29
|
+
class DatabricksPatcher:
|
30
|
+
@property
|
31
|
+
def orchestrator_patch_target(self):
|
32
|
+
return "cornflow.endpoints.execution.Databricks"
|
33
|
+
|
34
|
+
@property
|
35
|
+
def orchestrator_patch_fn(self):
|
36
|
+
return patch_db_client
|
37
|
+
|
38
|
+
def create_app(self):
|
39
|
+
app = create_app("testing-databricks")
|
40
|
+
return app
|
41
|
+
|
42
|
+
|
43
|
+
class TestExecutionsListEndpointAirflow(
|
44
|
+
AirflowPatcher, base_test_execution.BaseExecutionList
|
45
|
+
):
|
46
|
+
pass
|
47
|
+
|
48
|
+
|
49
|
+
class TestExecutionsListEndpointDatabricks(
|
50
|
+
DatabricksPatcher, base_test_execution.BaseExecutionList
|
51
|
+
):
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
55
|
+
class TestExecutionRelaunchEndpointAirflow(
|
56
|
+
AirflowPatcher, base_test_execution.BaseExecutionRelaunch
|
57
|
+
):
|
58
|
+
pass
|
59
|
+
|
60
|
+
|
61
|
+
class TestExecutionRelaunchEndpointDatabricks(
|
62
|
+
DatabricksPatcher, base_test_execution.BaseExecutionRelaunch
|
63
|
+
):
|
64
|
+
pass
|
65
|
+
|
66
|
+
|
67
|
+
class TestExecutionsDetailEndpointAirflow(
|
68
|
+
AirflowPatcher, base_test_execution.BaseExecutionDetail
|
69
|
+
):
|
70
|
+
pass
|
71
|
+
|
72
|
+
|
73
|
+
class TestExecutionsDetailEndpointDatabricks(
|
74
|
+
DatabricksPatcher, base_test_execution.BaseExecutionDetail
|
75
|
+
):
|
76
|
+
pass
|
77
|
+
|
78
|
+
|
79
|
+
class TestExecutionsDataEndpointAirflow(
|
80
|
+
AirflowPatcher, base_test_execution.BaseExecutionData
|
81
|
+
):
|
82
|
+
pass
|
83
|
+
|
84
|
+
|
85
|
+
class TestExecutionsDataEndpointDatabricks(
|
86
|
+
DatabricksPatcher, base_test_execution.BaseExecutionData
|
87
|
+
):
|
88
|
+
pass
|
89
|
+
|
90
|
+
|
91
|
+
class TestExecutionsLogEndpointAirflow(
|
92
|
+
AirflowPatcher, base_test_execution.BaseExecutionLog
|
93
|
+
):
|
94
|
+
pass
|
95
|
+
|
96
|
+
|
97
|
+
class TestExecutionsLogEndpointDatabricks(
|
98
|
+
DatabricksPatcher, base_test_execution.BaseExecutionLog
|
99
|
+
):
|
100
|
+
pass
|
101
|
+
|
102
|
+
|
103
|
+
class TestExecutionsModelAirflow(
|
104
|
+
AirflowPatcher, base_test_execution.BaseExecutionModel
|
105
|
+
):
|
106
|
+
pass
|
107
|
+
|
108
|
+
|
109
|
+
class TestExecutionsModelDatabricks(
|
110
|
+
DatabricksPatcher, base_test_execution.BaseExecutionModel
|
111
|
+
):
|
112
|
+
pass
|
113
|
+
|
114
|
+
|
115
|
+
class TestExecutionsStatusEndpointAirflow(
|
116
|
+
AirflowPatcher, base_test_execution.BaseExecutionStatus
|
117
|
+
):
|
118
|
+
pass
|
119
|
+
|
120
|
+
|
121
|
+
class TestExecutionsStatusEndpointDatabricks(
|
122
|
+
DatabricksPatcher, base_test_execution.BaseExecutionStatus
|
292
123
|
):
|
293
|
-
|
294
|
-
super().setUp()
|
295
|
-
self.query_arguments = {"run": 0}
|
296
|
-
|
297
|
-
# TODO: this test should be moved as it is not using the detail endpoint
|
298
|
-
def test_incomplete_payload2(self):
|
299
|
-
payload = {"description": "arg", "instance_id": self.payload["instance_id"]}
|
300
|
-
response = self.create_new_row(
|
301
|
-
self.url + "?run=0",
|
302
|
-
self.model,
|
303
|
-
payload,
|
304
|
-
expected_status=400,
|
305
|
-
check_payload=False,
|
306
|
-
)
|
307
|
-
|
308
|
-
def test_create_delete_instance_load(self):
|
309
|
-
idx = self.create_new_row(self.url + "?run=0", self.model, self.payload)
|
310
|
-
keys_to_check = [
|
311
|
-
"message",
|
312
|
-
"id",
|
313
|
-
"schema",
|
314
|
-
"data_hash",
|
315
|
-
"config",
|
316
|
-
"instance_id",
|
317
|
-
"user_id",
|
318
|
-
"indicators",
|
319
|
-
"description",
|
320
|
-
"name",
|
321
|
-
"created_at",
|
322
|
-
"state",
|
323
|
-
"username",
|
324
|
-
"updated_at"
|
325
|
-
]
|
326
|
-
execution = self.get_one_row(
|
327
|
-
self.url + idx,
|
328
|
-
payload={**self.payload, **dict(id=idx)},
|
329
|
-
keys_to_check=keys_to_check,
|
330
|
-
)
|
331
|
-
self.delete_row(self.url + idx + "/")
|
332
|
-
keys_to_check = [
|
333
|
-
"id",
|
334
|
-
"schema",
|
335
|
-
"description",
|
336
|
-
"name",
|
337
|
-
"user_id",
|
338
|
-
"executions",
|
339
|
-
"created_at",
|
340
|
-
"data_hash",
|
341
|
-
]
|
342
|
-
instance = self.get_one_row(
|
343
|
-
INSTANCE_URL + execution["instance_id"] + "/",
|
344
|
-
payload={},
|
345
|
-
expected_status=200,
|
346
|
-
check_payload=False,
|
347
|
-
keys_to_check=keys_to_check,
|
348
|
-
)
|
349
|
-
executions = [execution["id"] for execution in instance["executions"]]
|
350
|
-
self.assertFalse(idx in executions)
|
351
|
-
|
352
|
-
def test_delete_instance_deletes_execution(self):
|
353
|
-
# we create a new instance
|
354
|
-
with open(INSTANCE_PATH) as f:
|
355
|
-
payload = json.load(f)
|
356
|
-
fk_id = self.create_new_row(INSTANCE_URL, InstanceModel, payload)
|
357
|
-
payload = {**self.payload, **dict(instance_id=fk_id)}
|
358
|
-
# we create an execution for that instance
|
359
|
-
idx = self.create_new_row(self.url + "?run=0", self.model, payload)
|
360
|
-
self.get_one_row(self.url + idx, payload={**self.payload, **dict(id=idx)})
|
361
|
-
# we delete the new instance
|
362
|
-
self.delete_row(INSTANCE_URL + fk_id + "/")
|
363
|
-
# we check the execution does not exist
|
364
|
-
self.get_one_row(
|
365
|
-
self.url + idx, payload={}, expected_status=404, check_payload=False
|
366
|
-
)
|
367
|
-
|
368
|
-
def test_update_one_row_data(self):
|
369
|
-
idx = self.create_new_row(
|
370
|
-
self.url_with_query_arguments(), self.model, self.payload
|
371
|
-
)
|
372
|
-
with open(INSTANCE_PATH) as f:
|
373
|
-
payload = json.load(f)
|
374
|
-
payload["data"]["parameters"]["name"] = "NewName"
|
375
|
-
|
376
|
-
url = self.url + str(idx) + "/"
|
377
|
-
payload = {
|
378
|
-
**self.payload,
|
379
|
-
**dict(id=idx, name="new_name", data=payload["data"]),
|
380
|
-
}
|
381
|
-
self.update_row(
|
382
|
-
url,
|
383
|
-
dict(name="new_name", data=payload["data"]),
|
384
|
-
payload,
|
385
|
-
)
|
386
|
-
|
387
|
-
url += "data/"
|
388
|
-
row = self.client.get(
|
389
|
-
url, follow_redirects=True, headers=self.get_header_with_auth(self.token)
|
390
|
-
)
|
391
|
-
|
392
|
-
self.assertEqual(row.json["checks"], None)
|
393
|
-
|
394
|
-
@patch("cornflow.endpoints.execution.Airflow")
|
395
|
-
def test_stop_execution(self, af_client_class):
|
396
|
-
patch_af_client(af_client_class)
|
397
|
-
|
398
|
-
idx = self.create_new_row(EXECUTION_URL, self.model, payload=self.payload)
|
399
|
-
|
400
|
-
response = self.client.post(
|
401
|
-
self.url + str(idx) + "/",
|
402
|
-
follow_redirects=True,
|
403
|
-
headers=self.get_header_with_auth(self.token),
|
404
|
-
)
|
405
|
-
|
406
|
-
self.assertEqual(200, response.status_code)
|
407
|
-
self.assertEqual(response.json["message"], "The execution has been stopped")
|
408
|
-
|
409
|
-
|
410
|
-
class TestExecutionsDataEndpoint(TestExecutionsDetailEndpointMock):
|
411
|
-
def setUp(self):
|
412
|
-
super().setUp()
|
413
|
-
self.response_items = {"id", "name", "data"}
|
414
|
-
self.items_to_check = ["name"]
|
415
|
-
self.keys_to_check = [
|
416
|
-
"created_at",
|
417
|
-
"checks",
|
418
|
-
"instance_id",
|
419
|
-
"schema",
|
420
|
-
"data",
|
421
|
-
"user_id",
|
422
|
-
"message",
|
423
|
-
"data_hash",
|
424
|
-
"log",
|
425
|
-
"config",
|
426
|
-
"description",
|
427
|
-
"state",
|
428
|
-
"name",
|
429
|
-
"id",
|
430
|
-
]
|
431
|
-
|
432
|
-
def test_get_one_execution(self):
|
433
|
-
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
434
|
-
self.url = EXECUTION_URL + idx + "/data/"
|
435
|
-
payload = dict(self.payload)
|
436
|
-
payload["id"] = idx
|
437
|
-
self.get_one_row(self.url, payload, keys_to_check=self.keys_to_check)
|
438
|
-
|
439
|
-
def test_get_one_execution_superadmin(self):
|
440
|
-
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
441
|
-
payload = dict(self.payload)
|
442
|
-
payload["id"] = idx
|
443
|
-
token = self.create_service_user()
|
444
|
-
self.get_one_row(
|
445
|
-
EXECUTION_URL + idx + "/data/",
|
446
|
-
payload,
|
447
|
-
token=token,
|
448
|
-
keys_to_check=self.keys_to_check,
|
449
|
-
)
|
450
|
-
|
451
|
-
|
452
|
-
class TestExecutionsLogEndpoint(TestExecutionsDetailEndpointMock):
|
453
|
-
def setUp(self):
|
454
|
-
super().setUp()
|
455
|
-
self.response_items = {"id", "name", "log", "indicators"}
|
456
|
-
self.items_to_check = ["name"]
|
457
|
-
self.keys_to_check = [
|
458
|
-
"created_at",
|
459
|
-
"id",
|
460
|
-
"log_text",
|
461
|
-
"instance_id",
|
462
|
-
"state",
|
463
|
-
"message",
|
464
|
-
"description",
|
465
|
-
"data_hash",
|
466
|
-
"name",
|
467
|
-
"log",
|
468
|
-
"schema",
|
469
|
-
"user_id",
|
470
|
-
"config",
|
471
|
-
"indicators",
|
472
|
-
"username",
|
473
|
-
"updated_at"
|
474
|
-
]
|
475
|
-
|
476
|
-
def test_get_one_execution(self):
|
477
|
-
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
478
|
-
payload = dict(self.payload)
|
479
|
-
payload["id"] = idx
|
480
|
-
self.get_one_row(
|
481
|
-
EXECUTION_URL + idx + "/log/", payload, keys_to_check=self.keys_to_check
|
482
|
-
)
|
483
|
-
|
484
|
-
def test_get_one_execution_superadmin(self):
|
485
|
-
idx = self.create_new_row(EXECUTION_URL_NORUN, self.model, self.payload)
|
486
|
-
payload = dict(self.payload)
|
487
|
-
payload["id"] = idx
|
488
|
-
token = self.create_service_user()
|
489
|
-
self.get_one_row(
|
490
|
-
EXECUTION_URL + idx + "/log/",
|
491
|
-
payload,
|
492
|
-
token=token,
|
493
|
-
keys_to_check=self.keys_to_check,
|
494
|
-
)
|
495
|
-
|
496
|
-
|
497
|
-
class TestExecutionsStatusEndpoint(TestExecutionsDetailEndpointMock):
|
498
|
-
def setUp(self):
|
499
|
-
super().setUp()
|
500
|
-
self.response_items = {"id", "name", "status"}
|
501
|
-
self.items_to_check = []
|
502
|
-
|
503
|
-
@patch("cornflow.endpoints.execution.Airflow")
|
504
|
-
def test_get_one_status(self, af_client_class):
|
505
|
-
patch_af_client(af_client_class)
|
506
|
-
|
507
|
-
idx = self.create_new_row(EXECUTION_URL, self.model, self.payload)
|
508
|
-
payload = dict(self.payload)
|
509
|
-
payload["id"] = idx
|
510
|
-
keys_to_check = ["state", "message", "id", "data_hash"]
|
511
|
-
data = self.get_one_row(
|
512
|
-
EXECUTION_URL + idx + "/status/",
|
513
|
-
payload,
|
514
|
-
check_payload=False,
|
515
|
-
keys_to_check=keys_to_check,
|
516
|
-
)
|
517
|
-
self.assertEqual(data["state"], 1)
|
518
|
-
|
519
|
-
@patch("cornflow.endpoints.execution.Airflow")
|
520
|
-
def test_put_one_status(self, af_client_class):
|
521
|
-
patch_af_client(af_client_class)
|
522
|
-
|
523
|
-
idx = self.create_new_row(EXECUTION_URL, self.model, self.payload)
|
524
|
-
payload = dict(self.payload)
|
525
|
-
payload["id"] = idx
|
526
|
-
response = self.client.put(
|
527
|
-
EXECUTION_URL + idx + "/status/",
|
528
|
-
data=json.dumps({"status": 0}),
|
529
|
-
follow_redirects=True,
|
530
|
-
headers=self.get_header_with_auth(self.token),
|
531
|
-
)
|
532
|
-
|
533
|
-
self.assertEqual(200, response.status_code)
|
534
|
-
self.assertEqual(f"execution {idx} updated correctly", response.json["message"])
|
535
|
-
|
536
|
-
|
537
|
-
class TestExecutionsModel(TestExecutionsDetailEndpointMock):
|
538
|
-
def test_repr_method(self):
|
539
|
-
idx = self.create_new_row(self.url + "?run=0", self.model, self.payload)
|
540
|
-
self.repr_method(idx, f"<Execution {idx}>")
|
541
|
-
|
542
|
-
def test_str_method(self):
|
543
|
-
idx = self.create_new_row(self.url + "?run=0", self.model, self.payload)
|
544
|
-
self.str_method(idx, f"<Execution {idx}>")
|
124
|
+
pass
|