Skip to content

Commit 841d1b3

Browse files
authored
🌱 Introduce v1beta2 conditions for HCloudRemediation (#1971)
1 parent d3947db commit 841d1b3

10 files changed

Lines changed: 399 additions & 10 deletions

.golangci.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ linters:
114114
alias: v1beta1patch
115115
- pkg: sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions
116116
alias: v1beta1conditions
117+
- pkg: sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions/v1beta2
118+
alias: v1beta2conditions
117119
# Legacy-shadow conditions helper for v1beta2 CAPI core objects.
118120
# Different package path than v1beta1conditions above — aliasing
119121
# both distinctly avoids accidental swaps.

api/v1beta1/conditions_const.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,17 @@ const (
393393
TargetClusterSyncingSecretFailedV1Beta2Reason = "SyncingSecretFailed"
394394
)
395395

396-
// HetznerBareMetalMachine v1beta2 condition types.
396+
// HCloudRemediation v1beta2 conditions and reasons.
397+
const (
398+
// HCloudRemediationSkippedV1Beta2Condition reports that remediation was skipped because
399+
// the HCloudMachine has a state that makes remediation unnecessary or impossible.
400+
HCloudRemediationSkippedV1Beta2Condition = "RemediationSkipped"
401+
// IrrecoverableServerCreateFailureV1Beta2Reason indicates remediation was skipped because
402+
// the HCloudMachine failed to create with an irrecoverable error (e.g. invalid_input, resource_unavailable).
403+
IrrecoverableServerCreateFailureV1Beta2Reason = "IrrecoverableServerCreateFailure"
404+
)
397405

406+
// HetznerBareMetalMachine v1beta2 condition types.
398407
const (
399408
// HetznerBareMetalMachineHostAssociatedV1Beta2Condition is true when the host is associated.
400409
HetznerBareMetalMachineHostAssociatedV1Beta2Condition = "HostAssociated"

api/v1beta1/hcloudremediation_types.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package v1beta1
1919
import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1"
22+
v1beta2conditions "sigs.k8s.io/cluster-api/util/deprecated/v1beta1/conditions/v1beta2"
2223
)
2324

2425
// HCloudRemediationSpec defines the desired state of HCloudRemediation.
@@ -46,6 +47,21 @@ type HCloudRemediationStatus struct {
4647
// Conditions defines current service state of the HCloudRemediation.
4748
// +optional
4849
Conditions clusterv1beta1.Conditions `json:"conditions,omitempty"`
50+
51+
// v1beta2 groups all the fields that will be added or modified in HCloudRemediation's status with the V1Beta2 version.
52+
// +optional
53+
V1Beta2 *HCloudRemediationV1Beta2Status `json:"v1beta2,omitempty"`
54+
}
55+
56+
// HCloudRemediationV1Beta2Status groups all the fields that will be added or modified in HCloudRemediationStatus with the V1Beta2 version.
57+
type HCloudRemediationV1Beta2Status struct {
58+
// conditions represents the observations of a HCloudRemediation's current state.
59+
// Known condition types are Ready, HCloudTokenAvailable and HCloudRateLimitExceeded.
60+
// +optional
61+
// +listType=map
62+
// +listMapKey=type
63+
// +kubebuilder:validation:MaxItems=32
64+
Conditions []metav1.Condition `json:"conditions,omitempty"`
4965
}
5066

5167
// +kubebuilder:object:root=true
@@ -82,6 +98,22 @@ func (r *HCloudRemediation) SetConditions(conditions clusterv1beta1.Conditions)
8298
r.Status.Conditions = conditions
8399
}
84100

101+
// GetV1Beta2Conditions returns the observations of the operational state of the HCloudRemediation resource.
102+
func (r *HCloudRemediation) GetV1Beta2Conditions() []metav1.Condition {
103+
if r.Status.V1Beta2 == nil {
104+
return nil
105+
}
106+
return r.Status.V1Beta2.Conditions
107+
}
108+
109+
// SetV1Beta2Conditions sets the underlying v1beta2 service state of the HCloudRemediation.
110+
func (r *HCloudRemediation) SetV1Beta2Conditions(conditions []metav1.Condition) {
111+
if r.Status.V1Beta2 == nil {
112+
r.Status.V1Beta2 = &HCloudRemediationV1Beta2Status{}
113+
}
114+
r.Status.V1Beta2.Conditions = conditions
115+
}
116+
85117
//+kubebuilder:object:root=true
86118

