go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/deploy/service/model/entities.go (about) 1 // Copyright 2022 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package model contains Datastore entities definition. 16 package model 17 18 import ( 19 "sort" 20 "time" 21 22 "go.chromium.org/luci/deploy/api/modelpb" 23 "go.chromium.org/luci/gae/service/datastore" 24 ) 25 26 // Asset represents a Cloud resource (or a bunch of resources) actuated as 27 // a single unit. 28 type Asset struct { 29 _kind string `gae:"$kind,Asset"` 30 _extra datastore.PropertyMap `gae:"-,extra"` 31 32 // ID is the unique ID of this asset matching Asset.Id. 33 ID string `gae:"$id"` 34 // Asset contains all details about the asset. 35 Asset *modelpb.Asset 36 37 // LastHistoryID is ID of the last committed AssetHistory entity. 38 LastHistoryID int64 `gae:",noindex"` 39 40 // HistoryEntry is data of the last committed or currently recording entry. 41 // 42 // If its ID matches LastHistoryID, then it was already committed and it is 43 // the latest entry. Otherwise it is the currently recording one and its ID 44 // is LastHistoryID+1. 45 HistoryEntry *modelpb.AssetHistory 46 47 // ConsecutiveFailures counts how many actuations failed in a row. 48 // 49 // It is reset when an actuation succeeds or the asset is determined to be 50 // up-to-date, disabled, or locked. 51 ConsecutiveFailures int64 `gae:",noindex"` 52 } 53 54 // IsRecordingHistoryEntry is true if HistoryEntry is an uncommitted record. 55 func (a *Asset) IsRecordingHistoryEntry() bool { 56 return a.HistoryEntry != nil && a.HistoryEntry.HistoryId == a.LastHistoryID+1 57 } 58 59 // finalizeHistoryEntry marks the recording HistoryEntry as complete. 60 func (a *Asset) finalizeHistoryEntry() *modelpb.AssetHistory { 61 if !a.IsRecordingHistoryEntry() { 62 panic("not recording a history entry") 63 } 64 a.LastHistoryID = a.HistoryEntry.HistoryId 65 return a.HistoryEntry 66 } 67 68 // AssetHistory is an entry in an asset history log. 69 type AssetHistory struct { 70 _kind string `gae:"$kind,AssetHistory"` 71 _extra datastore.PropertyMap `gae:"-,extra"` 72 73 // ID is monotonically increasing ID, starting with 1. 74 ID int64 `gae:"$id"` 75 // Parent is the key of the parent Asset entity. 76 Parent *datastore.Key `gae:"$parent"` 77 // Entry contains all details. 78 Entry *modelpb.AssetHistory 79 80 // Created matches Entry.Actuation.Created, exposed for indexing. 81 Created time.Time 82 } 83 84 // Actuation is an inflight or finished actuation of some deployment. 85 type Actuation struct { 86 _kind string `gae:"$kind,Actuation"` 87 _extra datastore.PropertyMap `gae:"-,extra"` 88 89 // ID is the unique ID of the actuation matching Actuation.Id. 90 ID string `gae:"$id"` 91 // Actuation contains all details about the actuation. 92 Actuation *modelpb.Actuation 93 // Decisions is what the backend decided to do with the actuated assets. 94 Decisions *modelpb.ActuationDecisions 95 96 // State matches Actuation.State, exposed for indexing. 97 State modelpb.Actuation_State 98 // Created matches Actuation.Created, exposed for indexing. 99 Created time.Time 100 // Expiry matches Actuation.Expiry, exposed for indexing. 101 Expiry time.Time 102 } 103 104 // AssetIDs is a sorted list of asset IDs reported in this actuation. 105 // 106 // Returns assets with any actuation decision, including all SKIP_* decisions. 107 func (a *Actuation) AssetIDs() []string { 108 ids := make([]string, 0, len(a.Decisions.GetDecisions())) 109 for id := range a.Decisions.GetDecisions() { 110 ids = append(ids, id) 111 } 112 sort.Strings(ids) 113 return ids 114 } 115 116 // ActuatedAssetIDs is a sorted list of asset IDs that are being actuated. 117 // 118 // Only returns assets with ACTUATE_* decisions. 119 func (a *Actuation) ActuatedAssetIDs() []string { 120 ids := make([]string, 0, len(a.Decisions.GetDecisions())) 121 for id, decision := range a.Decisions.GetDecisions() { 122 if IsActuateDecision(decision.Decision) { 123 ids = append(ids, id) 124 } 125 } 126 sort.Strings(ids) 127 return ids 128 }