-
Notifications
You must be signed in to change notification settings - Fork 256
/
rabbitmqcluster_types.go
375 lines (330 loc) · 19.2 KB
/
rabbitmqcluster_types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
// RabbitMQ Cluster Operator
//
// Copyright 2020 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Mozilla Public license, Version 2.0 (the "License"). You may not use this product except in compliance with the Mozilla Public License.
//
// This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file.
package v1beta1
import (
"strconv"
"strings"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
k8sresource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +kubebuilder:object:root=true
// RabbitmqCluster is the Schema for the RabbitmqCluster API. Each instance of this object
// corresponds to a single RabbitMQ cluster.
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:resource:shortName={"rmq"}
type RabbitmqCluster struct {
// Embedded metadata identifying a Kind and API Verison of an object.
// For more info, see: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#TypeMeta
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// Spec is the desired state of the RabbitmqCluster Custom Resource.
Spec RabbitmqClusterSpec `json:"spec,omitempty"`
// Status presents the observed state of RabbitmqCluster
Status RabbitmqClusterStatus `json:"status,omitempty"`
}
// Spec is the desired state of the RabbitmqCluster Custom Resource.
type RabbitmqClusterSpec struct {
// Replicas is the number of nodes in the RabbitMQ cluster. Each node is deployed as a Replica in a StatefulSet. Only 1, 3, 5 replicas clusters are tested.
// This value should be an odd number to ensure the resultant cluster can establish exactly one quorum of nodes
// in the event of a fragmenting network partition.
// +optional
// +kubebuilder:validation:Minimum:=0
// +kubebuilder:default:=1
Replicas *int32 `json:"replicas,omitempty"`
// Image is the name of the RabbitMQ docker image to use for RabbitMQ nodes in the RabbitmqCluster.
// Must be provided together with ImagePullSecrets in order to use an image in a private registry.
// +kubebuilder:default:="rabbitmq:3.8.14-management"
Image string `json:"image,omitempty"`
// List of Secret resource containing access credentials to the registry for the RabbitMQ image. Required if the docker registry is private.
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
// The desired state of the Kubernetes Service to create for the cluster.
// +kubebuilder:default:={type: "ClusterIP"}
Service RabbitmqClusterServiceSpec `json:"service,omitempty"`
// The desired persistent storage configuration for each Pod in the cluster.
// +kubebuilder:default:={storage: "10Gi"}
Persistence RabbitmqClusterPersistenceSpec `json:"persistence,omitempty"`
// The desired compute resource requirements of Pods in the cluster.
// +kubebuilder:default:={limits: {cpu: "2000m", memory: "2Gi"}, requests: {cpu: "1000m", memory: "2Gi"}}
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
// Affinity scheduling rules to be applied on created Pods.
Affinity *corev1.Affinity `json:"affinity,omitempty"`
// Tolerations is the list of Toleration resources attached to each Pod in the RabbitmqCluster.
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
// Configuration options for RabbitMQ Pods created in the cluster.
Rabbitmq RabbitmqClusterConfigurationSpec `json:"rabbitmq,omitempty"`
// TLS-related configuration for the RabbitMQ cluster.
TLS TLSSpec `json:"tls,omitempty"`
// Provides the ability to override the generated manifest of several child resources.
Override RabbitmqClusterOverrideSpec `json:"override,omitempty"`
// If unset, or set to false, the cluster will run `rabbitmq-queues rebalance all` whenever the cluster is updated.
// Set to true to prevent the operator rebalancing queue leaders after a cluster update.
// Has no effect if the cluster only consists of one node.
// For more information, see https://www.rabbitmq.com/rabbitmq-queues.8.html#rebalance
SkipPostDeploySteps bool `json:"skipPostDeploySteps,omitempty"`
// TerminationGracePeriodSeconds is the timeout that each rabbitmqcluster pod will have to terminate gracefully.
// It defaults to 604800 seconds ( a week long) to ensure that the container preStop lifecycle hook can finish running.
// For more information, see: https://github.com/rabbitmq/cluster-operator/blob/main/docs/design/20200520-graceful-pod-termination.md
// +kubebuilder:validation:Minimum:=0
// +kubebuilder:default:=604800
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`
}
// Provides the ability to override the generated manifest of several child resources.
type RabbitmqClusterOverrideSpec struct {
// Override configuration for the RabbitMQ StatefulSet.
StatefulSet *StatefulSet `json:"statefulSet,omitempty"`
// Override configuration for the Service created to serve traffic to the cluster.
Service *Service `json:"service,omitempty"`
}
// Override configuration for the Service created to serve traffic to the cluster.
// Allows for the manifest of the created Service to be overwritten with custom configuration.
type Service struct {
// +optional
*EmbeddedLabelsAnnotations `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the behavior of a Service.
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec *corev1.ServiceSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
}
// Override configuration for the RabbitMQ StatefulSet.
// Allows for the manifest of the created StatefulSet to be overwritten with custom configuration.
type StatefulSet struct {
// +optional
*EmbeddedLabelsAnnotations `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the desired identities of pods in this set.
// +optional
Spec *StatefulSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
}
// StatefulSetSpec contains a subset of the fields included in k8s.io/api/apps/v1.StatefulSetSpec.
// Field RevisionHistoryLimit is omitted.
// Every field is made optional.
type StatefulSetSpec struct {
// replicas corresponds to the desired number of Pods in the StatefulSet.
// For more info, see https://pkg.go.dev/k8s.io/api/apps/v1#StatefulSetSpec
// +optional
Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`
// selector is a label query over pods that should match the replica count.
// It must match the pod template's labels.
// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
// +optional
Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"`
// template is the object that describes the pod that will be created if
// insufficient replicas are detected. Each pod stamped out by the StatefulSet
// will fulfill this Template, but have a unique identity from the rest
// of the StatefulSet.
// +optional
Template *PodTemplateSpec `json:"template,omitempty" protobuf:"bytes,3,opt,name=template"`
// volumeClaimTemplates is a list of claims that pods are allowed to reference.
// The StatefulSet controller is responsible for mapping network identities to
// claims in a way that maintains the identity of a pod. Every claim in
// this list must have at least one matching (by name) volumeMount in one
// container in the template. A claim in this list takes precedence over
// any volumes in the template, with the same name.
// +optional
VolumeClaimTemplates []PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty" protobuf:"bytes,4,rep,name=volumeClaimTemplates"`
// serviceName is the name of the service that governs this StatefulSet.
// This service must exist before the StatefulSet, and is responsible for
// the network identity of the set. Pods get DNS/hostnames that follow the
// pattern: pod-specific-string.serviceName.default.svc.cluster.local
// where "pod-specific-string" is managed by the StatefulSet controller.
// +optional
ServiceName string `json:"serviceName,omitempty" protobuf:"bytes,5,opt,name=serviceName"`
// podManagementPolicy controls how pods are created during initial scale up,
// when replacing pods on nodes, or when scaling down. The default policy is
// `OrderedReady`, where pods are created in increasing order (pod-0, then
// pod-1, etc) and the controller will wait until each pod is ready before
// continuing. When scaling down, the pods are removed in the opposite order.
// The alternative policy is `Parallel` which will create pods in parallel
// to match the desired scale without waiting, and on scale down will delete
// all pods at once.
// +optional
PodManagementPolicy appsv1.PodManagementPolicyType `json:"podManagementPolicy,omitempty" protobuf:"bytes,6,opt,name=podManagementPolicy,casttype=PodManagementPolicyType"`
// updateStrategy indicates the StatefulSetUpdateStrategy that will be
// employed to update Pods in the StatefulSet when a revision is made to
// Template.
// +optional
UpdateStrategy *appsv1.StatefulSetUpdateStrategy `json:"updateStrategy,omitempty" protobuf:"bytes,7,opt,name=updateStrategy"`
}
// EmbeddedLabelsAnnotations is an embedded subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta.
// Only labels and annotations are included.
type EmbeddedLabelsAnnotations struct {
// Map of string keys and values that can be used to organize and categorize
// (scope and select) objects. May match selectors of replication controllers
// and services.
// More info: http://kubernetes.io/docs/user-guide/labels
// +optional
Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"`
// Annotations is an unstructured key value map stored with a resource that may be
// set by external tools to store and retrieve arbitrary metadata. They are not
// queryable and should be preserved when modifying objects.
// More info: http://kubernetes.io/docs/user-guide/annotations
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"`
}
// EmbeddedObjectMeta is an embedded subset of the fields included in k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta.
// Only fields which are relevant to embedded resources are included.
type EmbeddedObjectMeta struct {
// Name must be unique within a namespace. Is required when creating resources, although
// some resources may allow a client to request the generation of an appropriate name
// automatically. Name is primarily intended for creation idempotence and configuration
// definition.
// Cannot be updated.
// More info: http://kubernetes.io/docs/user-guide/identifiers#names
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
// Namespace defines the space within each name must be unique. An empty namespace is
// equivalent to the "default" namespace, but "default" is the canonical representation.
// Not all objects are required to be scoped to a namespace - the value of this field for
// those objects will be empty.
//
// Must be a DNS_LABEL.
// Cannot be updated.
// More info: http://kubernetes.io/docs/user-guide/namespaces
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
// Map of string keys and values that can be used to organize and categorize
// (scope and select) objects. May match selectors of replication controllers
// and services.
// More info: http://kubernetes.io/docs/user-guide/labels
// +optional
Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,11,rep,name=labels"`
// Annotations is an unstructured key value map stored with a resource that may be
// set by external tools to store and retrieve arbitrary metadata. They are not
// queryable and should be preserved when modifying objects.
// More info: http://kubernetes.io/docs/user-guide/annotations
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,12,rep,name=annotations"`
}
// PodTemplateSpec is an embedded version of k8s.io/api/core/v1.PodTemplateSpec.
// It contains a reduced ObjectMeta.
type PodTemplateSpec struct {
// +optional
*EmbeddedObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the desired behavior of the pod.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
// +optional
Spec *corev1.PodSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
}
// PersistentVolumeClaim is an embedded version of k8s.io/api/core/v1.PersistentVolumeClaim.
// It contains TypeMeta and a reduced ObjectMeta.
// Field status is omitted.
type PersistentVolumeClaim struct {
// Embedded metadata identifying a Kind and API Verison of an object.
// For more info, see: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#TypeMeta
metav1.TypeMeta `json:",inline"`
// +optional
EmbeddedObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the desired characteristics of a volume requested by a pod author.
// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims
// +optional
Spec corev1.PersistentVolumeClaimSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
}
// Allows for the configuration of TLS certificates to be used by RabbitMQ. Also allows for non-TLS traffic to be disabled.
type TLSSpec struct {
// Name of a Secret in the same Namespace as the RabbitmqCluster, containing the server's private key & public certificate for TLS.
// The Secret must store these as tls.key and tls.crt, respectively.
// This Secret can be created by running `kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key`
SecretName string `json:"secretName,omitempty"`
// Name of a Secret in the same Namespace as the RabbitmqCluster, containing the Certificate Authority's public certificate for TLS.
// The Secret must store this as ca.crt.
// This Secret can be created by running `kubectl create secret generic ca-secret --from-file=ca.crt=path/to/ca.cert`
// Used for mTLS, and TLS for rabbitmq_web_stomp and rabbitmq_web_mqtt.
CaSecretName string `json:"caSecretName,omitempty"`
// When set to true, the RabbitmqCluster disables non-TLS listeners for RabbitMQ, management plugin and for any enabled plugins in the following list: stomp, mqtt, web_stomp, web_mqtt.
// Only TLS-enabled clients will be able to connect.
DisableNonTLSListeners bool `json:"disableNonTLSListeners,omitempty"`
}
// kubebuilder validating tags 'Pattern' and 'MaxLength' must be specified on string type.
// Alias type 'string' as 'Plugin' to specify schema validation on items of the list 'AdditionalPlugins'
// A Plugin to enable on the RabbitmqCluster.
// +kubebuilder:validation:Pattern:="^\\w+$"
// +kubebuilder:validation:MaxLength=100
type Plugin string
// RabbitMQ-related configuration.
type RabbitmqClusterConfigurationSpec struct {
// List of plugins to enable in addition to essential plugins: rabbitmq_management, rabbitmq_prometheus, and rabbitmq_peer_discovery_k8s.
// +kubebuilder:validation:MaxItems:=100
AdditionalPlugins []Plugin `json:"additionalPlugins,omitempty"`
// Modify to add to the rabbitmq.conf file in addition to default configurations set by the operator.
// Modifying this property on an existing RabbitmqCluster will trigger a StatefulSet rolling restart and will cause rabbitmq downtime.
// For more information on this config, see https://www.rabbitmq.com/configure.html#config-file
// +kubebuilder:validation:MaxLength:=2000
AdditionalConfig string `json:"additionalConfig,omitempty"`
// Specify any rabbitmq advanced.config configurations to apply to the cluster.
// For more information on advanced config, see https://www.rabbitmq.com/configure.html#advanced-config-file
// +kubebuilder:validation:MaxLength:=100000
AdvancedConfig string `json:"advancedConfig,omitempty"`
// Modify to add to the rabbitmq-env.conf file. Modifying this property on an existing RabbitmqCluster will trigger a StatefulSet rolling restart and will cause rabbitmq downtime.
// For more information on env config, see https://www.rabbitmq.com/man/rabbitmq-env.conf.5.html
// +kubebuilder:validation:MaxLength:=100000
EnvConfig string `json:"envConfig,omitempty"`
}
// The settings for the persistent storage desired for each Pod in the RabbitmqCluster.
type RabbitmqClusterPersistenceSpec struct {
// The name of the StorageClass to claim a PersistentVolume from.
StorageClassName *string `json:"storageClassName,omitempty"`
// The requested size of the persistent volume attached to each Pod in the RabbitmqCluster.
// The format of this field matches that defined by kubernetes/apimachinery.
// See https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity for more info on the format of this field.
// +kubebuilder:default:="10Gi"
Storage *k8sresource.Quantity `json:"storage,omitempty"`
}
// Settable attributes for the Service resource.
type RabbitmqClusterServiceSpec struct {
// Type of Service to create for the cluster. Must be one of: ClusterIP, LoadBalancer, NodePort.
// For more info see https://pkg.go.dev/k8s.io/api/core/v1#ServiceType
// +kubebuilder:validation:Enum=ClusterIP;LoadBalancer;NodePort
// +kubebuilder:default:="ClusterIP"
Type corev1.ServiceType `json:"type,omitempty"`
// Annotations to add to the Service.
Annotations map[string]string `json:"annotations,omitempty"`
}
func (cluster *RabbitmqCluster) TLSEnabled() bool {
return cluster.Spec.TLS.SecretName != ""
}
func (cluster *RabbitmqCluster) MutualTLSEnabled() bool {
return cluster.TLSEnabled() && cluster.Spec.TLS.CaSecretName != ""
}
func (cluster *RabbitmqCluster) MemoryLimited() bool {
return cluster.Spec.Resources != nil && cluster.Spec.Resources.Limits != nil && !cluster.Spec.Resources.Limits.Memory().IsZero()
}
func (cluster *RabbitmqCluster) SingleTLSSecret() bool {
return cluster.MutualTLSEnabled() && cluster.Spec.TLS.CaSecretName == cluster.Spec.TLS.SecretName
}
func (cluster *RabbitmqCluster) DisableNonTLSListeners() bool {
return cluster.Spec.TLS.DisableNonTLSListeners
}
func (cluster *RabbitmqCluster) AdditionalPluginEnabled(plugin Plugin) bool {
for _, p := range cluster.Spec.Rabbitmq.AdditionalPlugins {
if p == plugin {
return true
}
}
return false
}
// +kubebuilder:object:root=true
// RabbitmqClusterList contains a list of RabbitmqClusters.
type RabbitmqClusterList struct {
// Embedded metadata identifying a Kind and API Verison of an object.
// For more info, see: https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#TypeMeta
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
// Array of RabbitmqCluster resources.
Items []RabbitmqCluster `json:"items"`
}
func (cluster RabbitmqCluster) ChildResourceName(name string) string {
return strings.TrimSuffix(strings.Join([]string{cluster.Name, name}, "-"), "-")
}
func (cluster RabbitmqCluster) PVCName(i int) string {
return strings.Join([]string{"persistence", cluster.Name, "server", strconv.Itoa(i)}, "-")
}
func init() {
SchemeBuilder.Register(&RabbitmqCluster{}, &RabbitmqClusterList{})
}