Skip to content

Commit

Permalink
[artemiscloud#348] Fix conversion of reverted redelivery fields from …
Browse files Browse the repository at this point in the history
…v2alpha5 to v1beta1
  • Loading branch information
brusdev committed Oct 25, 2022
1 parent a3dc20c commit cbc381e
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 6 deletions.
6 changes: 4 additions & 2 deletions api/v1beta1/activemqartemis_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package v1beta1

import (
"encoding/json"

"github.com/RHsyseng/operator-utils/pkg/olm"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -83,9 +85,9 @@ type AddressSettingType struct {
// the time (in ms) to wait before redelivering a cancelled message.
RedeliveryDelay *int32 `json:"redeliveryDelay,omitempty"`
// multiplier to apply to the redelivery-delay
RedeliveryDelayMultiplier *string `json:"redeliveryDelayMultiplier,omitempty"`
RedeliveryDelayMultiplier *json.Number `json:"redeliveryDelayMultiplier,omitempty"`
// factor by which to modify the redelivery delay slightly to avoid collisions
RedeliveryCollisionAvoidanceFactor *string `json:"redeliveryCollisionAvoidanceFactor,omitempty"`
RedeliveryCollisionAvoidanceFactor *json.Number `json:"redeliveryCollisionAvoidanceFactor,omitempty"`
// Maximum value for the redelivery-delay
MaxRedeliveryDelay *int32 `json:"maxRedeliveryDelay,omitempty"`
// how many times to attempt to deliver a message before sending to dead letter address
Expand Down
5 changes: 3 additions & 2 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions controllers/activemqartemis_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package controllers

import (
"context"
"encoding/json"
"fmt"
"reflect"

appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -139,6 +141,11 @@ func (r *ActiveMQArtemisReconciler) Reconcile(ctx context.Context, request ctrl.
// When deleting before creation reconcile won't be called
if err = r.Get(context.TODO(), request.NamespacedName, customResource); err == nil {

if err := UpdateCR(customResource, r.Client, request.NamespacedName); err != nil {
reqLogger.Error(err, "Error updating the CR", "ActiveMQArtemis", request.NamespacedName)
return ctrl.Result{}, err
}

namer := MakeNamers(customResource)
reconciler := ActiveMQArtemisReconcilerImpl{}

Expand Down Expand Up @@ -238,6 +245,58 @@ func (r *ActiveMQArtemisReconciler) SetupWithManager(mgr ctrl.Manager) error {
return err
}

func UpdateCR(cr *brokerv1beta1.ActiveMQArtemis, client rtclient.Client, namespacedName types.NamespacedName) error {

// The redeliveryDelayMultiplier and RedeliveryCollisionAvoidanceFactor fields are *float32
// in v2alpha5/v0.20.1 and they are *string in v2alpha5/v1.0.0.
// Those fields has been reverted to the original type to fix this backward compatibility issue
// but this reversion has caused a conversion issue from v2alpha5 to v1beta1.
// To fix this conversion issue the type of v1beta1 fields have been changed to json.Number.
// The json.Number allows to unmarshal float and string values but it only allows to marshal string values.
// The following code block patches CR that contain float values and uses the string lenght to check
// if those values has been already patched.
patchPayload := []map[string]string{}
addressSettings := cr.Spec.AddressSettings.AddressSetting
for i := 0; i < len(addressSettings); i++ {
if addressSettings[i].RedeliveryDelayMultiplier != nil && len(addressSettings[i].RedeliveryDelayMultiplier.String()) < 9 {
redeliveryDelayMultiplier, err := addressSettings[i].RedeliveryDelayMultiplier.Float64()
if err != nil {
clog.Error(err, "Error parsing RedeliveryDelayMultiplier", "ActiveMQArtemis", namespacedName)
return err
}
patchPayload = append(patchPayload, map[string]string{
"op": "replace",
"path": fmt.Sprintf("/spec/addressSettings/addressSetting/%d/redeliveryDelayMultiplier", i),
"value": fmt.Sprintf("%.9f", redeliveryDelayMultiplier),
})
}
if addressSettings[i].RedeliveryCollisionAvoidanceFactor != nil && len(addressSettings[i].RedeliveryCollisionAvoidanceFactor.String()) < 9 {
redeliveryCollisionAvoidanceFactor, err := addressSettings[i].RedeliveryCollisionAvoidanceFactor.Float64()
if err != nil {
clog.Error(err, "Error parsing RedeliveryCollisionAvoidanceFactor", "ActiveMQArtemis", namespacedName)
return err
}
patchPayload = append(patchPayload, map[string]string{
"op": "replace",
"path": fmt.Sprintf("/spec/addressSettings/addressSetting/%d/redeliveryCollisionAvoidanceFactor", i),
"value": fmt.Sprintf("%.9f", redeliveryCollisionAvoidanceFactor),
})
}
}

if len(patchPayload) > 0 {
payloadBytes, _ := json.Marshal(patchPayload)

patchObj := rtclient.RawPatch(types.JSONPatchType, payloadBytes)
if err := client.Patch(context.TODO(), cr, patchObj); err != nil {
clog.Error(err, "unable to patch CR", "ActiveMQArtemis", namespacedName)
return err
}
}

return nil
}

func UpdateCRStatus(cr *brokerv1beta1.ActiveMQArtemis, client rtclient.Client, namespacedName types.NamespacedName) error {

common.SetReadyCondition(&cr.Status.Conditions)
Expand Down
8 changes: 8 additions & 0 deletions controllers/activemqartemis_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"strconv"
"strings"

"github.com/artemiscloud/activemq-artemis-operator/api/v1beta1"
brokerv2alpha4 "github.com/artemiscloud/activemq-artemis-operator/api/v2alpha4"
"github.com/artemiscloud/activemq-artemis-operator/api/v2alpha5"
"github.com/artemiscloud/activemq-artemis-operator/pkg/resources/environments"
Expand Down Expand Up @@ -250,6 +251,7 @@ var _ = Describe("artemis controller", func() {
AddressSetting: []v2alpha5.AddressSettingType{
{
Match: "#",
RedeliveryDelayMultiplier: &float32Var,
RedeliveryCollisionAvoidanceFactor: &float32Var,
},
},
Expand All @@ -267,6 +269,12 @@ var _ = Describe("artemis controller", func() {
g.Expect(k8sClient.Get(ctx, key, createdSs)).Should(Succeed())
}, timeout, interval).Should(Succeed())

key = types.NamespacedName{Name: toCreate.Name, Namespace: toCreate.Namespace}
createdCrd := &v1beta1.ActiveMQArtemis{}
Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(ctx, key, createdCrd)).Should(Succeed())
g.Expect(len(createdCrd.Status.PodStatus.Stopped)).Should(BeEquivalentTo(1))
}, existingClusterTimeout, existingClusterInterval).Should(Succeed())
})
})

Expand Down
13 changes: 11 additions & 2 deletions pkg/utils/cr2jinja2/cr2jinja2.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cr2jinja2

import (
"encoding/json"
"hash/fnv"

"github.com/artemiscloud/activemq-artemis-operator/api/v1beta1"
Expand Down Expand Up @@ -121,6 +122,14 @@ func checkFloat32(prop *float32) *string {
return &tmp
}

func checkFloat64AsJsonNumber(prop *json.Number) *string {
if nil == prop {
return nil
}
tmp := fmt.Sprint(prop.Float64())
return &tmp
}

func checkFloat32AsString(propstr *string) *string {
var prop *float32 = nil
var value float64
Expand Down Expand Up @@ -673,10 +682,10 @@ func processAddressSettingsV1beta1(sb *strings.Builder, addressSettings *[]v1bet
if value := checkInt32(s.RedeliveryDelay); value != nil {
sb.WriteString(" redelivery_delay: " + *value + "\n")
}
if value := checkFloat32AsString(s.RedeliveryDelayMultiplier); value != nil {
if value := checkFloat64AsJsonNumber(s.RedeliveryDelayMultiplier); value != nil {
sb.WriteString(" redelivery_delay_multiplier: " + *value + "\n")
}
if value := checkFloat32AsString(s.RedeliveryCollisionAvoidanceFactor); value != nil {
if value := checkFloat64AsJsonNumber(s.RedeliveryCollisionAvoidanceFactor); value != nil {
sb.WriteString(" redelivery_collision_avoidance_factor: " + *value + "\n")
}
if value := checkInt32(s.MaxRedeliveryDelay); value != nil {
Expand Down

0 comments on commit cbc381e

Please sign in to comment.