@@ -30,24 +30,25 @@ type Integration struct {
3030
3131// ServiceStatus represents a single Kubernetes workload's status.
3232type ServiceStatus struct {
33- ID string `json:"id"`
34- Name string `json:"name"`
35- Namespace string `json:"namespace"`
36- WorkloadType string `json:"workload_type"`
37- Version string `json:"version"`
38- Image string `json:"image"`
39- Replicas int32 `json:"replicas"`
40- ReadyReplicas int32 `json:"ready_replicas"`
41- Status string `json:"status"`
42- Labels map [string ]string `json:"labels,omitempty"`
43- Owner * string `json:"owner"`
44- Tier * string `json:"tier"`
45- ManagedBy * string `json:"managed_by"`
46- PartOf * string `json:"part_of"`
47- DependsOn []string `json:"depends_on"`
48- Integration Integration `json:"integration"`
49- CreatedAt time.Time `json:"created_at"`
50- UpdatedAt time.Time `json:"updated_at"`
33+ ID string `json:"id"`
34+ Name string `json:"name"`
35+ Namespace string `json:"namespace"`
36+ WorkloadType string `json:"workload_type"`
37+ Version string `json:"version"`
38+ Image string `json:"image"`
39+ Replicas int32 `json:"replicas"`
40+ ReadyReplicas int32 `json:"ready_replicas"`
41+ Status string `json:"status"`
42+ Labels map [string ]string `json:"labels,omitempty"`
43+ Owner * string `json:"owner"`
44+ Tier * string `json:"tier"`
45+ ManagedBy * string `json:"managed_by"`
46+ PartOf * string `json:"part_of"`
47+ DependsOn []string `json:"depends_on"`
48+ Integration Integration `json:"integration"`
49+ LastTransition * time.Time `json:"last_transition"`
50+ CreatedAt time.Time `json:"created_at"`
51+ UpdatedAt time.Time `json:"updated_at"`
5152}
5253
5354// Summary contains aggregate statistics.
@@ -138,25 +139,31 @@ func (c *Client) FetchDeployments(ctx context.Context) ([]ServiceStatus, Summary
138139 status := computeStatus (ready , desired )
139140 addToSummary (& summary , status )
140141
142+ var condTimes []time.Time
143+ for _ , cond := range dep .Status .Conditions {
144+ condTimes = append (condTimes , cond .LastTransitionTime .Time )
145+ }
146+
141147 services = append (services , ServiceStatus {
142- ID : fmt .Sprintf ("%s/%s" , dep .Namespace , dep .Name ),
143- Name : dep .Name ,
144- Namespace : dep .Namespace ,
145- WorkloadType : "deployment" ,
146- Version : version ,
147- Image : image ,
148- Replicas : desired ,
149- ReadyReplicas : ready ,
150- Status : status ,
151- Labels : dep .Spec .Template .Labels ,
152- Owner : owner ,
153- Tier : tier ,
154- ManagedBy : managedBy ,
155- PartOf : partOf ,
156- DependsOn : dependsOn ,
157- Integration : integration ,
158- CreatedAt : dep .CreationTimestamp .Time ,
159- UpdatedAt : time .Now (),
148+ ID : fmt .Sprintf ("%s/%s" , dep .Namespace , dep .Name ),
149+ Name : dep .Name ,
150+ Namespace : dep .Namespace ,
151+ WorkloadType : "deployment" ,
152+ Version : version ,
153+ Image : image ,
154+ Replicas : desired ,
155+ ReadyReplicas : ready ,
156+ Status : status ,
157+ Labels : dep .Spec .Template .Labels ,
158+ Owner : owner ,
159+ Tier : tier ,
160+ ManagedBy : managedBy ,
161+ PartOf : partOf ,
162+ DependsOn : dependsOn ,
163+ Integration : integration ,
164+ LastTransition : lastConditionTransition (condTimes ),
165+ CreatedAt : dep .CreationTimestamp .Time ,
166+ UpdatedAt : time .Now (),
160167 })
161168 }
162169
@@ -191,25 +198,31 @@ func (c *Client) FetchDeployments(ctx context.Context) ([]ServiceStatus, Summary
191198 status := computeStatus (ready , desired )
192199 addToSummary (& summary , status )
193200
201+ var ssTimes []time.Time
202+ for _ , cond := range ss .Status .Conditions {
203+ ssTimes = append (ssTimes , cond .LastTransitionTime .Time )
204+ }
205+
194206 services = append (services , ServiceStatus {
195- ID : fmt .Sprintf ("%s/%s" , ss .Namespace , ss .Name ),
196- Name : ss .Name ,
197- Namespace : ss .Namespace ,
198- WorkloadType : "statefulset" ,
199- Version : version ,
200- Image : image ,
201- Replicas : desired ,
202- ReadyReplicas : ready ,
203- Status : status ,
204- Labels : ss .Spec .Template .Labels ,
205- Owner : owner ,
206- Tier : tier ,
207- ManagedBy : managedBy ,
208- PartOf : partOf ,
209- DependsOn : dependsOn ,
210- Integration : integration ,
211- CreatedAt : ss .CreationTimestamp .Time ,
212- UpdatedAt : time .Now (),
207+ ID : fmt .Sprintf ("%s/%s" , ss .Namespace , ss .Name ),
208+ Name : ss .Name ,
209+ Namespace : ss .Namespace ,
210+ WorkloadType : "statefulset" ,
211+ Version : version ,
212+ Image : image ,
213+ Replicas : desired ,
214+ ReadyReplicas : ready ,
215+ Status : status ,
216+ Labels : ss .Spec .Template .Labels ,
217+ Owner : owner ,
218+ Tier : tier ,
219+ ManagedBy : managedBy ,
220+ PartOf : partOf ,
221+ DependsOn : dependsOn ,
222+ Integration : integration ,
223+ LastTransition : lastConditionTransition (ssTimes ),
224+ CreatedAt : ss .CreationTimestamp .Time ,
225+ UpdatedAt : time .Now (),
213226 })
214227 }
215228 }
@@ -242,25 +255,31 @@ func (c *Client) FetchDeployments(ctx context.Context) ([]ServiceStatus, Summary
242255 status := computeStatus (ready , desired )
243256 addToSummary (& summary , status )
244257
258+ var dsTimes []time.Time
259+ for _ , cond := range ds .Status .Conditions {
260+ dsTimes = append (dsTimes , cond .LastTransitionTime .Time )
261+ }
262+
245263 services = append (services , ServiceStatus {
246- ID : fmt .Sprintf ("%s/%s" , ds .Namespace , ds .Name ),
247- Name : ds .Name ,
248- Namespace : ds .Namespace ,
249- WorkloadType : "daemonset" ,
250- Version : version ,
251- Image : image ,
252- Replicas : desired ,
253- ReadyReplicas : ready ,
254- Status : status ,
255- Labels : ds .Spec .Template .Labels ,
256- Owner : owner ,
257- Tier : tier ,
258- ManagedBy : managedBy ,
259- PartOf : partOf ,
260- DependsOn : dependsOn ,
261- Integration : integration ,
262- CreatedAt : ds .CreationTimestamp .Time ,
263- UpdatedAt : time .Now (),
264+ ID : fmt .Sprintf ("%s/%s" , ds .Namespace , ds .Name ),
265+ Name : ds .Name ,
266+ Namespace : ds .Namespace ,
267+ WorkloadType : "daemonset" ,
268+ Version : version ,
269+ Image : image ,
270+ Replicas : desired ,
271+ ReadyReplicas : ready ,
272+ Status : status ,
273+ Labels : ds .Spec .Template .Labels ,
274+ Owner : owner ,
275+ Tier : tier ,
276+ ManagedBy : managedBy ,
277+ PartOf : partOf ,
278+ DependsOn : dependsOn ,
279+ Integration : integration ,
280+ LastTransition : lastConditionTransition (dsTimes ),
281+ CreatedAt : ds .CreationTimestamp .Time ,
282+ UpdatedAt : time .Now (),
264283 })
265284 }
266285 }
@@ -304,6 +323,20 @@ func addToSummary(summary *Summary, status string) {
304323 }
305324}
306325
326+ // lastConditionTransition returns the most recent condition transition time.
327+ func lastConditionTransition (times []time.Time ) * time.Time {
328+ if len (times ) == 0 {
329+ return nil
330+ }
331+ latest := times [0 ]
332+ for _ , t := range times [1 :] {
333+ if t .After (latest ) {
334+ latest = t
335+ }
336+ }
337+ return & latest
338+ }
339+
307340const annotationPrefix = "deployscope.dev/"
308341
309342func mergeAnnotations (sets ... map [string ]string ) map [string ]string {
0 commit comments