|
| 1 | +package v1alpha1 |
| 2 | + |
| 3 | +import ( |
| 4 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 5 | +) |
| 6 | + |
| 7 | +// RuleStatus defines the result of evaluating a NodeReadinessRule's criteria against a Node. |
| 8 | +// +kubebuilder:validation:Enum=Matched;Unmatched;Error |
| 9 | +type RuleStatus string |
| 10 | + |
| 11 | +const ( |
| 12 | + // RuleStatusMatched indicates that the Node successfully met all criteria |
| 13 | + // (both NodeSelector and Conditions) defined in the NodeReadinessRule. |
| 14 | + // When in this state, the controller should ensure the corresponding Taint is applied. |
| 15 | + RuleStatusMatched RuleStatus = "Matched" |
| 16 | + |
| 17 | + // RuleStatusUnmatched indicates that the Node did not meet the criteria |
| 18 | + // defined in the NodeReadinessRule (e.g., label mismatch or condition not satisfied). |
| 19 | + // When in this state, the controller should ensure the corresponding Taint is absent. |
| 20 | + RuleStatusUnmatched RuleStatus = "Unmatched" |
| 21 | + |
| 22 | + // RuleStatusError indicates that a programmatic or configuration error occurred |
| 23 | + // during the evaluation process (e.g., an invalid or unparseable NodeSelector). |
| 24 | + // The controller cannot safely determine if the taint should be present or absent. |
| 25 | + RuleStatusError RuleStatus = "Error" |
| 26 | +) |
| 27 | + |
| 28 | +// +kubebuilder:object:root=true |
| 29 | +// +kubebuilder:subresource:status |
| 30 | +// +kubebuilder:resource:scope=Cluster,shortName=nrrp |
| 31 | +// +kubebuilder:printcolumn:name="Node",type=string,JSONPath=`.spec.nodeName`,description="The Node this report belongs to." |
| 32 | +// +kubebuilder:printcolumn:name="Matched Rules",type=integer,JSONPath=`.status.summary.matchedRules`,description="Number of rules matching this node." |
| 33 | +// +kubebuilder:printcolumn:name="UnMatched Rules",type=integer,JSONPath=`.status.summary.unMatchedRules`,description="Number of rules not matching this node." |
| 34 | +// +kubebuilder:printcolumn:name="Applied Taints",type=integer,JSONPath=`.status.summary.appliedTaints`,description="Number of taints currently applied." |
| 35 | +// +kubebuilder:printcolumn:name="Errors",type=integer,JSONPath=`.status.summary.errors`,description="Number of evaluation errors." |
| 36 | +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` |
| 37 | + |
| 38 | +// NodeReadinessRuleReport is the Schema for the nodereadinessrulereports API. |
| 39 | +type NodeReadinessRuleReport struct { |
| 40 | + metav1.TypeMeta `json:",inline"` |
| 41 | + |
| 42 | + // metadata is a standard object metadata |
| 43 | + // +optional |
| 44 | + metav1.ObjectMeta `json:"metadata,omitzero"` |
| 45 | + |
| 46 | + // spec defines the desired state of NodeReadinessRuleReport |
| 47 | + // +required |
| 48 | + Spec NodeReadinessRuleReportSpec `json:"spec,omitzero"` |
| 49 | + |
| 50 | + // status defines the observed state of NodeReadinessRuleReport |
| 51 | + // +optional |
| 52 | + Status NodeReadinessRuleReportStatus `json:"status,omitzero"` |
| 53 | +} |
| 54 | + |
| 55 | +// NodeReadinessRuleReportSpec defines the desired state of NodeReadinessRuleReport. |
| 56 | +type NodeReadinessRuleReportSpec struct { |
| 57 | + // nodeName specifies the exact name of the target Kubernetes Node. |
| 58 | + // This object establishes a strict 1:1 relationship with the specified node, |
| 59 | + // acting as the single source of truth for all rules and statuses applied to it. |
| 60 | + // Because it binds this resource to a specific physical or virtual machine, it cannot be changed once set. |
| 61 | + // |
| 62 | + // The validation constraints enforce standard Kubernetes resource naming |
| 63 | + // (RFC 1123 DNS Subdomain format), as defined in upstream apimachinery: |
| 64 | + // https://github.com/kubernetes/apimachinery/blob/master/pkg/util/validation/validation.go#L198 |
| 65 | + // |
| 66 | + // +required |
| 67 | + // +kubebuilder:validation:MinLength=1 |
| 68 | + // +kubebuilder:validation:MaxLength=253 |
| 69 | + // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` |
| 70 | + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="nodeName is immutable and cannot be changed once set" |
| 71 | + NodeName string `json:"nodeName,omitempty"` |
| 72 | +} |
| 73 | + |
| 74 | +// NodeReadinessRuleReportStatus defines the observed state of NodeReadinessRuleReport. |
| 75 | +// +kubebuilder:validation:MinProperties=1 |
| 76 | +type NodeReadinessRuleReportStatus struct { |
| 77 | + // readinessReports provides detailed insight into the rule's assessment for individual Nodes. |
| 78 | + // This is primarily used for auditing and debugging why specific Nodes were or |
| 79 | + // were not targeted by the rule. |
| 80 | + // |
| 81 | + // +optional |
| 82 | + // +listType=map |
| 83 | + // +listMapKey=ruleName |
| 84 | + // +kubebuilder:validation:MaxItems=100 |
| 85 | + ReadinessReports []ReadinessReport `json:"readinessReports,omitempty"` |
| 86 | + |
| 87 | + // summary provides a quick overview of the rules applied to this node. |
| 88 | + // |
| 89 | + // +optional |
| 90 | + Summary ReportSummary `json:"summary,omitempty,omitzero"` |
| 91 | +} |
| 92 | + |
| 93 | +// ReadinessReport defines the outcome of evaluating a single NodeReadinessRule against a specific Node. |
| 94 | +type ReadinessReport struct { |
| 95 | + // ruleName is the name of the NodeReadinessRule being evaluated. |
| 96 | + // It acts as a direct reference to the NodeReadinessRule that generated this report entry. |
| 97 | + // |
| 98 | + // +required |
| 99 | + // +kubebuilder:validation:MinLength=1 |
| 100 | + // +kubebuilder:validation:MaxLength=253 |
| 101 | + // +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` |
| 102 | + RuleName string `json:"ruleName,omitempty"` |
| 103 | + |
| 104 | + // reason contains a concise, machine-readable string detailing the primary outcome |
| 105 | + // of the evaluation (e.g., "SelectorMismatch", "CriteriaMet", "ConditionNotFound"). |
| 106 | + // |
| 107 | + // +optional |
| 108 | + // +kubebuilder:validation:MinLength=1 |
| 109 | + // +kubebuilder:validation:MaxLength=256 |
| 110 | + Reason string `json:"reason,omitempty"` |
| 111 | + |
| 112 | + // message is a comprehensive, human-readable explanation providing further |
| 113 | + // context about the evaluation result or any specific errors encountered. |
| 114 | + // |
| 115 | + // +optional |
| 116 | + // +kubebuilder:validation:MinLength=1 |
| 117 | + // +kubebuilder:validation:MaxLength=10240 |
| 118 | + Message string `json:"message,omitempty"` |
| 119 | + |
| 120 | + // ruleStatus indicates the overall outcome of the rule's criteria against the Node. |
| 121 | + // This reflects whether the Node successfully matched the rule's NodeSelector and Conditions. |
| 122 | + // |
| 123 | + // +required |
| 124 | + RuleStatus RuleStatus `json:"ruleStatus,omitempty"` |
| 125 | + |
| 126 | + // taintStatus reflects the observed state of the rule's specified taint on the Node. |
| 127 | + // It indicates whether the taint is currently Present or Absent. |
| 128 | + // |
| 129 | + // +required |
| 130 | + TaintStatus TaintStatus `json:"taintStatus,omitempty"` |
| 131 | + |
| 132 | + // lastEvaluationTime records the exact moment the controller most recently |
| 133 | + // assessed this rule against the Node. This helps identify stale reports. |
| 134 | + // |
| 135 | + // +required |
| 136 | + LastEvaluationTime metav1.Time `json:"lastEvaluationTime,omitempty,omitzero"` |
| 137 | +} |
| 138 | + |
| 139 | +// ReportSummary aggregates the results to provide a high-level overview. |
| 140 | +// +kubebuilder:validation:MinProperties=1 |
| 141 | +type ReportSummary struct { |
| 142 | + // matchedRules is the total number of rules currently matching this node. |
| 143 | + // |
| 144 | + // +optional |
| 145 | + // +kubebuilder:validation:Minimum=0 |
| 146 | + MatchedRules *int32 `json:"matchedRules,omitempty"` |
| 147 | + |
| 148 | + // unMatchedRules is the total number of rules currently not matching this node. |
| 149 | + // |
| 150 | + // +optional |
| 151 | + // +kubebuilder:validation:Minimum=0 |
| 152 | + UnMatchedRules *int32 `json:"unMatchedRules,omitempty"` |
| 153 | + |
| 154 | + // appliedTaints is the total number of taints successfully applied by the controller. |
| 155 | + // |
| 156 | + // +optional |
| 157 | + // +kubebuilder:validation:Minimum=0 |
| 158 | + AppliedTaints *int32 `json:"appliedTaints,omitempty"` |
| 159 | + |
| 160 | + // errors is the total number of rules that failed to evaluate properly. |
| 161 | + // |
| 162 | + // +optional |
| 163 | + // +kubebuilder:validation:Minimum=0 |
| 164 | + Errors *int32 `json:"errors,omitempty"` |
| 165 | +} |
| 166 | + |
| 167 | +// +kubebuilder:object:root=true |
| 168 | + |
| 169 | +// NodeReadinessRuleReportList contains a list of NodeReadinessRuleReport. |
| 170 | +type NodeReadinessRuleReportList struct { |
| 171 | + metav1.TypeMeta `json:",inline"` |
| 172 | + metav1.ListMeta `json:"metadata,omitzero"` |
| 173 | + Items []NodeReadinessRuleReport `json:"items"` |
| 174 | +} |
| 175 | + |
| 176 | +func init() { |
| 177 | + objectTypes = append(objectTypes, &NodeReadinessRuleReport{}, &NodeReadinessRuleReportList{}) |
| 178 | +} |
0 commit comments