Skip to content

Commit 5a3af45

Browse files
authored
Merge pull request #13 from yasun1/last_updated_at
Standardize AdapterStatus Timestamp 'last_updated_at' Naming
2 parents 21c9c77 + 6629552 commit 5a3af45

6 files changed

Lines changed: 245 additions & 285 deletions

File tree

models/clusters/model.tsp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ model ClusterStatus {
5252

5353
/** Time of the last update
5454
* Updated when conditions are reported.
55-
* Most recent `last_updated_time` from the conditions
55+
* Computed as min(conditions[].last_updated_time) to detect stale adapters.
56+
* Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting.
5657
*/
5758
@format("date-time") last_updated_time: string;
5859

59-
conditions: Condition[];
60+
conditions: ResourceCondition[];
6061
}
6162

6263
@example(exampleCluster)

models/nodepools/model.tsp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ model NodePoolStatus {
4545

4646
/** Time of the last update
4747
* Updated when conditions are reported.
48-
* Most recent `last_updated_time` from the conditions
48+
* Computed as min(conditions[].last_updated_time) to detect stale adapters.
49+
* Uses earliest (not latest) timestamp to ensure Sentinel can detect if any adapter has stopped reporting.
4950
*/
5051
@format("date-time") last_updated_time: string;
5152

52-
conditions: Condition[];
53+
conditions: ResourceCondition[];
5354
}
5455

5556
@example(exampleNodePool)

models/statuses/example_adapter_status.tsp

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,20 @@ const exampleAdapterStatus: AdapterStatus = (#{
1010
status: "True",
1111
reason: "All validations passed",
1212
message: "All 30 validation tests passed",
13-
observed_generation: 1,
14-
created_time: "2021-01-01T10:00:00Z",
15-
last_updated_time: "2021-01-01T10:00:00Z",
1613
last_transition_time: "2021-01-01T10:00:00Z",
1714
},
1815
#{
1916
type: "Applied",
2017
status: "True",
2118
reason: "Validation job applied",
2219
message: "Validation job applied successfully",
23-
observed_generation: 1,
24-
created_time: "2021-01-01T10:00:00Z",
25-
last_updated_time: "2021-01-01T10:00:00Z",
2620
last_transition_time: "2021-01-01T10:00:00Z",
2721
},
2822
#{
2923
type: "Health",
3024
status: "True",
3125
reason: "Validation job healthy",
3226
message: "Validation job is healthy",
33-
observed_generation: 1,
34-
created_time: "2021-01-01T10:00:00Z",
35-
last_updated_time: "2021-01-01T10:00:00Z",
3627
last_transition_time: "2021-01-01T10:00:00Z",
3728
}
3829
],
@@ -52,37 +43,32 @@ const exampleAdapterStatus: AdapterStatus = (#{
5243
},
5344
},
5445
created_time: "2021-01-01T10:00:00Z",
55-
last_updated_time: "2021-01-01T10:02:00Z",
46+
last_report_time: "2021-01-01T10:02:00Z",
5647
});
5748

