Skip to content

Commit e6505e7

Browse files
committed
Add run_pattern_instance_task
Signed-off-by: Alina Buzachis <[email protected]>
1 parent c585836 commit e6505e7

File tree

9 files changed

+991
-0
lines changed

9 files changed

+991
-0
lines changed

core/task_runner.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import json
22
import logging
33
import os
4+
from contextlib import closing
45

6+
from core.utils.controller import assign_execute_roles
57
from core.utils.controller import build_collection_uri
8+
from core.utils.controller import create_execution_environment
9+
from core.utils.controller import create_job_templates
10+
from core.utils.controller import create_labels
11+
from core.utils.controller import create_project
612
from core.utils.controller import download_collection
13+
from core.utils.controller import get_http_session
14+
from core.utils.controller import save_instance_state
715

816
from .models import Pattern
17+
from .models import PatternInstance
918
from .models import Task
1019

1120
logger = logging.getLogger(__name__)
@@ -55,3 +64,35 @@ def run_pattern_task(pattern_id: int, task_id: int) -> None:
5564
error_message = f"An unexpected error occurred {str(e)}."
5665
logger.exception(f"Task {task_id} failed unexpectedly.")
5766
task.mark_failed({"error": error_message})
67+
68+
69+
def run_pattern_instance_task(instance_id: int, task_id: int) -> None:
70+
task = Task.objects.get(id=task_id)
71+
try:
72+
instance = PatternInstance.objects.select_related("pattern").get(id=instance_id)
73+
pattern = instance.pattern
74+
pattern_def = pattern.pattern_definition
75+
76+
if not pattern_def:
77+
raise ValueError("Pattern definition is missing.")
78+
79+
# Create a single session for all AAP calls
80+
with closing(get_http_session()) as session:
81+
task.mark_running({"info": "Creating controller project"})
82+
project_id = create_project(session, instance, pattern)
83+
task.mark_running({"info": "Creating execution environment"})
84+
ee_id = create_execution_environment(session, instance, pattern_def)
85+
task.mark_running({"info": "Creating labels"})
86+
labels = create_labels(session, instance, pattern_def)
87+
task.mark_running({"info": "Creating job templates"})
88+
automations = create_job_templates(
89+
session, instance, pattern_def, project_id, ee_id
90+
)
91+
task.mark_running({"info": "Saving instance"})
92+
save_instance_state(instance, project_id, ee_id, labels, automations)
93+
task.mark_running({"info": "Assigning roles"})
94+
assign_execute_roles(session, instance.executors, automations)
95+
task.mark_completed({"info": "PatternInstance processed"})
96+
except Exception as e:
97+
logger.exception("Failed to process PatternInstance.")
98+
task.mark_failed({"error": str(e)})

core/tests/test_controller_client.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
from unittest.mock import MagicMock
2+
from unittest.mock import patch
3+
4+
import pytest
5+
import requests
6+
17
import core.utils.controller.client as cc
28

39

@@ -6,3 +12,49 @@ def test_get_http_session():
612
s1 = cc.get_http_session()
713
s2 = cc.get_http_session()
814
assert s1 is not s2
15+
16+
17+
def _fake_response(status_code: int, payload: dict | list) -> requests.Response:
18+
"""Return a Response-like mock that behaves for raise_for_status/json."""
19+
resp = MagicMock(spec=requests.Response)
20+
resp.status_code = status_code
21+
resp.json.return_value = payload
22+
23+
if 400 <= status_code < 600:
24+
http_error = requests.HTTPError(response=resp)
25+
resp.raise_for_status.side_effect = http_error
26+
else:
27+
resp.raise_for_status.return_value = None
28+
return resp
29+
30+
31+
@patch("core.utils.controller.client.get_http_session")
32+
def test_post_non_400_error_is_propagated(mock_get_http_session):
33+
"""
34+
Test that a non-400 error is also immediately propagated.
35+
"""
36+
session = MagicMock()
37+
session.post.return_value = _fake_response(500, {"error": "server"})
38+
mock_get_http_session.return_value = session
39+
40+
with pytest.raises(requests.HTTPError):
41+
cc.post(session, "/labels/", {"name": "foo"})
42+
43+
session.get.assert_not_called()
44+
session.post.assert_called_once()
45+
46+
47+
@patch("core.utils.controller.client.get_http_session")
48+
def test_post_success(mock_get_http_session):
49+
"""
50+
Test that a successful POST request returns the JSON response.
51+
"""
52+
session = MagicMock()
53+
session.post.return_value = _fake_response(201, {"id": 123, "name": "foo"})
54+
mock_get_http_session.return_value = session
55+
56+
out = cc.post(session, "/labels/", {"name": "foo"})
57+
assert out == {"id": 123, "name": "foo"}
58+
59+
session.get.assert_not_called()
60+
session.post.assert_called_once()

0 commit comments

Comments
 (0)