Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ PYTEST_ADMIN_PASSWORD=start123
PYTEST_DEFAULT_MASTER_IMAGE=python/base
PYTEST_ASYNC_MAX_RETRIES=5
PYTEST_ASYNC_RETRY_DELAY_MILLIS=500
PYTEST_HUB_VERSION=0.8.19
PYTEST_HUB_VERSION=0.8.21
32 changes: 23 additions & 9 deletions flame_hub/_core_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,7 @@ class Log(BaseModel):
labels: dict[str, str | None]


AnalysisBuildStatus = t.Literal["starting", "started", "stopping", "stopped", "finished", "failed"]
AnalysisRunStatus = t.Literal["starting", "started", "running", "stopping", "stopped", "finished", "failed"]
ProcessStatus = t.Literal["starting", "started", "stopping", "stopped", "finished", "failed"]


class CreateAnalysis(BaseModel):
Expand All @@ -234,10 +233,17 @@ class CreateAnalysis(BaseModel):

class Analysis(CreateAnalysis):
id: uuid.UUID
configuration_locked: bool
nodes: int
build_status: AnalysisBuildStatus | None
run_status: AnalysisRunStatus | None
configuration_locked: bool
configuration_entrypoint_valid: bool
configuration_image_valid: bool
configuration_node_aggregator_valid: bool
configuration_node_default_valid: bool
configuration_nodes_valid: bool
build_status: ProcessStatus | None
execution_status: ProcessStatus | None
distribution_status: ProcessStatus | None
execution_progress: int | None
created_at: datetime
updated_at: datetime
registry: t.Annotated[Registry | None, IsIncludable] = None
Expand Down Expand Up @@ -278,7 +284,8 @@ class CreateAnalysisNode(BaseModel):
class AnalysisNode(CreateAnalysisNode):
id: uuid.UUID
approval_status: AnalysisNodeApprovalStatus | None
run_status: AnalysisNodeRunStatus | None
execution_status: ProcessStatus | None
execution_progress: int | None
comment: str | None
artifact_tag: str | None
artifact_digest: str | None
Expand All @@ -293,7 +300,8 @@ class AnalysisNode(CreateAnalysisNode):
class UpdateAnalysisNode(BaseModel):
comment: str | None | UNSET_T = UNSET
approval_status: AnalysisNodeApprovalStatus | None | UNSET_T = UNSET
run_status: AnalysisNodeRunStatus | None | UNSET_T = UNSET
execution_status: ProcessStatus | None | UNSET_T = UNSET
execution_progress: int | None | UNSET_T = UNSET


class CreateAnalysisNodeLog(BaseModel):
Expand Down Expand Up @@ -610,11 +618,17 @@ def update_analysis_node(
analysis_node_id: AnalysisNode | uuid.UUID | str,
comment: str | None | UNSET_T = UNSET,
approval_status: AnalysisNodeApprovalStatus | None | UNSET_T = UNSET,
run_status: AnalysisNodeRunStatus | None | UNSET_T = UNSET,
execution_status: ProcessStatus | None | UNSET_T = UNSET,
execution_progress: int | None | UNSET_T = UNSET,
) -> AnalysisNode:
return self._update_resource(
AnalysisNode,
UpdateAnalysisNode(comment=comment, approval_status=approval_status, run_status=run_status),
UpdateAnalysisNode(
comment=comment,
approval_status=approval_status,
execution_status=execution_status,
execution_progress=execution_progress,
),
"analysis-nodes",
analysis_node_id,
)
Expand Down
4 changes: 0 additions & 4 deletions flame_hub/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
"UpdateProject",
"ProjectNodeApprovalStatus",
"ProjectNode",
"AnalysisBuildStatus",
"AnalysisRunStatus",
"CreateAnalysis",
"Analysis",
"UpdateAnalysis",
Expand Down Expand Up @@ -85,8 +83,6 @@
ProjectNodeApprovalStatus,
CreateProjectNode,
ProjectNode,
AnalysisBuildStatus,
AnalysisRunStatus,
CreateAnalysis,
Analysis,
UpdateAnalysis,
Expand Down
6 changes: 2 additions & 4 deletions flame_hub/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
"RegistryProjectType",
"MasterImageCommandArgument",
"ProjectNodeApprovalStatus",
"AnalysisBuildStatus",
"AnalysisRunStatus",
"ProcessStatus",
"AnalysisCommand",
"AnalysisNodeApprovalStatus",
"AnalysisNodeRunStatus",
Expand Down Expand Up @@ -44,8 +43,7 @@
RegistryProjectType,
MasterImageCommandArgument,
ProjectNodeApprovalStatus,
AnalysisBuildStatus,
AnalysisRunStatus,
ProcessStatus,
AnalysisCommand,
AnalysisNodeApprovalStatus,
AnalysisNodeRunStatus,
Expand Down
7 changes: 7 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,12 @@ def next_random_string(charset=string.ascii_letters, length: int = 20):
return "".join([random.choice(charset) for _ in range(length)])