5849
// Example AdapterStatusCreateRequest (for POST /clusters/{id}/statuses)
5950
const exampleAdapterStatusCreateRequest: AdapterStatusCreateRequest = (#{
6051
adapter: "validator",
6152
observed_generation: 1,
53+
observed_time: "2021-01-01T10:00:00Z",
6254
conditions: #[
6355
#{
6456
type: "Available",
6557
status: "True",
6658
reason: "All validations passed",
6759
message: "All 30 validation tests passed",
68-
observed_generation: 1,
69-
observed_time: "2021-01-01T10:00:00Z",
7060
},
7161
#{
7262
type: "Applied",
7363
status: "True",
7464
reason: "Validation job applied",
7565
message: "Validation job applied successfully",
76-
observed_generation: 1,
77-
observed_time: "2021-01-01T10:00:00Z",
7866
},
7967
#{
8068
type: "Health",
8169
status: "True",
8270
reason: "Validation job healthy",
8371
message: "Validation job is healthy",
84-
observed_generation: 1,
85-
observed_time: "2021-01-01T10:00:00Z",
8672
}
8773
],
8874
metadata: #{
@@ -118,9 +104,6 @@ const exampleAdapterStatusList: AdapterStatusList = (#{
118104
status: "True",
119105
reason: "All validations passed",
120106
message: "All 30 validation tests passed",
121-
observed_generation: 1,
122-
created_time: "2021-01-01T10:00:00Z",
123-
last_updated_time: "2021-01-01T10:00:00Z",
124107
last_transition_time: "2021-01-01T10:00:00Z",
125108
},
126109
],
@@ -129,7 +112,7 @@ const exampleAdapterStatusList: AdapterStatusList = (#{
129112
duration: "2m",
130113
},
131114
created_time: "2021-01-01T10:00:00Z",
132-
last_updated_time: "2021-01-01T10:02:00Z",
115+
last_report_time: "2021-01-01T10:02:00Z",
133116
},
134117
#{
135118
adapter: "dns",
@@ -140,14 +123,11 @@ const exampleAdapterStatusList: AdapterStatusList = (#{
140123
status: "True",
141124
reason: "DNS configured",
142125
message: "DNS records created",
143-
observed_generation: 1,
144-
created_time: "2021-01-01T10:01:00Z",
145-
last_updated_time: "2021-01-01T10:01:00Z",
146126
last_transition_time: "2021-01-01T10:01:00Z",
147127
},
148128
],
149129
created_time: "2021-01-01T10:01:00Z",
150-
last_updated_time: "2021-01-01T10:01:30Z",
130+
last_report_time: "2021-01-01T10:01:30Z",
151131
},
152132
],
153133
});

models/statuses/model.tsp

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@ import "../common/model.tsp";
22
import "./example_adapter_status.tsp";
33

