|
| 1 | +// Copyright Istio 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 v1alpha1 |
| 16 | + |
| 17 | +import ( |
| 18 | + "time" |
| 19 | + |
| 20 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| 21 | +) |
| 22 | + |
| 23 | +const ( |
| 24 | + ZTunnelKind = "ZTunnel" |
| 25 | +) |
| 26 | + |
| 27 | +// ZTunnelSpec defines the desired state of ZTunnel |
| 28 | +type ZTunnelSpec struct { |
| 29 | + // +sail:version |
| 30 | + // Defines the version of Istio to install. |
| 31 | + // Must be one of: v1.24.0 or latest. |
| 32 | + // +operator-sdk:csv:customresourcedefinitions:type=spec,order=1,displayName="Istio Version",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:fieldGroup:General", "urn:alm:descriptor:com.tectonic.ui:select:v1.24.0", "urn:alm:descriptor:com.tectonic.ui:select:latest"} |
| 33 | + // +kubebuilder:validation:Enum=v1.24.0;latest |
| 34 | + // +kubebuilder:default=v1.24.0 |
| 35 | + Version string `json:"version"` |
| 36 | + |
| 37 | + // +sail:profile |
| 38 | + // The built-in installation configuration profile to use. |
| 39 | + // The 'default' profile is 'ambient' and it is always applied. |
| 40 | + // Must be one of: ambient, default, demo, empty, external, preview, remote, stable. |
| 41 | + // +++PROFILES-DROPDOWN-HIDDEN-UNTIL-WE-FULLY-IMPLEMENT-THEM+++operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Profile",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:fieldGroup:General", "urn:alm:descriptor:com.tectonic.ui:select:ambient", "urn:alm:descriptor:com.tectonic.ui:select:default", "urn:alm:descriptor:com.tectonic.ui:select:demo", "urn:alm:descriptor:com.tectonic.ui:select:empty", "urn:alm:descriptor:com.tectonic.ui:select:external", "urn:alm:descriptor:com.tectonic.ui:select:minimal", "urn:alm:descriptor:com.tectonic.ui:select:preview", "urn:alm:descriptor:com.tectonic.ui:select:remote"} |
| 42 | + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:hidden"} |
| 43 | + // +kubebuilder:validation:Enum=ambient;default;demo;empty;external;openshift-ambient;openshift;preview;remote;stable |
| 44 | + // +kubebuilder:default=ambient |
| 45 | + Profile string `json:"profile,omitempty"` |
| 46 | + |
| 47 | + // Namespace to which the Istio ztunnel component should be installed. |
| 48 | + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:Namespace"} |
| 49 | + // +kubebuilder:default=ztunnel |
| 50 | + Namespace string `json:"namespace"` |
| 51 | + |
| 52 | + // Defines the values to be passed to the Helm charts when installing Istio ztunnel. |
| 53 | + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Helm Values" |
| 54 | + Values *ZTunnelValues `json:"values,omitempty"` |
| 55 | +} |
| 56 | + |
| 57 | +// ZTunnelStatus defines the observed state of ZTunnel |
| 58 | +type ZTunnelStatus struct { |
| 59 | + // ObservedGeneration is the most recent generation observed for this |
| 60 | + // ZTunnel object. It corresponds to the object's generation, which is |
| 61 | + // updated on mutation by the API Server. The information in the status |
| 62 | + // pertains to this particular generation of the object. |
| 63 | + ObservedGeneration int64 `json:"observedGeneration,omitempty"` |
| 64 | + |
| 65 | + // Represents the latest available observations of the object's current state. |
| 66 | + Conditions []ZTunnelCondition `json:"conditions,omitempty"` |
| 67 | + |
| 68 | + // Reports the current state of the object. |
| 69 | + State ZTunnelConditionReason `json:"state,omitempty"` |
| 70 | +} |
| 71 | + |
| 72 | +// GetCondition returns the condition of the specified type |
| 73 | +func (s *ZTunnelStatus) GetCondition(conditionType ZTunnelConditionType) ZTunnelCondition { |
| 74 | + if s != nil { |
| 75 | + for i := range s.Conditions { |
| 76 | + if s.Conditions[i].Type == conditionType { |
| 77 | + return s.Conditions[i] |
| 78 | + } |
| 79 | + } |
| 80 | + } |
| 81 | + return ZTunnelCondition{Type: conditionType, Status: metav1.ConditionUnknown} |
| 82 | +} |
| 83 | + |
| 84 | +// SetCondition sets a specific condition in the list of conditions |
| 85 | +func (s *ZTunnelStatus) SetCondition(condition ZTunnelCondition) { |
| 86 | + var now time.Time |
| 87 | + if testTime == nil { |
| 88 | + now = time.Now() |
| 89 | + } else { |
| 90 | + now = *testTime |
| 91 | + } |
| 92 | + |
| 93 | + // The lastTransitionTime only gets serialized out to the second. This can |
| 94 | + // break update skipping, as the time in the resource returned from the client |
| 95 | + // may not match the time in our cached status during a reconcile. We truncate |
| 96 | + // here to save any problems down the line. |
| 97 | + lastTransitionTime := metav1.NewTime(now.Truncate(time.Second)) |
| 98 | + |
| 99 | + for i, prevCondition := range s.Conditions { |
| 100 | + if prevCondition.Type == condition.Type { |
| 101 | + if prevCondition.Status != condition.Status { |
| 102 | + condition.LastTransitionTime = lastTransitionTime |
| 103 | + } else { |
| 104 | + condition.LastTransitionTime = prevCondition.LastTransitionTime |
| 105 | + } |
| 106 | + s.Conditions[i] = condition |
| 107 | + return |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | + // If the condition does not exist, initialize the lastTransitionTime |
| 112 | + condition.LastTransitionTime = lastTransitionTime |
| 113 | + s.Conditions = append(s.Conditions, condition) |
| 114 | +} |
| 115 | + |
| 116 | +// ZTunnelCondition represents a specific observation of the ZTunnel object's state. |
| 117 | +type ZTunnelCondition struct { |
| 118 | + // The type of this condition. |
| 119 | + Type ZTunnelConditionType `json:"type,omitempty"` |
| 120 | + |
| 121 | + // The status of this condition. Can be True, False or Unknown. |
| 122 | + Status metav1.ConditionStatus `json:"status,omitempty"` |
| 123 | + |
| 124 | + // Unique, single-word, CamelCase reason for the condition's last transition. |
| 125 | + Reason ZTunnelConditionReason `json:"reason,omitempty"` |
| 126 | + |
| 127 | + // Human-readable message indicating details about the last transition. |
| 128 | + Message string `json:"message,omitempty"` |
| 129 | + |
| 130 | + // Last time the condition transitioned from one status to another. |
| 131 | + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` |
| 132 | +} |
| 133 | + |
| 134 | +// ZTunnelConditionType represents the type of the condition. Condition stages are: |
| 135 | +// Installed, Reconciled, Ready |
| 136 | +type ZTunnelConditionType string |
| 137 | + |
| 138 | +// ZTunnelConditionReason represents a short message indicating how the condition came |
| 139 | +// to be in its present state. |
| 140 | +type ZTunnelConditionReason string |
| 141 | + |
| 142 | +const ( |
| 143 | + // ZTunnelConditionReconciled signifies whether the controller has |
| 144 | + // successfully reconciled the resources defined through the CR. |
| 145 | + ZTunnelConditionReconciled ZTunnelConditionType = "Reconciled" |
| 146 | + |
| 147 | + // ZTunnelReasonReconcileError indicates that the reconciliation of the resource has failed, but will be retried. |
| 148 | + ZTunnelReasonReconcileError ZTunnelConditionReason = "ReconcileError" |
| 149 | +) |
| 150 | + |
| 151 | +const ( |
| 152 | + // ZTunnelConditionReady signifies whether the ztunnel DaemonSet is ready. |
| 153 | + ZTunnelConditionReady ZTunnelConditionType = "Ready" |
| 154 | + |
| 155 | + // ZTunnelDaemonSetNotReady indicates that the ztunnel DaemonSet is not ready. |
| 156 | + ZTunnelDaemonSetNotReady ZTunnelConditionReason = "DaemonSetNotReady" |
| 157 | + |
| 158 | + // ZTunnelReasonReadinessCheckFailed indicates that the DaemonSet readiness status could not be ascertained. |
| 159 | + ZTunnelReasonReadinessCheckFailed ZTunnelConditionReason = "ReadinessCheckFailed" |
| 160 | +) |
| 161 | + |
| 162 | +const ( |
| 163 | + // ZTunnelReasonHealthy indicates that the control plane is fully reconciled and that all components are ready. |
| 164 | + ZTunnelReasonHealthy ZTunnelConditionReason = "Healthy" |
| 165 | +) |
| 166 | + |
| 167 | +// +kubebuilder:object:root=true |
| 168 | +// +kubebuilder:resource:scope=Cluster,categories=istio-io |
| 169 | +// +kubebuilder:subresource:status |
| 170 | +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Whether the Istio ztunnel installation is ready to handle requests." |
| 171 | +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.state",description="The current state of this object." |
| 172 | +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.version",description="The version of the Istio ztunnel installation." |
| 173 | +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" |
| 174 | +// +kubebuilder:validation:XValidation:rule="self.metadata.name == 'default'",message="metadata.name must be 'default'" |
| 175 | + |
| 176 | +// ZTunnel represents a deployment of the Istio ztunnel component. |
| 177 | +type ZTunnel struct { |
| 178 | + metav1.TypeMeta `json:",inline"` |
| 179 | + metav1.ObjectMeta `json:"metadata,omitempty"` |
| 180 | + |
| 181 | + // +kubebuilder:default={version: "v1.24.0", namespace: "ztunnel", profile: "ambient"} |
| 182 | + Spec ZTunnelSpec `json:"spec,omitempty"` |
| 183 | + |
| 184 | + Status ZTunnelStatus `json:"status,omitempty"` |
| 185 | +} |
| 186 | + |
| 187 | +// +kubebuilder:object:root=true |
| 188 | + |
| 189 | +// ZTunnelList contains a list of ZTunnel |
| 190 | +type ZTunnelList struct { |
| 191 | + metav1.TypeMeta `json:",inline"` |
| 192 | + metav1.ListMeta `json:"metadata,omitempty"` |
| 193 | + Items []ZTunnel `json:"items"` |
| 194 | +} |
| 195 | + |
| 196 | +func init() { |
| 197 | + SchemeBuilder.Register(&ZTunnel{}, &ZTunnelList{}) |
| 198 | +} |
0 commit comments