github.com/operator-framework/operator-lifecycle-manager@v0.30.0/doc/contributors/design-proposals/csv-status.md (about) 1 # CSV Reporting 2 3 ## Motivation 4 The `ClusterServiceVersion` `CustomResource` needs to report useful and contextual information to the user via the `status` sub-resource. An end user associates an operator with a `CSV`. The end user is primarily interested in learning about the status of the deployment or upgrade of the operator associated with the `CSV`. The following events among many others are of interest 5 6 * An instance of the operator managed by the `csv` is being installed (No previous version exists). 7 * An operator is being upgraded to a desired version. 8 * An operator has been successfully installed or upgraded. 9 * Error happens while an operator install or upgrade is in progress. 10 * An operator is being removed. 11 12 ### Conventions 13 In order to design a status that makes sense in the context of kubernetes resources, it's important to conform to current conventions. This will also help us avoid pitfalls that may have already been solved. 14 15 In light of this, `ClusterServiceVesrion` will have the following `Condition` type(s). 16 17 ```go 18 // ClusterServiceVersionConditionType is the state of the underlying operator. 19 type ClusterServiceVersionConditionType string 20 21 const ( 22 // Available means that the underlying operator has been deployed successfully 23 // and it has passed all liveness/readiness check(s) performed by olm. 24 OperatorAvailable ClusterServiceVersionConditionType = "Available" 25 26 // Progressing means that the deployment of the underlying operator is in progress. 27 OperatorProgressing ClusterServiceVersionConditionType = "Progressing" 28 29 // We can add more condition type(s) as wee see fit. 30 ) 31 ``` 32 33 The current definition of `ClusterServiceVersionCondition` does not conform to kubernetes `status` conventions. We will make the following change(s) to make it conformant to current conventions. 34 * Remove `LastUpdateTime` from `ClusterServiceVersionCondition`. There is no logic that depends on this field. 35 * Remove `Phase` 36 * Add `Type` of `ClusterServiceVersionConditionType` type. 37 * Add `Status` of `corev1.ConditionStatus` type. 38 39 ```go 40 import ( 41 corev1 "k8s.io/kubernetes/pkg/apis/core/v1" 42 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 43 ) 44 45 type ClusterServiceVersionCondition struct { 46 // Type is the type of ClusterServiceVersionCondition condition. 47 Type ClusterServiceVersionConditionType `json:"type" description:"type of ClusterServiceVersion condition"` 48 49 // Status is the status of the condition, one of True, False, Unknown. 50 Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` 51 52 // Reason is a one-word CamelCase reason for the condition's last transition. 53 // +optional 54 Reason ConditionReason `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` 55 56 // Message is a human-readable message indicating details about last transition. 57 // +optional 58 Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` 59 60 // LastHeartbeatTime is the last time we got an update on a given condition 61 // +optional 62 LastHeartbeatTime *metav1.Time `json:"lastHeartbeatTime,omitempty" description:"last time we got an update on a given condition"` 63 64 // LastTransitionTime is the last time the condition transit from one status to another 65 // +optional 66 LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty" description:"last time the condition transit from one status to another"` 67 } 68 ``` 69 70 ### Current Phase 71 A CSV transitions through a set of phase(s) during its life cycle. These phase(s) are internal to olm. Currently the following group of fields track the current phase. 72 ```go 73 type ClusterServiceVersionStatus struct { 74 // Current condition of the ClusterServiceVersion 75 Phase ClusterServiceVersionPhase `json:"phase,omitempty"` 76 // A human readable message indicating details about why the ClusterServiceVersion is in this condition. 77 // +optional 78 Message string `json:"message,omitempty"` 79 // A brief CamelCase message indicating details about why the ClusterServiceVersion is in this state. 80 // e.g. 'RequirementsNotMet' 81 // +optional 82 Reason ConditionReason `json:"reason,omitempty"` 83 // Last time we updated the status 84 // +optional 85 LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` 86 // Last time the status transitioned from one status to another. 87 // +optional 88 LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` 89 } 90 ``` 91 92 We can consolidate this set fields into a separate structure as follows 93 ```go 94 type ClusterServiceVersionTransition struct { 95 // Name of the phase. 96 Phase ClusterServiceVersionPhase `json:"phase,omitempty"` 97 // A human readable message indicating details about why the ClusterServiceVersion is in this phase. 98 // +optional 99 Message string `json:"message,omitempty"` 100 // A brief CamelCase message indicating details about why the ClusterServiceVersion is in this phase. 101 // e.g. 'RequirementsNotMet' 102 // +optional 103 Reason ConditionReason `json:"reason,omitempty"` 104 // Last time we updated the status 105 // +optional 106 LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` 107 // Last time the status transitioned to this phase. 108 // +optional 109 LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` 110 } 111 112 type ClusterServiceVersionStatus struct { 113 CurrentPhase ClusterServiceVersionTransition `json:"phase,omitempty"` 114 } 115 ``` 116 117 This will probably break the current UI since it expects the `phase` name to be directly under `status` for any CSV. 118 119 120 ### Transition History 121 Today we keep appending new `ClusterServiceVersionCondition` to `Status.Conditions`. This does not conform to the conventions. `Status.Conditions` will now be a collection of `ClusterServiceVersionCondition` last observed. Typically it will have an item of `ClusterServiceVersionCondition` from each `ClusterServiceVersionConditionType`, as shown below. 122 123 ```yaml 124 conditions: 125 - type: Progressing 126 Status: True 127 Message: Working towards v1.0.0 128 - type: Available 129 Status: False 130 Reason: CSVReasonRequirementsUnknown 131 Message: Scheduling ClusterServiceVersion for requirement verification 132 ``` 133 134 If we want to continue to maintain a history of last N phase transition(s) or activities then we can add the following to `status`. 135 ```go 136 type ClusterServiceVersionStatus struct { 137 LastTransitions []ClusterServiceVersionTransition `json:"lastTransitions,omitempty"` 138 } 139 ``` 140 141 ### Versions 142 The `ClusterServiceVersion` resource needs to report the version of the operator it manages. The version information should have a `name` and a `version`. It must always match the currently installed version. If `v1.0.0` is currently installed, then this must indicate `v1.0.0` even if the associated `ClusterServiceVersion` is in the process of installing a new version `v1.1.0`. 143 144 ```go 145 type OperatorVersion struct { 146 // Name is the name of the operator. 147 Name string `json:"name"` 148 149 // Version of the operator currently installed. 150 Version string `json:"version"` 151 } 152 ``` 153 154 ```go 155 type ClusterServiceVersionStatus struct { 156 // List of conditions, a history of state transitions 157 Conditions []ClusterServiceVersionCondition `json:"conditions,omitempty"` 158 159 // Version of the underlying operator. 160 Version OperatorVersion `json:"version,omitempty"` 161 } 162 ``` 163 164 ### Related Objects 165 If an end user is looking at a csv, he/she should be able to access the related resource(s) associated with the csv. For example, the end user should be able to: 166 * Refer to the `Subscription` object that is associated with the `csv`. 167 * Refer to the `InstallPlan` object that created this `csv`. Is this useful during troubleshooting? 168 * Refer to the `CatalogSource` object that contains the operator manifest. 169 170 To make it easier for the end user to access the related resource(s), the following change is being proposed. 171 ```go 172 type ClusterServiceVersionStatus struct { 173 // Option 1: 174 175 // InstallPlanRef is a reference to the InstallPlan that created this CSV. 176 // +optional 177 InstallPlanRef *corev1.ObjectReference `json:"installPlanRef,omitempty"` 178 179 // SubscriptionRef is a reference to the Subscription related to this CSV. 180 // +optional 181 SubscriptionRef *corev1.ObjectReference `json:"subscriptionRef,omitempty"` 182 183 // CatalogSourceRef is a reference to the CatalogSource related to this CSV. 184 // +optional 185 CatalogSourceRef *corev1.ObjectReference `json:"catalogSourceRef,omitempty"` 186 187 // Option 2 188 // An array of ObjectReference pointing to the related object(s) 189 RelatedObjects []*corev1.ObjectReference `json:"relatedObjects,omitempty"` 190 } 191 ``` 192 193 ## User Experience 194 Let's go through some of the use cases related to operator deployment and upgrade and see what portion of the `status` would look like to an end user/administrator. 195 196 ### Use Case 1: 197 A new operator is being installed and olm is running requirements check. 198 ```yaml 199 status: 200 ... 201 phase: Pending 202 conditions: 203 - type: Progressing 204 Status: True 205 Message: Working towards v1.0.0 206 - type: Available 207 Status: False 208 Reason: CSVReasonRequirementsUnknown 209 Message: Scheduling ClusterServiceVersion for requirement verification 210 ``` 211 `status.version` is empty since we don't have any version of the operator installed yet. 212 213 ### Use Case 2: 214 A new operator has been successfully installed, no previous version existed. 215 ```yaml 216 status: 217 ... 218 phase: Succeeded 219 conditions: 220 - type: Progressing 221 Status: False 222 Message: Deployed version v1.0.0 223 - type: Available 224 Status: True 225 version: 226 name: etcd 227 version: 1.0.0 228 ``` 229 230 ### Use Case 3: 231 An existing operator is being upgraded to a new version. We need to put more thoughts into this, what is below is just a rough sketch. 232 ```yaml 233 // This is while upgrade is in progress. 234 // Original ClusterServiceVersion that is being replaced. 235 status: 236 ... 237 phase: Replacing 238 conditions: 239 - type: Progressing 240 Status: False 241 - type: Available 242 Status: False 243 Reason: BeingReplaced 244 version: 245 name: etcd 246 version: v1.0.0 247 248 // Head CSV 249 status: 250 ... 251 phase: Pending 252 conditions: 253 - type: Progressing 254 Status: True 255 Message: Working toward v2.0.0 256 - type: Available 257 Status: False 258 version: 259 name: etcd 260 version: 1.0.0 261 ``` 262 `version` is set to `1.0.0` since this is the last version installed on the cluster. Once the upgrade is successful, the `head` csv status will look like this. 263 ```yaml 264 status: 265 ... 266 phase: Succeeded 267 conditions: 268 - type: Progressing 269 Status: False 270 Message: Deployed version v2.0.0 271 - type: Available 272 Status: True 273 version: 274 name: etcd 275 version: 2.0.0 276 ```