44
/**
5-
* Condition represents a single status condition
6-
* Used in both AdapterStatus.conditions[] (with standard types like "Available")
7-
* and ClusterStatus.conditions[] (with semantic types like "ValidationSuccessful", "DNSSuccessful", etc.)
5+
* Base condition fields shared by all condition types
86
*/
9-
model Condition {
7+
model ConditionBase {
108
/**
119
* Condition type
12-
* In AdapterStatus: Standard Kubernetes types ("Available", "Applied", "Health")
13-
* In ClusterStatus: Semantic types ("ValidationSuccessful", "DNSSuccessful", "NodePoolSuccessful", etc.)
1410
*/
1511
type: string;
1612

@@ -29,6 +25,29 @@ model Condition {
2925
*/
3026
message?: string;
3127

28+
/**
29+
* When this condition last transitioned status (API-managed)
30+
* Only updated when status changes (True/False/Unknown), not when reason/message changes
31+
*/
32+
@format("date-time") last_transition_time: string;
33+
}
34+
35+
/**
36+
* Condition in AdapterStatus
37+
* Used for standard Kubernetes condition types: "Available", "Applied", "Health"
38+
* Note: observed_generation is at AdapterStatus level, not per-condition,
39+
* since all conditions in one AdapterStatus share the same observed generation
40+
*/
41+
model AdapterCondition extends ConditionBase {
42+
// No additional fields - inherits all fields from ConditionBase
43+
}
44+
45+
/**
46+
* Condition in Cluster/NodePool status
47+
* Used for semantic condition types: "ValidationSuccessful", "DNSSuccessful", "NodePoolSuccessful", etc.
48+
* Includes observed_generation and last_updated_time to track adapter-specific state
49+
*/
50+
model ResourceCondition extends ConditionBase {
3251
/**
3352
* Generation of the spec that this condition reflects
3453
*/
@@ -40,39 +59,28 @@ model Condition {
4059
@format("date-time") created_time: string;
4160

4261
/**
43-
* When this condition was last updated (API-managed)
62+
* When the corresponding adapter last reported (API-managed)
63+
* Updated every time the adapter POSTs, even if condition status hasn't changed
64+
* Copied from AdapterStatus.last_report_time
4465
*/
4566
@format("date-time") last_updated_time: string;
46-
47-
/**
48-
* When this condition last transitioned status (API-managed)
49-
*/
50-
@format("date-time") last_transition_time?: string;
5167
}
5268

5369
/**
5470
* Condition data for create/update requests (from adapters)
71+
* observed_generation and observed_time are now at AdapterStatusCreateRequest level
5572
*/
5673
model ConditionRequest {
5774
type: string;
5875
status: "True" | "False" | "Unknown";
5976
reason?: string;
6077
message?: string;
61-
observed_generation: int32;
62-
63-
/**
64-
* When the adapter observed this condition
65-
* API will use this to set created_time, last_updated_time, last_transition_time
66-
*/
67-
@format("date-time") observed_time: string;
6878
}
6979

7080
/**
71-
* AdapterStatus represents the complete status report from an adapter
72-
* Contains multiple conditions, job metadata, and adapter-specific data
81+
* Base fields shared by AdapterStatus and AdapterStatusCreateRequest
7382
*/
74-
@example(exampleAdapterStatus)
75-
model AdapterStatus {
83+
model AdapterStatusBase {
7684
/**
7785
* Adapter name (e.g., "validator", "dns", "provisioner")
7886
*/
@@ -83,12 +91,6 @@ model AdapterStatus {
8391
*/
8492
observed_generation: int32;
8593

86-
/**
87-
* Kubernetes-style conditions tracking adapter state
88-
* Typically includes: Available, Applied, Health
89-
*/
90-
conditions: Condition[];
91-
9294
/**
9395
* Job execution metadata
9496
*/
@@ -105,35 +107,45 @@ model AdapterStatus {
105107
* Adapter-specific data (structure varies by adapter type)
106108
*/
107109
data?: Record<unknown>;
110+
}
111+
112+
/**
113+
* AdapterStatus represents the complete status report from an adapter
114+
* Contains multiple conditions, job metadata, and adapter-specific data
115+
*/
116+
@example(exampleAdapterStatus)
117+
model AdapterStatus extends AdapterStatusBase {
118+
/**
119+
* Kubernetes-style conditions tracking adapter state
120+
* Typically includes: Available, Applied, Health
121+
*/
122+
conditions: AdapterCondition[];
108123

109124
/**
110125
* When this adapter status was first created (API-managed)
111126
*/
112127
@format("date-time") created_time: string;
113128

114129
/**
115-
* When this adapter status was last updated (API-managed)
130+
* When this adapter last reported its status (API-managed)
131+
* Updated every time the adapter POSTs, even if conditions haven't changed
132+
* Used by Sentinel to detect adapter liveness
116133
*/
117-
@format("date-time") last_updated_time: string;
134+
@format("date-time") last_report_time: string;
118135
}
119136

120137
/**
121138
* Request payload for creating/updating adapter status
122139
*/
123140
@example(exampleAdapterStatusCreateRequest)
124-
model AdapterStatusCreateRequest {
125-
adapter: string;
126-
observed_generation: int32;
141+
model AdapterStatusCreateRequest extends AdapterStatusBase {
142+
/**
143+
* When the adapter observed this resource state
144+
* API will use this to set AdapterStatus.last_report_time
145+
*/
146+
@format("date-time") observed_time: string;
147+
127148
conditions: ConditionRequest[];
128-
metadata?: {
129-
job_name?: string;
130-
job_namespace?: string;
131-
attempt?: int32;
132-
@format("date-time") started_time?: string;
133-
@format("date-time") completed_time?: string;
134-
duration?: string;
135-
};
136-
data?: Record<unknown>;
137149
}
138150

139151
/**

0 commit comments

Comments
 (0)