Add Rabbitmq
Change-Id: I9edabda696c341d86936e3ded06c5fd2e2cc94ed
This commit is contained in:
@@ -12,6 +12,8 @@
|
|||||||
repository: vexxhost/memcached
|
repository: vexxhost/memcached
|
||||||
- context: images/memcached_exporter
|
- context: images/memcached_exporter
|
||||||
repository: vexxhost/memcached_exporter
|
repository: vexxhost/memcached_exporter
|
||||||
|
- context: images/rabbitmq
|
||||||
|
repository: vexxhost/rabbitmq
|
||||||
- context: .
|
- context: .
|
||||||
repository: vexxhost/openstack-operator
|
repository: vexxhost/openstack-operator
|
||||||
|
|
||||||
@@ -65,4 +67,4 @@
|
|||||||
- openstack-operator:images:upload
|
- openstack-operator:images:upload
|
||||||
promote:
|
promote:
|
||||||
jobs:
|
jobs:
|
||||||
- openstack-operator:images:promote
|
- openstack-operator:images:promote
|
4
Makefile
4
Makefile
@@ -86,4 +86,6 @@ images:
|
|||||||
docker build images/mcrouter -t vexxhost/mcrouter:latest
|
docker build images/mcrouter -t vexxhost/mcrouter:latest
|
||||||
docker build images/mcrouter_exporter -t vexxhost/mcrouter_exporter:latest
|
docker build images/mcrouter_exporter -t vexxhost/mcrouter_exporter:latest
|
||||||
docker build images/memcached -t vexxhost/memcached:latest
|
docker build images/memcached -t vexxhost/memcached:latest
|
||||||
docker build images/memcached_exporter -t vexxhost/memcached_exporter:latest
|
docker build images/memcached_exporter -t vexxhost/memcached_exporter:latest
|
||||||
|
docker build images/rabbitmq -t vexxhost/rabbitmq:latest
|
||||||
|
|
||||||
|
65
api/v1alpha1/rabbitmq_type.go
Normal file
65
api/v1alpha1/rabbitmq_type.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RabbitmqPolicySpec defines the Rabbitmq Policy Spec for the Vhost
|
||||||
|
type RabbitmqPolicyDefinitionSpec struct {
|
||||||
|
Vhost string `json:"vhost,omitempty"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Pattern string `json:"pattern"`
|
||||||
|
Definition RabbitmqPolicyDefinition `json:"definition"`
|
||||||
|
Priority int64 `json:"priority"`
|
||||||
|
ApplyTo string `json:"apply-to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RabbitmqPolicyDefinition defines the Rabbitmq Policy content
|
||||||
|
type RabbitmqPolicyDefinition struct {
|
||||||
|
FederationUpstreamSet string `json:"federation-upstream-set,omitempty"`
|
||||||
|
HaMode string `json:"ha-mode,omitempty"`
|
||||||
|
HaParams int `json:"ha-params,omitempty"`
|
||||||
|
HaSyncMode string `json:"ha-sync-mode,omitempty"`
|
||||||
|
Expires int `json:"expires,omitempty"`
|
||||||
|
MessageTTL int `json:"message-ttl,omitempty"`
|
||||||
|
MaxLen int `json:"max-length,omitempty"`
|
||||||
|
MaxLenBytes int `json:"max-length-bytes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RabbitmqSpec defines the desired state of Rabbitmq
|
||||||
|
type RabbitmqSpec struct {
|
||||||
|
AuthSecret string `json:"authSecret"`
|
||||||
|
Policies []RabbitmqPolicyDefinitionSpec `json:"policies,omitempty"`
|
||||||
|
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||||
|
Tolerations []v1.Toleration `json:"tolerations,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RabbitmqStatus defines the observed state of Rabbitmq
|
||||||
|
type RabbitmqStatus struct {
|
||||||
|
// +kubebuilder:validation:Default=Pending
|
||||||
|
Phase string `json:"phase"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rabbitmq is the Schema for the Rabbitmqs API
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
type Rabbitmq struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
Spec RabbitmqSpec `json:"spec,omitempty"`
|
||||||
|
Status RabbitmqStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// RabbitmqList contains a list of Rabbitmq
|
||||||
|
type RabbitmqList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitempty"`
|
||||||
|
Items []Rabbitmq `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&Rabbitmq{}, &RabbitmqList{})
|
||||||
|
}
|
@@ -257,3 +257,142 @@ func (in *MemcachedStatus) DeepCopy() *MemcachedStatus {
|
|||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *Rabbitmq) DeepCopyInto(out *Rabbitmq) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
|
out.Status = in.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rabbitmq.
|
||||||
|
func (in *Rabbitmq) DeepCopy() *Rabbitmq {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(Rabbitmq)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *Rabbitmq) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RabbitmqList) DeepCopyInto(out *RabbitmqList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]Rabbitmq, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RabbitmqList.
|
||||||
|
func (in *RabbitmqList) DeepCopy() *RabbitmqList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RabbitmqList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *RabbitmqList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RabbitmqPolicyDefinition) DeepCopyInto(out *RabbitmqPolicyDefinition) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RabbitmqPolicyDefinition.
|
||||||
|
func (in *RabbitmqPolicyDefinition) DeepCopy() *RabbitmqPolicyDefinition {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RabbitmqPolicyDefinition)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RabbitmqPolicyDefinitionSpec) DeepCopyInto(out *RabbitmqPolicyDefinitionSpec) {
|
||||||
|
*out = *in
|
||||||
|
out.Definition = in.Definition
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RabbitmqPolicyDefinitionSpec.
|
||||||
|
func (in *RabbitmqPolicyDefinitionSpec) DeepCopy() *RabbitmqPolicyDefinitionSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RabbitmqPolicyDefinitionSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RabbitmqSpec) DeepCopyInto(out *RabbitmqSpec) {
|
||||||
|
*out = *in
|
||||||
|
if in.Policies != nil {
|
||||||
|
in, out := &in.Policies, &out.Policies
|
||||||
|
*out = make([]RabbitmqPolicyDefinitionSpec, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.NodeSelector != nil {
|
||||||
|
in, out := &in.NodeSelector, &out.NodeSelector
|
||||||
|
*out = make(map[string]string, len(*in))
|
||||||
|
for key, val := range *in {
|
||||||
|
(*out)[key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if in.Tolerations != nil {
|
||||||
|
in, out := &in.Tolerations, &out.Tolerations
|
||||||
|
*out = make([]v1.Toleration, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RabbitmqSpec.
|
||||||
|
func (in *RabbitmqSpec) DeepCopy() *RabbitmqSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RabbitmqSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *RabbitmqStatus) DeepCopyInto(out *RabbitmqStatus) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RabbitmqStatus.
|
||||||
|
func (in *RabbitmqStatus) DeepCopy() *RabbitmqStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(RabbitmqStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
@@ -133,6 +133,47 @@ func (c *ContainerBuilder) Probe(handler v1.Handler, readyInterval int32, liveIn
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EnvVarFromString register one environment variable set from the string pair.
|
||||||
|
func (c *ContainerBuilder) EnvVarFromString(name string, value string) *ContainerBuilder {
|
||||||
|
c.obj.Env = append(c.obj.Env, corev1.EnvVar{
|
||||||
|
Name: name,
|
||||||
|
Value: value,
|
||||||
|
})
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnvVarFromConfigMap register one environment variable set from the configMap.
|
||||||
|
func (c *ContainerBuilder) EnvVarFromConfigMap(name string, cfmName string, cfmKey string) *ContainerBuilder {
|
||||||
|
c.obj.Env = append(c.obj.Env, corev1.EnvVar{
|
||||||
|
Name: name,
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: cfmName,
|
||||||
|
},
|
||||||
|
Key: cfmKey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnvVarFromSecret register one environment variable set from the secret.
|
||||||
|
func (c *ContainerBuilder) EnvVarFromSecret(name string, scName string, scKey string) *ContainerBuilder {
|
||||||
|
c.obj.Env = append(c.obj.Env, corev1.EnvVar{
|
||||||
|
Name: name,
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
SecretKeyRef: &corev1.SecretKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: scName,
|
||||||
|
},
|
||||||
|
Key: scKey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// Build returns the object after making certain assertions
|
// Build returns the object after making certain assertions
|
||||||
func (c *ContainerBuilder) Build() (corev1.Container, error) {
|
func (c *ContainerBuilder) Build() (corev1.Container, error) {
|
||||||
if c.securityContext == nil {
|
if c.securityContext == nil {
|
||||||
|
78
builders/pvc.go
Normal file
78
builders/pvc.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package builders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alecthomas/units"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PersistentVolumeClaimBuilder defines the interface to build a PVC
|
||||||
|
type PersistentVolumeClaimBuilder struct {
|
||||||
|
obj *corev1.PersistentVolumeClaim
|
||||||
|
}
|
||||||
|
|
||||||
|
// PVC returns a new PVC builder
|
||||||
|
func PersistentVolumeClaim(existing *corev1.PersistentVolumeClaim) *PersistentVolumeClaimBuilder {
|
||||||
|
|
||||||
|
return &PersistentVolumeClaimBuilder{
|
||||||
|
obj: existing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) ReadWriteOnce() *PersistentVolumeClaimBuilder {
|
||||||
|
pvc.obj.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resources defines the resource configuration for the PV
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) Resources(storage int64) *PersistentVolumeClaimBuilder {
|
||||||
|
storage = storage * int64(units.Megabyte)
|
||||||
|
pvc.obj.Spec.Resources = v1.ResourceRequirements{
|
||||||
|
Requests: v1.ResourceList{
|
||||||
|
v1.ResourceStorage: *resource.NewQuantity(storage, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) ReadOnlyMany() *PersistentVolumeClaimBuilder {
|
||||||
|
pvc.obj.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{"ReadOnlyMany"}
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) ReadWriteMany() *PersistentVolumeClaimBuilder {
|
||||||
|
pvc.obj.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{"ReadWriteMany"}
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) Selector(selector metav1.LabelSelector) *PersistentVolumeClaimBuilder {
|
||||||
|
pvc.obj.Spec.Selector = &selector
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) VolumeName(name string) *PersistentVolumeClaimBuilder {
|
||||||
|
pvc.obj.Spec.VolumeName = name
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) StorageClassName(name string) *PersistentVolumeClaimBuilder {
|
||||||
|
pvc.obj.Spec.StorageClassName = &name
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) Block() *PersistentVolumeClaimBuilder {
|
||||||
|
*pvc.obj.Spec.VolumeMode = corev1.PersistentVolumeBlock
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) Filesystem() *PersistentVolumeClaimBuilder {
|
||||||
|
*pvc.obj.Spec.VolumeMode = corev1.PersistentVolumeFilesystem
|
||||||
|
return pvc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build returns a complete PVC object
|
||||||
|
func (pvc *PersistentVolumeClaimBuilder) Build() (corev1.PersistentVolumeClaim, error) {
|
||||||
|
return *pvc.obj, nil
|
||||||
|
}
|
50
builders/secret.go
Normal file
50
builders/secret.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package builders
|
||||||
|
|
||||||
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SecretBuilder defines the interface to build a Secret
|
||||||
|
type SecretBuilder struct {
|
||||||
|
obj *corev1.Secret
|
||||||
|
owner metav1.Object
|
||||||
|
scheme *runtime.Scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secret returns a new secret builder
|
||||||
|
func Secret(existing *corev1.Secret, owner metav1.Object, scheme *runtime.Scheme) *SecretBuilder {
|
||||||
|
existing.Data = map[string][]byte{}
|
||||||
|
existing.StringData = map[string]string{}
|
||||||
|
|
||||||
|
return &SecretBuilder{
|
||||||
|
obj: existing,
|
||||||
|
owner: owner,
|
||||||
|
scheme: scheme,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data sets a key inside this Secret
|
||||||
|
func (cm *SecretBuilder) Data(key, value string) *SecretBuilder {
|
||||||
|
cm.obj.Data[key] = []byte(value)
|
||||||
|
return cm
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringData sets a key inside this Secret
|
||||||
|
func (cm *SecretBuilder) StringData(key, value string) *SecretBuilder {
|
||||||
|
cm.obj.StringData[key] = value
|
||||||
|
return cm
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecretType sets the secret type
|
||||||
|
func (cm *SecretBuilder) SecretType(value string) *SecretBuilder {
|
||||||
|
cm.obj.Type = corev1.SecretType(value)
|
||||||
|
return cm
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build returns a complete Secret object
|
||||||
|
func (cm *SecretBuilder) Build() error {
|
||||||
|
return controllerutil.SetControllerReference(cm.owner, cm.obj, cm.scheme)
|
||||||
|
}
|
76
builders/statefulset.go
Normal file
76
builders/statefulset.go
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package builders
|
||||||
|
|
||||||
|
import (
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/utils/pointer"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StatefulSetBuilder defines the interface to build a StatefulSet
|
||||||
|
type StatefulSetBuilder struct {
|
||||||
|
obj *appsv1.StatefulSet
|
||||||
|
podTemplateSpec *PodTemplateSpecBuilder
|
||||||
|
pvcs []*PersistentVolumeClaimBuilder
|
||||||
|
scheme *runtime.Scheme
|
||||||
|
labels map[string]string
|
||||||
|
owner metav1.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatefulSet returns a new StatefulSet builder
|
||||||
|
func StatefulSet(existing *appsv1.StatefulSet, owner metav1.Object, scheme *runtime.Scheme) *StatefulSetBuilder {
|
||||||
|
return &StatefulSetBuilder{
|
||||||
|
obj: existing,
|
||||||
|
labels: map[string]string{},
|
||||||
|
owner: owner,
|
||||||
|
scheme: scheme,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Labels specifies labels for the StatefulSet
|
||||||
|
func (d *StatefulSetBuilder) Labels(labels map[string]string) *StatefulSetBuilder {
|
||||||
|
d.labels = labels
|
||||||
|
d.obj.ObjectMeta.Labels = d.labels
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replicas defines the number of replicas
|
||||||
|
func (d *StatefulSetBuilder) Replicas(replicas int32) *StatefulSetBuilder {
|
||||||
|
d.obj.Spec.Replicas = pointer.Int32Ptr(replicas)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodTemplateSpec defines a builder for the pod template spec
|
||||||
|
func (d *StatefulSetBuilder) PodTemplateSpec(podTemplateSpec *PodTemplateSpecBuilder) *StatefulSetBuilder {
|
||||||
|
d.podTemplateSpec = podTemplateSpec
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// PVCs defines a builder array for the PVC spec
|
||||||
|
func (d *StatefulSetBuilder) PVCs(pvcs ...*PersistentVolumeClaimBuilder) *StatefulSetBuilder {
|
||||||
|
d.pvcs = pvcs
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build creates a final StatefulSet objet
|
||||||
|
func (d *StatefulSetBuilder) Build() error {
|
||||||
|
podTemplateSpec, err := d.podTemplateSpec.Labels(d.labels).Build()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.obj.Spec.Template = podTemplateSpec
|
||||||
|
|
||||||
|
for _, c := range d.pvcs {
|
||||||
|
pvc, err := c.Build()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.obj.Spec.VolumeClaimTemplates = append(d.obj.Spec.VolumeClaimTemplates, pvc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return controllerutil.SetControllerReference(d.owner, d.obj, d.scheme)
|
||||||
|
}
|
@@ -33,6 +33,28 @@ func (v *VolumeBuilder) FromConfigMap(name string) *VolumeBuilder {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromSecret sets the source of the volume from a Secret
|
||||||
|
func (v *VolumeBuilder) FromSecret(name string) *VolumeBuilder {
|
||||||
|
v.obj.VolumeSource = corev1.VolumeSource{
|
||||||
|
Secret: &corev1.SecretVolumeSource{
|
||||||
|
SecretName: name,
|
||||||
|
DefaultMode: pointer.Int32Ptr(420),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromPersistentVolumeClaim sets the source of the volume from a PVC
|
||||||
|
func (v *VolumeBuilder) FromPersistentVolumeClaim(name string) *VolumeBuilder {
|
||||||
|
v.obj.VolumeSource = corev1.VolumeSource{
|
||||||
|
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||||
|
ClaimName: name,
|
||||||
|
ReadOnly: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
// Build returns the object after checking assertions
|
// Build returns the object after checking assertions
|
||||||
func (v *VolumeBuilder) Build() corev1.Volume {
|
func (v *VolumeBuilder) Build() corev1.Volume {
|
||||||
return *v.obj
|
return *v.obj
|
||||||
|
149
chart/crds/infrastructure.vexxhost.cloud_rabbitmqs.yaml
Normal file
149
chart/crds/infrastructure.vexxhost.cloud_rabbitmqs.yaml
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.2.5
|
||||||
|
creationTimestamp: null
|
||||||
|
name: rabbitmqs.infrastructure.vexxhost.cloud
|
||||||
|
spec:
|
||||||
|
group: infrastructure.vexxhost.cloud
|
||||||
|
names:
|
||||||
|
kind: Rabbitmq
|
||||||
|
listKind: RabbitmqList
|
||||||
|
plural: rabbitmqs
|
||||||
|
singular: rabbitmq
|
||||||
|
scope: Namespaced
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: Rabbitmq is the Schema for the Rabbitmqs API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: RabbitmqSpec defines the desired state of Rabbitmq
|
||||||
|
properties:
|
||||||
|
authSecret:
|
||||||
|
type: string
|
||||||
|
nodeSelector:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
policies:
|
||||||
|
items:
|
||||||
|
description: RabbitmqPolicySpec defines the Rabbitmq Policy Spec for
|
||||||
|
the Vhost
|
||||||
|
properties:
|
||||||
|
apply-to:
|
||||||
|
type: string
|
||||||
|
definition:
|
||||||
|
description: RabbitmqPolicyDefinition defines the Rabbitmq Policy
|
||||||
|
content
|
||||||
|
properties:
|
||||||
|
expires:
|
||||||
|
type: integer
|
||||||
|
federation-upstream-set:
|
||||||
|
type: string
|
||||||
|
ha-mode:
|
||||||
|
type: string
|
||||||
|
ha-params:
|
||||||
|
type: integer
|
||||||
|
ha-sync-mode:
|
||||||
|
type: string
|
||||||
|
max-length:
|
||||||
|
type: integer
|
||||||
|
max-length-bytes:
|
||||||
|
type: integer
|
||||||
|
message-ttl:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
pattern:
|
||||||
|
type: string
|
||||||
|
priority:
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
vhost:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- apply-to
|
||||||
|
- definition
|
||||||
|
- name
|
||||||
|
- pattern
|
||||||
|
- priority
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
tolerations:
|
||||||
|
items:
|
||||||
|
description: The pod this Toleration is attached to tolerates any
|
||||||
|
taint that matches the triple <key,value,effect> using the matching
|
||||||
|
operator <operator>.
|
||||||
|
properties:
|
||||||
|
effect:
|
||||||
|
description: Effect indicates the taint effect to match. Empty
|
||||||
|
means match all taint effects. When specified, allowed values
|
||||||
|
are NoSchedule, PreferNoSchedule and NoExecute.
|
||||||
|
type: string
|
||||||
|
key:
|
||||||
|
description: Key is the taint key that the toleration applies
|
||||||
|
to. Empty means match all taint keys. If the key is empty, operator
|
||||||
|
must be Exists; this combination means to match all values and
|
||||||
|
all keys.
|
||||||
|
type: string
|
||||||
|
operator:
|
||||||
|
description: Operator represents a key's relationship to the value.
|
||||||
|
Valid operators are Exists and Equal. Defaults to Equal. Exists
|
||||||
|
is equivalent to wildcard for value, so that a pod can tolerate
|
||||||
|
all taints of a particular category.
|
||||||
|
type: string
|
||||||
|
tolerationSeconds:
|
||||||
|
description: TolerationSeconds represents the period of time the
|
||||||
|
toleration (which must be of effect NoExecute, otherwise this
|
||||||
|
field is ignored) tolerates the taint. By default, it is not
|
||||||
|
set, which means tolerate the taint forever (do not evict).
|
||||||
|
Zero and negative values will be treated as 0 (evict immediately)
|
||||||
|
by the system.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
value:
|
||||||
|
description: Value is the taint value the toleration matches to.
|
||||||
|
If the operator is Exists, the value should be empty, otherwise
|
||||||
|
just a regular string.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- authSecret
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: RabbitmqStatus defines the observed state of Rabbitmq
|
||||||
|
properties:
|
||||||
|
phase:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- phase
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
version: v1alpha1
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@@ -43,6 +43,19 @@ rules:
|
|||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- infrastructure.vexxhost.cloud
|
- infrastructure.vexxhost.cloud
|
||||||
resources:
|
resources:
|
||||||
@@ -83,6 +96,26 @@ rules:
|
|||||||
- get
|
- get
|
||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- infrastructure.vexxhost.cloud
|
||||||
|
resources:
|
||||||
|
- rabbitmqs
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- infrastructure.vexxhost.cloud
|
||||||
|
resources:
|
||||||
|
- rabbitmqs/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- monitoring.coreos.com
|
- monitoring.coreos.com
|
||||||
resources:
|
resources:
|
||||||
|
149
config/crd/bases/infrastructure.vexxhost.cloud_rabbitmqs.yaml
Normal file
149
config/crd/bases/infrastructure.vexxhost.cloud_rabbitmqs.yaml
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.2.5
|
||||||
|
creationTimestamp: null
|
||||||
|
name: rabbitmqs.infrastructure.vexxhost.cloud
|
||||||
|
spec:
|
||||||
|
group: infrastructure.vexxhost.cloud
|
||||||
|
names:
|
||||||
|
kind: Rabbitmq
|
||||||
|
listKind: RabbitmqList
|
||||||
|
plural: rabbitmqs
|
||||||
|
singular: rabbitmq
|
||||||
|
scope: Namespaced
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: Rabbitmq is the Schema for the Rabbitmqs API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: 'APIVersion defines the versioned schema of this representation
|
||||||
|
of an object. Servers should convert recognized schemas to the latest
|
||||||
|
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: 'Kind is a string value representing the REST resource this
|
||||||
|
object represents. Servers may infer this from the endpoint the client
|
||||||
|
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: RabbitmqSpec defines the desired state of Rabbitmq
|
||||||
|
properties:
|
||||||
|
authSecret:
|
||||||
|
type: string
|
||||||
|
nodeSelector:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
policies:
|
||||||
|
items:
|
||||||
|
description: RabbitmqPolicySpec defines the Rabbitmq Policy Spec for
|
||||||
|
the Vhost
|
||||||
|
properties:
|
||||||
|
apply-to:
|
||||||
|
type: string
|
||||||
|
definition:
|
||||||
|
description: RabbitmqPolicyDefinition defines the Rabbitmq Policy
|
||||||
|
content
|
||||||
|
properties:
|
||||||
|
expires:
|
||||||
|
type: integer
|
||||||
|
federation-upstream-set:
|
||||||
|
type: string
|
||||||
|
ha-mode:
|
||||||
|
type: string
|
||||||
|
ha-params:
|
||||||
|
type: integer
|
||||||
|
ha-sync-mode:
|
||||||
|
type: string
|
||||||
|
max-length:
|
||||||
|
type: integer
|
||||||
|
max-length-bytes:
|
||||||
|
type: integer
|
||||||
|
message-ttl:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
pattern:
|
||||||
|
type: string
|
||||||
|
priority:
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
vhost:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- apply-to
|
||||||
|
- definition
|
||||||
|
- name
|
||||||
|
- pattern
|
||||||
|
- priority
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
tolerations:
|
||||||
|
items:
|
||||||
|
description: The pod this Toleration is attached to tolerates any
|
||||||
|
taint that matches the triple <key,value,effect> using the matching
|
||||||
|
operator <operator>.
|
||||||
|
properties:
|
||||||
|
effect:
|
||||||
|
description: Effect indicates the taint effect to match. Empty
|
||||||
|
means match all taint effects. When specified, allowed values
|
||||||
|
are NoSchedule, PreferNoSchedule and NoExecute.
|
||||||
|
type: string
|
||||||
|
key:
|
||||||
|
description: Key is the taint key that the toleration applies
|
||||||
|
to. Empty means match all taint keys. If the key is empty, operator
|
||||||
|
must be Exists; this combination means to match all values and
|
||||||
|
all keys.
|
||||||
|
type: string
|
||||||
|
operator:
|
||||||
|
description: Operator represents a key's relationship to the value.
|
||||||
|
Valid operators are Exists and Equal. Defaults to Equal. Exists
|
||||||
|
is equivalent to wildcard for value, so that a pod can tolerate
|
||||||
|
all taints of a particular category.
|
||||||
|
type: string
|
||||||
|
tolerationSeconds:
|
||||||
|
description: TolerationSeconds represents the period of time the
|
||||||
|
toleration (which must be of effect NoExecute, otherwise this
|
||||||
|
field is ignored) tolerates the taint. By default, it is not
|
||||||
|
set, which means tolerate the taint forever (do not evict).
|
||||||
|
Zero and negative values will be treated as 0 (evict immediately)
|
||||||
|
by the system.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
value:
|
||||||
|
description: Value is the taint value the toleration matches to.
|
||||||
|
If the operator is Exists, the value should be empty, otherwise
|
||||||
|
just a regular string.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
required:
|
||||||
|
- authSecret
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
description: RabbitmqStatus defines the observed state of Rabbitmq
|
||||||
|
properties:
|
||||||
|
phase:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- phase
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
version: v1alpha1
|
||||||
|
versions:
|
||||||
|
- name: v1alpha1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
status:
|
||||||
|
acceptedNames:
|
||||||
|
kind: ""
|
||||||
|
plural: ""
|
||||||
|
conditions: []
|
||||||
|
storedVersions: []
|
@@ -4,6 +4,7 @@
|
|||||||
resources:
|
resources:
|
||||||
- bases/infrastructure.vexxhost.cloud_mcrouters.yaml
|
- bases/infrastructure.vexxhost.cloud_mcrouters.yaml
|
||||||
- bases/infrastructure.vexxhost.cloud_memcacheds.yaml
|
- bases/infrastructure.vexxhost.cloud_memcacheds.yaml
|
||||||
|
- bases/infrastructure.vexxhost.cloud_rabbitmqs.yaml
|
||||||
- bases/monitoring.coreos.com_podmonitors.yaml
|
- bases/monitoring.coreos.com_podmonitors.yaml
|
||||||
- bases/monitoring.coreos.com_prometheusrules.yaml
|
- bases/monitoring.coreos.com_prometheusrules.yaml
|
||||||
# +kubebuilder:scaffold:crdkustomizeresource
|
# +kubebuilder:scaffold:crdkustomizeresource
|
||||||
|
@@ -43,6 +43,19 @@ rules:
|
|||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
- services
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- infrastructure.vexxhost.cloud
|
- infrastructure.vexxhost.cloud
|
||||||
resources:
|
resources:
|
||||||
@@ -83,6 +96,26 @@ rules:
|
|||||||
- get
|
- get
|
||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
|
- apiGroups:
|
||||||
|
- infrastructure.vexxhost.cloud
|
||||||
|
resources:
|
||||||
|
- rabbitmqs
|
||||||
|
verbs:
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- infrastructure.vexxhost.cloud
|
||||||
|
resources:
|
||||||
|
- rabbitmqs/status
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- patch
|
||||||
|
- update
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- monitoring.coreos.com
|
- monitoring.coreos.com
|
||||||
resources:
|
resources:
|
||||||
|
15
config/samples/infrastructure_v1alpha1_rabbitmq.yaml
Normal file
15
config/samples/infrastructure_v1alpha1_rabbitmq.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: infrastructure.vexxhost.cloud/v1alpha1
|
||||||
|
kind: Rabbitmq
|
||||||
|
metadata:
|
||||||
|
name: sample
|
||||||
|
spec:
|
||||||
|
authSecret: rabbitmq-sample
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: rabbitmq-sample
|
||||||
|
namespace: default
|
||||||
|
data:
|
||||||
|
password: Y0dGemMzZHZjbVE9
|
||||||
|
username: ZFhObGNnPT0=
|
||||||
|
kind: Secret
|
18
config/samples/rabbitmq_pv.yaml
Normal file
18
config/samples/rabbitmq_pv.yaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# When the default StorageClass is "", use this.
|
||||||
|
---
|
||||||
|
kind: PersistentVolume
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: data
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/instance: sample
|
||||||
|
app.kubernetes.io/managed-by: openstack-operator
|
||||||
|
app.kubernetes.io/name: rabbitmq
|
||||||
|
spec:
|
||||||
|
capacity:
|
||||||
|
storage: 1Gi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
hostPath:
|
||||||
|
path: "/opt/pv/rabbitmq"
|
||||||
|
persistentVolumeReclaimPolicy: Delete
|
208
controllers/rabbitmq_controller.go
Normal file
208
controllers/rabbitmq_controller.go
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
monitoringv1 "opendev.org/vexxhost/openstack-operator/api/monitoring/v1"
|
||||||
|
infrastructurev1alpha1 "opendev.org/vexxhost/openstack-operator/api/v1alpha1"
|
||||||
|
"opendev.org/vexxhost/openstack-operator/builders"
|
||||||
|
"opendev.org/vexxhost/openstack-operator/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RabbitmqReconciler reconciles a Rabbitmq object
|
||||||
|
type RabbitmqReconciler struct {
|
||||||
|
client.Client
|
||||||
|
Log logr.Logger
|
||||||
|
Scheme *runtime.Scheme
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
_rabbitmqDefaultUsernameCfgKey = "username"
|
||||||
|
_rabbitmqDefaultPasswordCfgKey = "password"
|
||||||
|
_rabbitmqBuiltinMetricPort = 15692
|
||||||
|
_rabbitmqPort = 5672
|
||||||
|
_rabbitmqRunAsUser = 999
|
||||||
|
_rabbitmqRunAsGroup = 999
|
||||||
|
)
|
||||||
|
|
||||||
|
// +kubebuilder:rbac:groups=infrastructure.vexxhost.cloud,resources=rabbitmqs,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=infrastructure.vexxhost.cloud,resources=rabbitmqs/status,verbs=get;update;patch
|
||||||
|
// +kubebuilder:rbac:groups=monitoring.coreos.com,resources=prometheusrules,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=monitoring.coreos.com,resources=podmonitors,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=core,resources=secrets;services,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
|
||||||
|
// Reconcile does the reconcilication of Rabbitmq instances
|
||||||
|
func (r *RabbitmqReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
log := r.Log.WithValues("rabbitmq", req.NamespacedName)
|
||||||
|
|
||||||
|
var Rabbitmq infrastructurev1alpha1.Rabbitmq
|
||||||
|
if err := r.Get(ctx, req.NamespacedName, &Rabbitmq); err != nil {
|
||||||
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Labels
|
||||||
|
labels := map[string]string{
|
||||||
|
"app.kubernetes.io/name": "rabbitmq",
|
||||||
|
"app.kubernetes.io/instance": req.Name,
|
||||||
|
"app.kubernetes.io/managed-by": "openstack-operator",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deployment
|
||||||
|
deployment := &appsv1.Deployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: req.Namespace,
|
||||||
|
Name: fmt.Sprintf("rabbitmq-%s", req.Name),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
op, err := utils.CreateOrUpdate(ctx, r, deployment, func() error {
|
||||||
|
return builders.Deployment(deployment, &Rabbitmq, r.Scheme).
|
||||||
|
Labels(labels).
|
||||||
|
Replicas(1).
|
||||||
|
PodTemplateSpec(
|
||||||
|
builders.PodTemplateSpec().
|
||||||
|
PodSpec(
|
||||||
|
builders.PodSpec().
|
||||||
|
NodeSelector(Rabbitmq.Spec.NodeSelector).
|
||||||
|
Tolerations(Rabbitmq.Spec.Tolerations).
|
||||||
|
Containers(
|
||||||
|
builders.Container("rabbitmq", "vexxhost/rabbitmq:latest").
|
||||||
|
EnvVarFromSecret("RABBITMQ_DEFAULT_USER", Rabbitmq.Spec.AuthSecret, _rabbitmqDefaultUsernameCfgKey).
|
||||||
|
EnvVarFromSecret("RABBITMQ_DEFAULT_PASS", Rabbitmq.Spec.AuthSecret, _rabbitmqDefaultPasswordCfgKey).
|
||||||
|
Port("rabbitmq", _rabbitmqPort).
|
||||||
|
Port("metrics", _rabbitmqBuiltinMetricPort).
|
||||||
|
PortProbe("rabbitmq", 15, 30).
|
||||||
|
Resources(500, 512, 500, 2).
|
||||||
|
SecurityContext(
|
||||||
|
builders.SecurityContext().
|
||||||
|
RunAsUser(_rabbitmqRunAsUser).
|
||||||
|
RunAsGroup(_rabbitmqRunAsGroup),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).
|
||||||
|
Build()
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
log.WithValues("resource", "Deployment").WithValues("op", op).Info("Reconciled")
|
||||||
|
|
||||||
|
// PodMonitor
|
||||||
|
podMonitor := &monitoringv1.PodMonitor{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "monitoring.coreos.com/v1",
|
||||||
|
Kind: "PodMonitor",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: req.Namespace,
|
||||||
|
Name: "rabbitmq-podmonitor",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app.kubernetes.io/name": "rabbitmq",
|
||||||
|
"app.kubernetes.io/managed-by": "openstack-operator",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
op, err = utils.CreateOrUpdate(ctx, r, podMonitor, func() error {
|
||||||
|
return builders.PodMonitor(podMonitor, &Rabbitmq, r.Scheme).
|
||||||
|
Selector(map[string]string{
|
||||||
|
"app.kubernetes.io/name": "rabbitmq",
|
||||||
|
}).
|
||||||
|
PodMetricsEndpoints(
|
||||||
|
builders.PodMetricsEndpoint().
|
||||||
|
Port("metrics").
|
||||||
|
Path("/metrics").
|
||||||
|
Interval("15s"),
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
log.WithValues("resource", "rabbitmq-podmonitor").WithValues("op", op).Info("Reconciled")
|
||||||
|
|
||||||
|
// Alertrule
|
||||||
|
alertRule := &monitoringv1.PrometheusRule{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: req.Namespace,
|
||||||
|
Name: "rabbitmq-alertrule",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
op, err = utils.CreateOrUpdate(ctx, r, alertRule, func() error {
|
||||||
|
return builders.PrometheusRule(alertRule, &Rabbitmq, r.Scheme).
|
||||||
|
RuleGroups(builders.RuleGroup().
|
||||||
|
Name("rabbitmq-rule").
|
||||||
|
Rules(
|
||||||
|
builders.Rule().
|
||||||
|
Alert("RabbitmqDown").
|
||||||
|
Message("Rabbitmq node down.").
|
||||||
|
Priority(1).
|
||||||
|
Expr("rabbitmq_up == 0"),
|
||||||
|
builders.Rule().
|
||||||
|
Alert("RabbitmqTooManyConnections").
|
||||||
|
Message("RabbitMQ instance has too many connections.").
|
||||||
|
Priority(1).
|
||||||
|
Expr("rabbitmq_connectionsTotal > 1000"),
|
||||||
|
builders.Rule().
|
||||||
|
Alert("RabbitmqTooManyMessagesInQueue").
|
||||||
|
Message("Queue is filling up.").
|
||||||
|
Priority(1).
|
||||||
|
Expr("rabbitmq_queue_messages_ready > 1000"),
|
||||||
|
builders.Rule().
|
||||||
|
Alert("RabbitmqSlowQueueConsuming").
|
||||||
|
Message("Queue messages are consumed slowly.").
|
||||||
|
Priority(1).
|
||||||
|
Expr("time() - rabbitmq_queue_head_message_timestamp > 60"),
|
||||||
|
).
|
||||||
|
Interval("1m")).
|
||||||
|
Build()
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
log.WithValues("resource", "rabbitmq-alertrule").WithValues("op", op).Info("Reconciled")
|
||||||
|
|
||||||
|
// Service
|
||||||
|
service := &corev1.Service{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: req.Namespace,
|
||||||
|
Name: fmt.Sprintf("rabbitmq-%s", req.Name),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
op, err = utils.CreateOrUpdate(ctx, r, service, func() error {
|
||||||
|
return builders.Service(service, &Rabbitmq, r.Scheme).
|
||||||
|
Port("epmd", 4369).
|
||||||
|
Port("amqp", 5671).
|
||||||
|
Port("distport", 25672).
|
||||||
|
Selector(labels).
|
||||||
|
Build()
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
log.WithValues("resource", "Service").WithValues("op", op).Info("Reconciled")
|
||||||
|
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupWithManager initializes the controller with primary manager
|
||||||
|
func (r *RabbitmqReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
|
For(&infrastructurev1alpha1.Rabbitmq{}).
|
||||||
|
Owns(&appsv1.Deployment{}).
|
||||||
|
Owns(&corev1.Service{}).
|
||||||
|
Owns(&monitoringv1.PodMonitor{}).
|
||||||
|
Owns(&monitoringv1.PrometheusRule{}).
|
||||||
|
Complete(r)
|
||||||
|
}
|
4
images/rabbitmq/Dockerfile
Normal file
4
images/rabbitmq/Dockerfile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FROM rabbitmq:latest
|
||||||
|
RUN rabbitmq-plugins enable --offline rabbitmq_prometheus && \
|
||||||
|
rabbitmq-plugins enable --offline rabbitmq_management && \
|
||||||
|
rabbitmq-plugins enable --offline rabbitmq_peer_discovery_k8s
|
12
main.go
12
main.go
@@ -57,6 +57,7 @@ func main() {
|
|||||||
|
|
||||||
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
|
ctrl.SetLogger(zap.New(zap.UseDevMode(true)))
|
||||||
|
|
||||||
|
// Create manager
|
||||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
MetricsBindAddress: metricsAddr,
|
MetricsBindAddress: metricsAddr,
|
||||||
@@ -69,6 +70,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup controllers with manager
|
||||||
if err = (&controllers.McrouterReconciler{
|
if err = (&controllers.McrouterReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Log: ctrl.Log.WithName("controllers").WithName("Mcrouter"),
|
Log: ctrl.Log.WithName("controllers").WithName("Mcrouter"),
|
||||||
@@ -77,6 +79,7 @@ func main() {
|
|||||||
setupLog.Error(err, "unable to create controller", "controller", "Mcrouter")
|
setupLog.Error(err, "unable to create controller", "controller", "Mcrouter")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = (&controllers.MemcachedReconciler{
|
if err = (&controllers.MemcachedReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Log: ctrl.Log.WithName("controllers").WithName("Memcached"),
|
Log: ctrl.Log.WithName("controllers").WithName("Memcached"),
|
||||||
@@ -85,6 +88,15 @@ func main() {
|
|||||||
setupLog.Error(err, "unable to create controller", "controller", "Memcached")
|
setupLog.Error(err, "unable to create controller", "controller", "Memcached")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = (&controllers.RabbitmqReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Log: ctrl.Log.WithName("controllers").WithName("Rabbitmq"),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "unable to create controller", "controller", "Rabbitmq")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
// +kubebuilder:scaffold:builder
|
// +kubebuilder:scaffold:builder
|
||||||
|
|
||||||
setupLog.Info("starting manager", "revision", version.Revision)
|
setupLog.Info("starting manager", "revision", version.Revision)
|
||||||
|
Reference in New Issue
Block a user