diff --git a/src/api-service/__app__/onefuzzlib/orm.py b/src/api-service/__app__/onefuzzlib/orm.py index e89203590..436ecab6f 100644 --- a/src/api-service/__app__/onefuzzlib/orm.py +++ b/src/api-service/__app__/onefuzzlib/orm.py @@ -37,7 +37,7 @@ from onefuzztypes.enums import ( ) from onefuzztypes.models import Error, SecretData from onefuzztypes.primitives import Container, PoolName, Region -from pydantic import BaseModel, Field +from pydantic import BaseModel from typing_extensions import Protocol from .azure.table import get_client @@ -219,8 +219,9 @@ class ModelMixin(BaseModel): return result +# NOTE: if you want to include Timestamp in a model that uses ORMMixin, +# it must be maintained as part of the model. class ORMMixin(ModelMixin): - Timestamp: Optional[datetime] = Field(alias="Timestamp") etag: Optional[str] @classmethod @@ -257,7 +258,7 @@ class ORMMixin(ModelMixin): return None def export_exclude(self) -> Optional[MappingIntStrAny]: - return {"etag": ..., "Timestamp": ...} + return {"etag": ...} def telemetry_include(self) -> Optional[MappingIntStrAny]: return {} diff --git a/src/api-service/__app__/onefuzzlib/proxy.py b/src/api-service/__app__/onefuzzlib/proxy.py index 24b7daa29..5d062454e 100644 --- a/src/api-service/__app__/onefuzzlib/proxy.py +++ b/src/api-service/__app__/onefuzzlib/proxy.py @@ -42,6 +42,7 @@ PROXY_LOG_PREFIX = "scaleset-proxy: " # This isn't intended to ever be shared to the client, hence not being in # onefuzztypes class Proxy(ORMMixin): + timestamp: Optional[datetime.datetime] = Field(alias="Timestamp") region: Region state: VmState = Field(default=VmState.init) auth: Authentication = Field(default_factory=build_auth) @@ -179,12 +180,12 @@ class Proxy(ORMMixin): ) return False - elif not self.heartbeat and self.Timestamp and self.Timestamp < ten_minutes_ago: + elif not self.heartbeat and self.timestamp and self.timestamp < ten_minutes_ago: logging.error( PROXY_LOG_PREFIX + "no heartbeat in the last 10 minutes: " "%s timestamp: %s compared_to:%s", self.region, - self.Timestamp, + self.timestamp, ten_minutes_ago, ) return False diff --git a/src/api-service/__app__/onefuzzlib/task_event.py b/src/api-service/__app__/onefuzzlib/task_event.py index 463a731fc..e67b85043 100644 --- a/src/api-service/__app__/onefuzzlib/task_event.py +++ b/src/api-service/__app__/onefuzzlib/task_event.py @@ -17,12 +17,12 @@ class TaskEvent(BASE_TASK_EVENT, ORMMixin): @classmethod def get_summary(cls, task_id: UUID) -> List[TaskEventSummary]: events = cls.search(query={"task_id": [task_id]}) - # handle None case of Optional[e.Timestamp], which shouldn't happen - events.sort(key=lambda e: e.Timestamp or datetime.datetime.max) + # handle None case of Optional[e.timestamp], which shouldn't happen + events.sort(key=lambda e: e.timestamp or datetime.datetime.max) return [ TaskEventSummary( - timestamp=e.Timestamp, + timestamp=e.timestamp, event_data=get_event_data(e.event_data), event_type=get_event_type(e.event_data), ) diff --git a/src/pytypes/onefuzztypes/models.py b/src/pytypes/onefuzztypes/models.py index e54206791..f701a6a9a 100644 --- a/src/pytypes/onefuzztypes/models.py +++ b/src/pytypes/onefuzztypes/models.py @@ -535,6 +535,7 @@ class JobTaskInfo(BaseModel): class Job(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") job_id: UUID = Field(default_factory=uuid4) state: JobState = Field(default=JobState.init) config: JobConfig @@ -557,6 +558,7 @@ class NodeHeartbeatEntry(BaseModel): class Node(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") pool_name: PoolName machine_id: UUID state: NodeState = Field(default=NodeState.init) @@ -620,6 +622,7 @@ class AutoScaleConfig(BaseModel): class Pool(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") name: PoolName pool_id: UUID = Field(default_factory=uuid4) os: OS @@ -647,6 +650,7 @@ class ScalesetNodeState(BaseModel): class Scaleset(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") pool_name: PoolName scaleset_id: UUID = Field(default_factory=uuid4) state: ScalesetState = Field(default=ScalesetState.init) @@ -676,6 +680,7 @@ class NotificationConfig(BaseModel): class Repro(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") vm_id: UUID = Field(default_factory=uuid4) task_id: UUID config: ReproConfig @@ -795,6 +800,7 @@ class NodeCommandEnvelope(BaseModel): class TaskEvent(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") task_id: UUID machine_id: UUID event_data: WorkerEvent @@ -813,6 +819,7 @@ class NodeAssignment(BaseModel): class Task(BaseModel): + timestamp: Optional[datetime] = Field(alias="Timestamp") job_id: UUID task_id: UUID = Field(default_factory=uuid4) state: TaskState = Field(default=TaskState.init) diff --git a/src/pytypes/onefuzztypes/webhooks.py b/src/pytypes/onefuzztypes/webhooks.py index 1ad661bc3..6f18a2ce5 100644 --- a/src/pytypes/onefuzztypes/webhooks.py +++ b/src/pytypes/onefuzztypes/webhooks.py @@ -3,6 +3,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. +from datetime import datetime from typing import List, Optional from uuid import UUID, uuid4 @@ -17,6 +18,7 @@ class WebhookMessage(EventMessage): class WebhookMessageLog(WebhookMessage): + timestamp: Optional[datetime] = Field(alias="Timestamp") state: WebhookMessageState = Field(default=WebhookMessageState.queued) try_count: int = Field(default=0)