1 package v1 2 3 import ( 4 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 ) 6 7 // +genclient 8 // +genclient:nonNamespaced 9 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 10 11 // Ingress holds cluster-wide information about ingress, including the default ingress domain 12 // used for routes. The canonical name is `cluster`. 13 // 14 // Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). 15 // +openshift:compatibility-gen:level=1 16 type Ingress struct { 17 metav1.TypeMeta `json:",inline"` 18 19 // metadata is the standard object's metadata. 20 // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 21 metav1.ObjectMeta `json:"metadata,omitempty"` 22 23 // spec holds user settable values for configuration 24 // +kubebuilder:validation:Required 25 // +required 26 Spec IngressSpec `json:"spec"` 27 // status holds observed values from the cluster. They may not be overridden. 28 // +optional 29 Status IngressStatus `json:"status"` 30 } 31 32 type IngressSpec struct { 33 // domain is used to generate a default host name for a route when the 34 // route's host name is empty. The generated host name will follow this 35 // pattern: "<route-name>.<route-namespace>.<domain>". 36 // 37 // It is also used as the default wildcard domain suffix for ingress. The 38 // default ingresscontroller domain will follow this pattern: "*.<domain>". 39 // 40 // Once set, changing domain is not currently supported. 41 Domain string `json:"domain"` 42 43 // appsDomain is an optional domain to use instead of the one specified 44 // in the domain field when a Route is created without specifying an explicit 45 // host. If appsDomain is nonempty, this value is used to generate default 46 // host values for Route. Unlike domain, appsDomain may be modified after 47 // installation. 48 // This assumes a new ingresscontroller has been setup with a wildcard 49 // certificate. 50 // +optional 51 AppsDomain string `json:"appsDomain,omitempty"` 52 53 // componentRoutes is an optional list of routes that are managed by OpenShift components 54 // that a cluster-admin is able to configure the hostname and serving certificate for. 55 // The namespace and name of each route in this list should match an existing entry in the 56 // status.componentRoutes list. 57 // 58 // To determine the set of configurable Routes, look at namespace and name of entries in the 59 // .status.componentRoutes list, where participating operators write the status of 60 // configurable routes. 61 // +optional 62 // +listType=map 63 // +listMapKey=namespace 64 // +listMapKey=name 65 ComponentRoutes []ComponentRouteSpec `json:"componentRoutes,omitempty"` 66 67 // requiredHSTSPolicies specifies HSTS policies that are required to be set on newly created or updated routes 68 // matching the domainPattern/s and namespaceSelector/s that are specified in the policy. 69 // Each requiredHSTSPolicy must have at least a domainPattern and a maxAge to validate a route HSTS Policy route 70 // annotation, and affect route admission. 71 // 72 // A candidate route is checked for HSTS Policies if it has the HSTS Policy route annotation: 73 // "haproxy.router.openshift.io/hsts_header" 74 // E.g. haproxy.router.openshift.io/hsts_header: max-age=31536000;preload;includeSubDomains 75 // 76 // - For each candidate route, if it matches a requiredHSTSPolicy domainPattern and optional namespaceSelector, 77 // then the maxAge, preloadPolicy, and includeSubdomainsPolicy must be valid to be admitted. Otherwise, the route 78 // is rejected. 79 // - The first match, by domainPattern and optional namespaceSelector, in the ordering of the RequiredHSTSPolicies 80 // determines the route's admission status. 81 // - If the candidate route doesn't match any requiredHSTSPolicy domainPattern and optional namespaceSelector, 82 // then it may use any HSTS Policy annotation. 83 // 84 // The HSTS policy configuration may be changed after routes have already been created. An update to a previously 85 // admitted route may then fail if the updated route does not conform to the updated HSTS policy configuration. 86 // However, changing the HSTS policy configuration will not cause a route that is already admitted to stop working. 87 // 88 // Note that if there are no RequiredHSTSPolicies, any HSTS Policy annotation on the route is valid. 89 // +optional 90 RequiredHSTSPolicies []RequiredHSTSPolicy `json:"requiredHSTSPolicies,omitempty"` 91 92 // loadBalancer contains the load balancer details in general which are not only specific to the underlying infrastructure 93 // provider of the current cluster and are required for Ingress Controller to work on OpenShift. 94 // +optional 95 LoadBalancer LoadBalancer `json:"loadBalancer,omitempty"` 96 } 97 98 // IngressPlatformSpec holds the desired state of Ingress specific to the underlying infrastructure provider 99 // of the current cluster. Since these are used at spec-level for the underlying cluster, it 100 // is supposed that only one of the spec structs is set. 101 // +union 102 type IngressPlatformSpec struct { 103 // type is the underlying infrastructure provider for the cluster. 104 // Allowed values are "AWS", "Azure", "BareMetal", "GCP", "Libvirt", 105 // "OpenStack", "VSphere", "oVirt", "KubeVirt", "EquinixMetal", "PowerVS", 106 // "AlibabaCloud", "Nutanix" and "None". Individual components may not support all platforms, 107 // and must handle unrecognized platforms as None if they do not support that platform. 108 // 109 // +unionDiscriminator 110 Type PlatformType `json:"type"` 111 112 // aws contains settings specific to the Amazon Web Services infrastructure provider. 113 // +optional 114 AWS *AWSIngressSpec `json:"aws,omitempty"` 115 } 116 117 type LoadBalancer struct { 118 // platform holds configuration specific to the underlying 119 // infrastructure provider for the ingress load balancers. 120 // When omitted, this means the user has no opinion and the platform is left 121 // to choose reasonable defaults. These defaults are subject to change over time. 122 // +optional 123 Platform IngressPlatformSpec `json:"platform,omitempty"` 124 } 125 126 // AWSIngressSpec holds the desired state of the Ingress for Amazon Web Services infrastructure provider. 127 // This only includes fields that can be modified in the cluster. 128 // +union 129 type AWSIngressSpec struct { 130 // type allows user to set a load balancer type. 131 // When this field is set the default ingresscontroller will get created using the specified LBType. 132 // If this field is not set then the default ingress controller of LBType Classic will be created. 133 // Valid values are: 134 // 135 // * "Classic": A Classic Load Balancer that makes routing decisions at either 136 // the transport layer (TCP/SSL) or the application layer (HTTP/HTTPS). See 137 // the following for additional details: 138 // 139 // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#clb 140 // 141 // * "NLB": A Network Load Balancer that makes routing decisions at the 142 // transport layer (TCP/SSL). See the following for additional details: 143 // 144 // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/load-balancer-types.html#nlb 145 // +unionDiscriminator 146 // +kubebuilder:validation:Enum:=NLB;Classic 147 // +kubebuilder:validation:Required 148 Type AWSLBType `json:"type,omitempty"` 149 } 150 151 type AWSLBType string 152 153 const ( 154 // NLB is the Network Load Balancer Type of AWS. Using NLB one can set NLB load balancer type for the default ingress controller. 155 NLB AWSLBType = "NLB" 156 157 // Classic is the Classic Load Balancer Type of AWS. Using CLassic one can set Classic load balancer type for the default ingress controller. 158 Classic AWSLBType = "Classic" 159 ) 160 161 // ConsumingUser is an alias for string which we add validation to. Currently only service accounts are supported. 162 // +kubebuilder:validation:Pattern="^system:serviceaccount:[a-z0-9]([-a-z0-9]*[a-z0-9])?:[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" 163 // +kubebuilder:validation:MinLength=1 164 // +kubebuilder:validation:MaxLength=512 165 type ConsumingUser string 166 167 // Hostname is an alias for hostname string validation. 168 // 169 // The left operand of the | is the original kubebuilder hostname validation format, which is incorrect because it 170 // allows upper case letters, disallows hyphen or number in the TLD, and allows labels to start/end in non-alphanumeric 171 // characters. See https://bugzilla.redhat.com/show_bug.cgi?id=2039256. 172 // ^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$ 173 // 174 // The right operand of the | is a new pattern that mimics the current API route admission validation on hostname, 175 // except that it allows hostnames longer than the maximum length: 176 // ^(([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})[\.]){0,}([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})$ 177 // 178 // Both operand patterns are made available so that modifications on ingress spec can still happen after an invalid hostname 179 // was saved via validation by the incorrect left operand of the | operator. 180 // 181 // +kubebuilder:validation:Pattern=`^([a-zA-Z0-9\p{S}\p{L}]((-?[a-zA-Z0-9\p{S}\p{L}]{0,62})?)|([a-zA-Z0-9\p{S}\p{L}](([a-zA-Z0-9-\p{S}\p{L}]{0,61}[a-zA-Z0-9\p{S}\p{L}])?)(\.)){1,}([a-zA-Z\p{L}]){2,63})$|^(([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})[\.]){0,}([a-z0-9][-a-z0-9]{0,61}[a-z0-9]|[a-z0-9]{1,63})$` 182 type Hostname string 183 184 type IngressStatus struct { 185 // componentRoutes is where participating operators place the current route status for routes whose 186 // hostnames and serving certificates can be customized by the cluster-admin. 187 // +optional 188 // +listType=map 189 // +listMapKey=namespace 190 // +listMapKey=name 191 ComponentRoutes []ComponentRouteStatus `json:"componentRoutes,omitempty"` 192 193 // defaultPlacement is set at installation time to control which 194 // nodes will host the ingress router pods by default. The options are 195 // control-plane nodes or worker nodes. 196 // 197 // This field works by dictating how the Cluster Ingress Operator will 198 // consider unset replicas and nodePlacement fields in IngressController 199 // resources when creating the corresponding Deployments. 200 // 201 // See the documentation for the IngressController replicas and nodePlacement 202 // fields for more information. 203 // 204 // When omitted, the default value is Workers 205 // 206 // +kubebuilder:validation:Enum:="ControlPlane";"Workers";"" 207 // +optional 208 DefaultPlacement DefaultPlacement `json:"defaultPlacement"` 209 } 210 211 // ComponentRouteSpec allows for configuration of a route's hostname and serving certificate. 212 type ComponentRouteSpec struct { 213 // namespace is the namespace of the route to customize. 214 // 215 // The namespace and name of this componentRoute must match a corresponding 216 // entry in the list of status.componentRoutes if the route is to be customized. 217 // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ 218 // +kubebuilder:validation:MinLength=1 219 // +kubebuilder:validation:MaxLength=63 220 // +kubebuilder:validation:Required 221 // +required 222 Namespace string `json:"namespace"` 223 224 // name is the logical name of the route to customize. 225 // 226 // The namespace and name of this componentRoute must match a corresponding 227 // entry in the list of status.componentRoutes if the route is to be customized. 228 // +kubebuilder:validation:MinLength=1 229 // +kubebuilder:validation:MaxLength=256 230 // +kubebuilder:validation:Required 231 // +required 232 Name string `json:"name"` 233 234 // hostname is the hostname that should be used by the route. 235 // +kubebuilder:validation:Required 236 // +required 237 Hostname Hostname `json:"hostname"` 238 239 // servingCertKeyPairSecret is a reference to a secret of type `kubernetes.io/tls` in the openshift-config namespace. 240 // The serving cert/key pair must match and will be used by the operator to fulfill the intent of serving with this name. 241 // If the custom hostname uses the default routing suffix of the cluster, 242 // the Secret specification for a serving certificate will not be needed. 243 // +optional 244 ServingCertKeyPairSecret SecretNameReference `json:"servingCertKeyPairSecret"` 245 } 246 247 // ComponentRouteStatus contains information allowing configuration of a route's hostname and serving certificate. 248 type ComponentRouteStatus struct { 249 // namespace is the namespace of the route to customize. It must be a real namespace. Using an actual namespace 250 // ensures that no two components will conflict and the same component can be installed multiple times. 251 // 252 // The namespace and name of this componentRoute must match a corresponding 253 // entry in the list of spec.componentRoutes if the route is to be customized. 254 // +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ 255 // +kubebuilder:validation:MinLength=1 256 // +kubebuilder:validation:MaxLength=63 257 // +kubebuilder:validation:Required 258 // +required 259 Namespace string `json:"namespace"` 260 261 // name is the logical name of the route to customize. It does not have to be the actual name of a route resource 262 // but it cannot be renamed. 263 // 264 // The namespace and name of this componentRoute must match a corresponding 265 // entry in the list of spec.componentRoutes if the route is to be customized. 266 // +kubebuilder:validation:MinLength=1 267 // +kubebuilder:validation:MaxLength=256 268 // +kubebuilder:validation:Required 269 // +required 270 Name string `json:"name"` 271 272 // defaultHostname is the hostname of this route prior to customization. 273 // +kubebuilder:validation:Required 274 // +required 275 DefaultHostname Hostname `json:"defaultHostname"` 276 277 // consumingUsers is a slice of ServiceAccounts that need to have read permission on the servingCertKeyPairSecret secret. 278 // +kubebuilder:validation:MaxItems=5 279 // +optional 280 ConsumingUsers []ConsumingUser `json:"consumingUsers,omitempty"` 281 282 // currentHostnames is the list of current names used by the route. Typically, this list should consist of a single 283 // hostname, but if multiple hostnames are supported by the route the operator may write multiple entries to this list. 284 // +kubebuilder:validation:MinItems=1 285 // +optional 286 CurrentHostnames []Hostname `json:"currentHostnames,omitempty"` 287 288 // conditions are used to communicate the state of the componentRoutes entry. 289 // 290 // Supported conditions include Available, Degraded and Progressing. 291 // 292 // If available is true, the content served by the route can be accessed by users. This includes cases 293 // where a default may continue to serve content while the customized route specified by the cluster-admin 294 // is being configured. 295 // 296 // If Degraded is true, that means something has gone wrong trying to handle the componentRoutes entry. 297 // The currentHostnames field may or may not be in effect. 298 // 299 // If Progressing is true, that means the component is taking some action related to the componentRoutes entry. 300 // +optional 301 // +listType=map 302 // +listMapKey=type 303 Conditions []metav1.Condition `json:"conditions,omitempty"` 304 305 // relatedObjects is a list of resources which are useful when debugging or inspecting how spec.componentRoutes is applied. 306 // +kubebuilder:validation:MinItems=1 307 // +kubebuilder:validation:Required 308 // +required 309 RelatedObjects []ObjectReference `json:"relatedObjects"` 310 } 311 312 // Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). 313 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 314 // +openshift:compatibility-gen:level=1 315 type IngressList struct { 316 metav1.TypeMeta `json:",inline"` 317 318 // metadata is the standard list's metadata. 319 // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata 320 metav1.ListMeta `json:"metadata"` 321 322 Items []Ingress `json:"items"` 323 } 324 325 // DefaultPlacement defines the default placement of ingress router pods. 326 type DefaultPlacement string 327 328 const ( 329 // "Workers" is for having router pods placed on worker nodes by default. 330 DefaultPlacementWorkers DefaultPlacement = "Workers" 331 332 // "ControlPlane" is for having router pods placed on control-plane nodes by default. 333 DefaultPlacementControlPlane DefaultPlacement = "ControlPlane" 334 ) 335