87119
// HCloudRemediationList contains a list of HCloudRemediation.
@@ -92,6 +124,64 @@ type HCloudRemediationList struct {
92124
Items []HCloudRemediation `json:"items"`
93125
}
94126

127+
// HCloudRemediationV1Beta2SummaryOpts returns the v1beta2 summary options for HCloudRemediation.
128+
// It is the single source of truth for which conditions contribute to the Ready summary,
129+
// used both by HCloudRemediationScope.Close() and by early-exit error paths that bypass the scope.
130+
//
131+
// The order of conditions in ForConditionTypes defines the priority for the Ready summary:
132+
// when multiple conditions are unhealthy, the summary lists all of them in priority order
133+
// (highest-priority first). The ordering reflects operational importance:
134+
// 1. HCloudTokenAvailable - invalid credentials block everything.
135+
// 2. HCloudRateLimitExceeded - rate-limit issues (negative polarity).
136+
// 3. RemediationSkipped - remediation was skipped due to an irrecoverable
137+
// machine state; surfaced for visibility (negative polarity).
138+
func HCloudRemediationV1Beta2SummaryOpts() []v1beta2conditions.SummaryOption {
139+
return []v1beta2conditions.SummaryOption{
140+
// ForConditionTypes lists every condition that contributes to Ready, in
141+
// priority order. When multiple conditions are unhealthy the summary
142+
// surfaces them in this order, so the most important issue is listed first.
143+
v1beta2conditions.ForConditionTypes{
144+
HCloudTokenAvailableV1Beta2Condition,
145+
HCloudRateLimitExceededV1Beta2Condition,
146+
HCloudRemediationSkippedV1Beta2Condition,
147+
},
148+
// IgnoreTypesIfMissing tells the summary not to treat the absence of a
149+
// listed condition as Unknown. Some reconcile paths exit before every
150+
// condition has been set (for example, before the token is checked or
151+
// before remediation has been evaluated), and we don't want those early
152+
// exits to flip Ready to Unknown.
153+
v1beta2conditions.IgnoreTypesIfMissing{
154+
HCloudTokenAvailableV1Beta2Condition,
155+
HCloudRateLimitExceededV1Beta2Condition,
156+
HCloudRemediationSkippedV1Beta2Condition,
157+
},
158+
// CustomMergeStrategy is used only to override the merge reasons, so
159+
// the Ready summary uses CAPI's standard Ready reasons (Ready /
160+
// NotReady / ReadyUnknown) instead of the generic merge defaults
161+
// (IssuesReported / UnknownReported / InfoReported).
162+
//
163+
// Negative polarity is passed directly into GetDefaultMergePriorityFunc
164+
// here. When a CustomMergeStrategy is provided, NewSummaryCondition
165+
// skips the path that wires up the NegativePolarityConditionTypes
166+
// SummaryOption into the default strategy, so the negative-polarity
167+
// types must be specified explicitly inside the strategy.
168+
v1beta2conditions.CustomMergeStrategy{
169+
MergeStrategy: v1beta2conditions.DefaultMergeStrategy(
170+
v1beta2conditions.GetPriorityFunc(v1beta2conditions.GetDefaultMergePriorityFunc(
171+
// conditions with negative polarity
172+
HCloudRateLimitExceededV1Beta2Condition,
173+
HCloudRemediationSkippedV1Beta2Condition,
174+
)),
175+
v1beta2conditions.ComputeReasonFunc(v1beta2conditions.GetDefaultComputeMergeReasonFunc(
176+
clusterv1beta1.NotReadyV1Beta2Reason,
177+
clusterv1beta1.ReadyUnknownV1Beta2Reason,
178+
clusterv1beta1.ReadyV1Beta2Reason,
179+
)),
180+
),
181+
},
182+
}
183+
}
184+
95185
func init() {
96186
objectTypes = append(objectTypes, &HCloudRemediation{}, &HCloudRemediationList{})
97187
}

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/infrastructure.cluster.x-k8s.io_hcloudremediations.yaml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,75 @@ spec:
172172
RetryCount can be used as a counter during the remediation.
173173
Field can hold number of reboots etc.
174174
type: integer
175+
v1beta2:
176+
description: v1beta2 groups all the fields that will be added or modified
177+
in HCloudRemediation's status with the V1Beta2 version.
178+
properties:
179+
conditions:
180+
description: |-
181+
conditions represents the observations of a HCloudRemediation's current state.
182+
Known condition types are Ready, HCloudTokenAvailable and HCloudRateLimitExceeded.
183+
items:
184+
description: Condition contains details for one aspect of the
185+
current state of this API Resource.
186+
properties:
187+
lastTransitionTime:
188+
description: |-
189+
lastTransitionTime is the last time the condition transitioned from one status to another.
190+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
191+
format: date-time
192+
type: string
193+
message:
194+
description: |-
195+
message is a human readable message indicating details about the transition.
196+
This may be an empty string.
197+
maxLength: 32768
198+
type: string
199+
observedGeneration:
200+
description: |-
201+
observedGeneration represents the .metadata.generation that the condition was set based upon.
202+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
203+
with respect to the current state of the instance.
204+
format: int64
205+
minimum: 0
206+
type: integer
207+
reason:
208+
description: |-
209+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
210+
Producers of specific condition types may define expected values and meanings for this field,
211+
and whether the values are considered a guaranteed API.
212+
The value should be a CamelCase string.
213+
This field may not be empty.
214+
maxLength: 1024
215+
minLength: 1
216+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
217+
type: string
218+
status:
219+
description: status of the condition, one of True, False,
220+
Unknown.
221+
enum:
222+
- "True"
223+
- "False"
224+
- Unknown
225+
type: string
226+
type:
227+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
228+
maxLength: 316
229+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
230+
type: string
231+
required:
232+
- lastTransitionTime
233+
- message
234+
- reason
235+
- status
236+
- type
237+
type: object
238+
maxItems: 32
239+
type: array
240+
x-kubernetes-list-map-keys:
241+
- type
242+
x-kubernetes-list-type: map
243+
type: object
175244
type: object
176245
type: object
177246
served: true

