-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathresource.py
More file actions
123 lines (99 loc) · 4 KB
/
Copy pathresource.py
File metadata and controls
123 lines (99 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
122
123
# Copyright IBM Corporation 2025, 2026
# SPDX-License-Identifier: MIT
import enum
import typing
import uuid
from typing import Annotated
import pydantic
from orchestrator.core.metadata import PackageProvenance
from orchestrator.core.operation.config import (
DiscoveryOperationEnum,
DiscoveryOperationResourceConfiguration,
)
from orchestrator.core.resources import (
ADOResource,
ADOResourceEventEnum,
ADOResourceStatus,
CoreResourceKinds,
)
class OperationResourceEventEnum(enum.Enum):
"""Additional events in OperationResource lifecycle"""
STARTED = "started"
FINISHED = "finished"
class OperationExitStateEnum(enum.Enum):
"""Enumerates the possible exit-states of an operation when it finishes"""
SUCCESS = "success" # The operation returned with success
FAIL = "fail" # The operation returned with failure
ERROR = "error" # Some exception was raised during operation
class OperationResourceStatus(ADOResourceStatus):
"""Records information on the status of an operation resource - a life-cycle event that occurred or an exit status"""
event: Annotated[
ADOResourceEventEnum | OperationResourceEventEnum,
pydantic.Field(
description="An event that happened to an operation resource: created, added, started, finished, updated"
),
] = None
exit_state: Annotated[
OperationExitStateEnum | None,
pydantic.Field(
description="The exit state of the operation: success, failed, error. Only can be set if on a FINISHED event"
),
] = None
@pydantic.model_validator(mode="after")
def check_status(self) -> "OperationResourceStatus":
if self.exit_state and self.event != OperationResourceEventEnum.FINISHED:
raise ValueError(
f"Recording an exit state (here {self.exit_state}) for an operation resource status, "
f"requires recording a corresponding FINISHED event ({self.event} given)"
)
return self
class OperationResource(ADOResource):
version: Annotated[str, pydantic.Field()] = "v1"
kind: Annotated[CoreResourceKinds, pydantic.Field()] = CoreResourceKinds.OPERATION
operationType: Annotated[
DiscoveryOperationEnum, pydantic.Field(description="The type of this operation")
]
operatorIdentifier: Annotated[
str,
pydantic.Field(
description="The id of the operator resource that executed this operation"
),
]
config: DiscoveryOperationResourceConfiguration
status: Annotated[
list[OperationResourceStatus],
pydantic.Field(
default_factory=lambda: [
OperationResourceStatus(event=ADOResourceEventEnum.CREATED)
],
description="A list of status objects",
),
]
operatorProvenance: Annotated[
PackageProvenance | None,
pydantic.Field(
default=None,
description=(
"Python distribution that provided the operator at the time this "
"operation was created. None for operations created before provenance "
"tracking was introduced, or when the distribution could not be resolved."
),
),
]
@pydantic.model_validator(mode="before")
@classmethod
def generate_identifier_if_not_provided(
cls, data: typing.Any # noqa: ANN401
) -> "OperationResource":
if isinstance(data, dict):
# Do not do anything if the identifier is already present
if data.get("identifier", None) is not None:
return data
# Do not attempt to generate anything if operatorIdentifier
# (a required field) has not been provided
if "operatorIdentifier" not in data:
return data
kind = CoreResourceKinds.OPERATION.value
operator_identifier = data["operatorIdentifier"]
data["identifier"] = f"{kind}-{operator_identifier}-{str(uuid.uuid4())[:8]}"
return data