Skip to content

Commit

Permalink
chore(v2alpha2): change replicant template to pointer
Browse files Browse the repository at this point in the history
Signed-off-by: Rory Z <[email protected]>
  • Loading branch information
Rory-Z committed Jun 20, 2023
1 parent fba55e8 commit ab0d9d2
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 185 deletions.
45 changes: 19 additions & 26 deletions apis/apps/v2alpha1/emqx_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ limitations under the License.
package v2alpha1

import (
"reflect"
"encoding/json"

"github.com/emqx/emqx-operator/apis/apps/v2alpha2"
"sigs.k8s.io/controller-runtime/pkg/conversion"
Expand All @@ -26,8 +26,15 @@ import (
// ConvertTo converts this version to the Hub version (v1).
func (src *EMQX) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*v2alpha2.EMQX)
assigned(&dst.ObjectMeta, src.ObjectMeta.DeepCopy())
assigned(&dst.Spec, src.Spec.DeepCopy())

b, err := json.Marshal(src)
if err != nil {
return err
}

if err := json.Unmarshal(b, dst); err != nil {
return err
}
dst.SetGroupVersionKind(v2alpha2.GroupVersion.WithKind("EMQX"))

// +kubebuilder:docs-gen:collapse=rote conversion
Expand All @@ -37,31 +44,17 @@ func (src *EMQX) ConvertTo(dstRaw conversion.Hub) error {
// ConvertFrom converts from the Hub version (v1) to this version.
func (dst *EMQX) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*v2alpha2.EMQX)
assigned(&dst.ObjectMeta, src.ObjectMeta.DeepCopy())
assigned(&dst.Spec, src.Spec.DeepCopy())

b, err := json.Marshal(src)
if err != nil {
return err
}

if err := json.Unmarshal(b, dst); err != nil {
return err
}
dst.SetGroupVersionKind(GroupVersion.WithKind("EMQX"))

// +kubebuilder:docs-gen:collapse=rote conversion
return nil
}