def next_random_number(lower=0, upper=1, is_int=False):
if is_int:
return random.randint(lower, upper)
else:
return random.uniform(lower, upper)


def next_uuid():
return str(uuid.uuid4())
36 changes: 28 additions & 8 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
AnalysisBucket,
AnalysisBucketFile,
)
from tests.helpers import next_random_string, next_uuid, assert_eventually
from tests.helpers import next_random_string, next_uuid, assert_eventually, next_random_number

pytestmark = pytest.mark.integration

Expand Down Expand Up @@ -174,7 +174,7 @@ def analysis_bucket_file_includables():

@pytest.fixture()
def configured_analysis(core_client, registry, analysis, master_realm, analysis_bucket_file):
# An analysis needs at least one default and one aggregator node.
# An analysis needs at least one default node, one aggregator node, a base image and an entrypoint to be lockable.
nodes = []
for node_type in t.get_args(NodeType):
new_node = core_client.create_node(
Expand All @@ -186,8 +186,22 @@ def configured_analysis(core_client, registry, analysis, master_realm, analysis_
nodes.append(new_node)
core_client.create_project_node(analysis.project_id, new_node)
core_client.create_analysis_node(analysis, new_node)
core_client.send_analysis_command(analysis.id, command="configurationLock")
return analysis

# It takes some time until an analysis is lockable.
def _check_analysis_lockable():
try:
core_client.send_analysis_command(analysis.id, command="configurationLock")
except HubAPIError as e:
assert False, e
else:
assert True

assert_eventually(_check_analysis_lockable)

yield analysis

for node in nodes:
core_client.delete_node(node)


@pytest.fixture()
Expand Down Expand Up @@ -417,16 +431,22 @@ def test_build_status_analysis(core_client, configured_analysis):

def _check_checking_event_in_logs():
logs = core_client.find_analysis_logs(filter={"analysis_id": configured_analysis.id})
assert "checking" in [log.labels.get("event", None) for log in logs]
assert "configured" in [log.labels.get("event", None) for log in logs]

assert_eventually(_check_checking_event_in_logs)


def test_analysis_node_update(core_client, analysis_node):
new_analysis_node = core_client.update_analysis_node(analysis_node.id, run_status="starting")
def test_update_analysis_node(core_client, analysis_node):
progress = next_random_number(upper=100, is_int=True)
new_analysis_node = core_client.update_analysis_node(
analysis_node.id,
execution_status="starting",
execution_progress=progress,
)

assert analysis_node != new_analysis_node
assert new_analysis_node.run_status == "starting"
assert new_analysis_node.execution_status == "starting"
assert new_analysis_node.execution_progress == progress


def test_get_analysis_nodes(core_client, analysis_node, analysis_node_includables):
Expand Down