config/crd/bases/infrastructure.cluster.x-k8s.io_hcloudremediationtemplates.yaml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,75 @@ spec:
180180
RetryCount can be used as a counter during the remediation.
181181
Field can hold number of reboots etc.
182182
type: integer
183+
v1beta2:
184+
description: v1beta2 groups all the fields that will be added
185+
or modified in HCloudRemediation's status with the V1Beta2 version.
186+
properties:
187+
conditions:
188+
description: |-
189+
conditions represents the observations of a HCloudRemediation's current state.
190+
Known condition types are Ready, HCloudTokenAvailable and HCloudRateLimitExceeded.
191+
items:
192+
description: Condition contains details for one aspect of
193+
the current state of this API Resource.
194+
properties:
195+
lastTransitionTime:
196+
description: |-
197+
lastTransitionTime is the last time the condition transitioned from one status to another.
198+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
199+
format: date-time
200+
type: string
201+
message:
202+
description: |-
203+
message is a human readable message indicating details about the transition.
204+
This may be an empty string.
205+
maxLength: 32768
206+
type: string
207+
observedGeneration:
208+
description: |-
209+
observedGeneration represents the .metadata.generation that the condition was set based upon.
210+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
211+
with respect to the current state of the instance.
212+
format: int64
213+
minimum: 0
214+
type: integer
215+
reason:
216+
description: |-
217+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
218+
Producers of specific condition types may define expected values and meanings for this field,
219+
and whether the values are considered a guaranteed API.
220+
The value should be a CamelCase string.
221+
This field may not be empty.
222+
maxLength: 1024
223+
minLength: 1
224+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
225+
type: string
226+
status:
227+
description: status of the condition, one of True, False,
228+
Unknown.
229+
enum:
230+
- "True"
231+
- "False"
232+
- Unknown
233+
type: string
234+
type:
235+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
236+
maxLength: 316
237+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
238+
type: string
239+
required:
240+
- lastTransitionTime
241+
- message
242+
- reason
243+
- status
244+
- type
245+
type: object
246+
maxItems: 32
247+
type: array
248+
x-kubernetes-list-map-keys:
249+
- type
250+
x-kubernetes-list-type: map
251+
type: object
183252
type: object
184253
required:
185254
- status

0 commit comments

Comments
 (0)