func assigned(dist, src interface{}) {
dVal := reflect.ValueOf(dist).Elem()
sVal := reflect.ValueOf(src).Elem()

switch sVal.Type().Kind() {
case reflect.Struct:
for i := 0; i < sVal.NumField(); i++ {
name := sVal.Type().Field(i).Name
if dVal.FieldByName(name).IsValid() && dVal.FieldByName(name).CanSet() {
assigned(dVal.FieldByName(name).Addr().Interface(), sVal.FieldByName(name).Addr().Interface())
}
}
case reflect.Array, reflect.Slice:
for i := 0; i < sVal.Len(); i++ {
dVal.Set(reflect.Append(dVal, sVal.Index(i)))
}
default:
dVal.Set(reflect.ValueOf(sVal.Interface()))
}
}
6 changes: 3 additions & 3 deletions apis/apps/v2alpha2/emqx_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ type EMQXReplicantTemplateSpec struct {
// Replicas is the desired number of replicas of the given Template.
// These are replicas in the sense that they are instantiations of the
// same Template, but individual replicas also have a consistent identity.
// Defaults to 2 if EMQX core node, or 3 if EMQX replicant node.
//+kubebuilder:validation:Minimum=2
// Defaults to 3.
//+kubebuilder:default:=3
Replicas *int32 `json:"replicas,omitempty"`
// Entrypoint array. Not executed within a shell.
// The container image's ENTRYPOINT is used if this is not provided.
Expand Down Expand Up @@ -231,7 +231,7 @@ type EMQXSpec struct {
// CoreTemplate is the object that describes the EMQX core node that will be created
CoreTemplate EMQXCoreTemplate `json:"coreTemplate,omitempty"`
// ReplicantTemplate is the object that describes the EMQX replicant node that will be created
ReplicantTemplate EMQXReplicantTemplate `json:"replicantTemplate,omitempty"`
ReplicantTemplate *EMQXReplicantTemplate `json:"replicantTemplate,omitempty"`
// DashboardServiceTemplate is the object that describes the EMQX dashboard service that will be created
// This service always selector the EMQX core node
}
Expand Down
138 changes: 61 additions & 77 deletions apis/apps/v2alpha2/emqx_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ func (r *EMQX) Default() {
r.defaultLabels()
r.defaultAnnotations()
r.defaultBootstrapConfig()
r.defaultReplicas()
r.defaultDashboardServiceTemplate()
r.defaultProbe()
r.defaultSecurityContext()
Expand All @@ -69,6 +68,12 @@ var _ webhook.Validator = &EMQX{}
func (r *EMQX) ValidateCreate() error {
emqxlog.Info("validate create", "name", r.Name)

if *r.Spec.CoreTemplate.Spec.Replicas < 2 {
err := emperror.New("the number of EMQX core nodes must be greater than 1")
emqxlog.Error(err, "validate create failed")
return err
}

if _, err := hocon.ParseString(r.Spec.BootstrapConfig); err != nil {
err = emperror.Wrap(err, "failed to parse bootstrap config")
emqxlog.Error(err, "validate create failed")
Expand All @@ -82,6 +87,12 @@ func (r *EMQX) ValidateCreate() error {
func (r *EMQX) ValidateUpdate(old runtime.Object) error {
emqxlog.Info("validate update", "name", r.Name)

if *r.Spec.CoreTemplate.Spec.Replicas < 2 {
err := emperror.New("the number of EMQX core nodes must be greater than 1")
emqxlog.Error(err, "validate update failed")
return err
}

oldEMQX := old.(*EMQX)
if !reflect.DeepEqual(oldEMQX.Spec.BootstrapAPIKeys, r.Spec.BootstrapAPIKeys) {
err := emperror.Errorf("bootstrap APIKey cannot be updated")
Expand All @@ -103,13 +114,6 @@ func (r *EMQX) ValidateUpdate(old runtime.Object) error {
return err
}

if !reflect.DeepEqual(oldEMQX.Spec.ReplicantTemplate.ObjectMeta, r.Spec.ReplicantTemplate.ObjectMeta) ||
!reflect.DeepEqual(oldEMQX.Spec.CoreTemplate.ObjectMeta, r.Spec.CoreTemplate.ObjectMeta) {
err := emperror.New(".spec.coreTemplate.metadata and .spec.replicantTemplate.metadata cannot be updated")
emqxlog.Error(err, "validate update failed")
return err
}

return nil
}

Expand All @@ -126,59 +130,49 @@ func (r *EMQX) defaultNames() {
r.Name = "emqx"
}

if r.Spec.CoreTemplate.Name == "" {
r.Spec.CoreTemplate.Name = r.CoreNodeNamespacedName().Name
}

if r.Spec.ReplicantTemplate.Name == "" {
r.Spec.ReplicantTemplate.Name = r.ReplicantNodeNamespacedName().Name
}

if r.Spec.DashboardServiceTemplate.Name == "" {
r.Spec.DashboardServiceTemplate.Name = r.DashboardServiceNamespacedName().Name
}

if r.Spec.ListenersServiceTemplate.Name == "" {
r.Spec.ListenersServiceTemplate.Name = r.ListenersServiceNamespacedName().Name
}
}

func (r *EMQX) defaultLabels() {
if r.Labels == nil {
r.Labels = make(map[string]string)
if r.Spec.CoreTemplate.Name == "" {
r.Spec.CoreTemplate.Name = r.CoreNodeNamespacedName().Name
}
r.Labels["apps.emqx.io/managed-by"] = "emqx-operator"
r.Labels["apps.emqx.io/instance"] = r.GetName()

// Core
if r.Spec.CoreTemplate.Labels == nil {
r.Spec.CoreTemplate.Labels = make(map[string]string)
if r.Spec.ReplicantTemplate != nil {
if r.Spec.ReplicantTemplate.Name == "" {
r.Spec.ReplicantTemplate.Name = r.ReplicantNodeNamespacedName().Name
}
}
r.Spec.CoreTemplate.Labels["apps.emqx.io/instance"] = r.Name
r.Spec.CoreTemplate.Labels["apps.emqx.io/managed-by"] = "emqx-operator"
r.Spec.CoreTemplate.Labels["apps.emqx.io/db-role"] = "core"

// Replicant
if r.Spec.ReplicantTemplate.Labels == nil {
r.Spec.ReplicantTemplate.Labels = make(map[string]string)
}
r.Spec.ReplicantTemplate.Labels["apps.emqx.io/instance"] = r.Name
r.Spec.ReplicantTemplate.Labels["apps.emqx.io/managed-by"] = "emqx-operator"
r.Spec.ReplicantTemplate.Labels["apps.emqx.io/db-role"] = "replicant"
}

func (r *EMQX) defaultLabels() {
r.Labels = AddLabel(r.Labels, "apps.emqx.io/managed-by", "emqx-operator")
r.Labels = AddLabel(r.Labels, "apps.emqx.io/instance", r.GetName())

// Dashboard service
if r.Spec.DashboardServiceTemplate.Labels == nil {
r.Spec.DashboardServiceTemplate.Labels = make(map[string]string)
}
r.Spec.DashboardServiceTemplate.Labels["apps.emqx.io/instance"] = r.Name
r.Spec.DashboardServiceTemplate.Labels["apps.emqx.io/managed-by"] = "emqx-operator"
r.Spec.DashboardServiceTemplate.Labels = AddLabel(r.Spec.DashboardServiceTemplate.Labels, "apps.emqx.io/managed-by", "emqx-operator")
r.Spec.DashboardServiceTemplate.Labels = AddLabel(r.Spec.DashboardServiceTemplate.Labels, "apps.emqx.io/instance", r.GetName())

// Listeners service
if r.Spec.ListenersServiceTemplate.Labels == nil {
r.Spec.ListenersServiceTemplate.Labels = make(map[string]string)
r.Spec.ListenersServiceTemplate.Labels = AddLabel(r.Spec.ListenersServiceTemplate.Labels, "apps.emqx.io/managed-by", "emqx-operator")
r.Spec.ListenersServiceTemplate.Labels = AddLabel(r.Spec.ListenersServiceTemplate.Labels, "apps.emqx.io/instance", r.GetName())

// Core
r.Spec.CoreTemplate.Labels = AddLabel(r.Spec.CoreTemplate.Labels, "apps.emqx.io/managed-by", "emqx-operator")
r.Spec.CoreTemplate.Labels = AddLabel(r.Spec.CoreTemplate.Labels, "apps.emqx.io/instance", r.GetName())
r.Spec.CoreTemplate.Labels = AddLabel(r.Spec.CoreTemplate.Labels, "apps.emqx.io/db-role", "core")

// Replicant
if r.Spec.ReplicantTemplate != nil {
r.Spec.ReplicantTemplate.Labels = AddLabel(r.Spec.ReplicantTemplate.Labels, "apps.emqx.io/managed-by", "emqx-operator")
r.Spec.ReplicantTemplate.Labels = AddLabel(r.Spec.ReplicantTemplate.Labels, "apps.emqx.io/instance", r.GetName())
r.Spec.ReplicantTemplate.Labels = AddLabel(r.Spec.ReplicantTemplate.Labels, "apps.emqx.io/db-role", "replicant")
}
r.Spec.ListenersServiceTemplate.Labels["apps.emqx.io/instance"] = r.Name
r.Spec.ListenersServiceTemplate.Labels["apps.emqx.io/managed-by"] = "emqx-operator"
}

func (r *EMQX) defaultAnnotations() {
Expand All @@ -188,10 +182,12 @@ func (r *EMQX) defaultAnnotations() {
}
delete(annotations, "kubectl.kubernetes.io/last-applied-configuration")

r.Spec.CoreTemplate.Annotations = mergeMap(r.Spec.CoreTemplate.Annotations, annotations)
r.Spec.ReplicantTemplate.Annotations = mergeMap(r.Spec.ReplicantTemplate.Annotations, annotations)
r.Spec.DashboardServiceTemplate.Annotations = mergeMap(r.Spec.DashboardServiceTemplate.Annotations, annotations)
r.Spec.ListenersServiceTemplate.Annotations = mergeMap(r.Spec.ListenersServiceTemplate.Annotations, annotations)
r.Spec.CoreTemplate.Annotations = mergeMap(r.Spec.CoreTemplate.Annotations, annotations)
if r.Spec.ReplicantTemplate != nil {
r.Spec.ReplicantTemplate.Annotations = mergeMap(r.Spec.ReplicantTemplate.Annotations, annotations)
}
}

func (r *EMQX) defaultBootstrapConfig() {
Expand Down Expand Up @@ -230,15 +226,6 @@ func (r *EMQX) defaultBootstrapConfig() {
r.Spec.BootstrapConfig = config.String()
}

func (r *EMQX) defaultReplicas() {
if r.Spec.CoreTemplate.Spec.Replicas == nil {
r.Spec.CoreTemplate.Spec.Replicas = pointer.Int32Ptr(2)
}
if r.Spec.ReplicantTemplate.Spec.Replicas == nil {
r.Spec.ReplicantTemplate.Spec.Replicas = pointer.Int32Ptr(3)
}
}

func (r *EMQX) defaultDashboardServiceTemplate() {
r.Spec.DashboardServiceTemplate.Spec.Selector = r.Spec.CoreTemplate.Labels
dashboardPort, err := GetDashboardServicePort(r)
Expand Down Expand Up @@ -300,34 +287,31 @@ func (r *EMQX) defaultProbe() {
r.Spec.CoreTemplate.Spec.LivenessProbe = defaultLivenessProbe
}

if r.Spec.ReplicantTemplate.Spec.ReadinessProbe == nil {
r.Spec.ReplicantTemplate.Spec.ReadinessProbe = defaultReadinessProbe
}
if r.Spec.ReplicantTemplate.Spec.LivenessProbe == nil {
r.Spec.ReplicantTemplate.Spec.LivenessProbe = defaultLivenessProbe
if r.Spec.ReplicantTemplate != nil {
if r.Spec.ReplicantTemplate.Spec.ReadinessProbe == nil {
r.Spec.ReplicantTemplate.Spec.ReadinessProbe = defaultReadinessProbe
}
if r.Spec.ReplicantTemplate.Spec.LivenessProbe == nil {
r.Spec.ReplicantTemplate.Spec.LivenessProbe = defaultLivenessProbe
}
}
}

func (r *EMQX) defaultSecurityContext() {
if r.Spec.CoreTemplate.Spec.PodSecurityContext == nil {
r.Spec.CoreTemplate.Spec.PodSecurityContext = &corev1.PodSecurityContext{
RunAsUser: pointer.Int64(1000),
RunAsGroup: pointer.Int64(1000),
FSGroup: pointer.Int64(1000),
}

r.Spec.CoreTemplate.Spec.PodSecurityContext.FSGroupChangePolicy = (*corev1.PodFSGroupChangePolicy)(pointer.String("Always"))
r.Spec.CoreTemplate.Spec.PodSecurityContext.SupplementalGroups = []int64{1000}
podSecurityContext := &corev1.PodSecurityContext{
RunAsUser: pointer.Int64(1000),
RunAsGroup: pointer.Int64(1000),
FSGroup: pointer.Int64(1000),
FSGroupChangePolicy: (*corev1.PodFSGroupChangePolicy)(pointer.String("Always")),
SupplementalGroups: []int64{1000},
}

if r.Spec.ReplicantTemplate.Spec.PodSecurityContext == nil {
r.Spec.ReplicantTemplate.Spec.PodSecurityContext = &corev1.PodSecurityContext{
RunAsUser: pointer.Int64(1000),
RunAsGroup: pointer.Int64(1000),
FSGroup: pointer.Int64(1000),
if r.Spec.CoreTemplate.Spec.PodSecurityContext == nil {
r.Spec.CoreTemplate.Spec.PodSecurityContext = podSecurityContext.DeepCopy()
}
if r.Spec.ReplicantTemplate != nil {
if r.Spec.ReplicantTemplate.Spec.PodSecurityContext == nil {
r.Spec.ReplicantTemplate.Spec.PodSecurityContext = podSecurityContext.DeepCopy()
}

r.Spec.ReplicantTemplate.Spec.PodSecurityContext.FSGroupChangePolicy = (*corev1.PodFSGroupChangePolicy)(pointer.String("Always"))
r.Spec.ReplicantTemplate.Spec.PodSecurityContext.SupplementalGroups = []int64{1000}
}
}
Loading

0 comments on commit ab0d9d2

Please sign in to comment.