fix syncing of stream CRDs (#2152)

* fix syncing of stream CRDs and improve corresponding unit tests
This commit is contained in:
Felix Kunde 2022-12-30 13:09:15 +01:00 committed by GitHub
parent c1657ec484
commit 4534a4cd9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 27 deletions

View File

@ -374,13 +374,16 @@ func (c *Cluster) createOrUpdateStreams() error {
} }
for _, appId := range appIds { for _, appId := range appIds {
streamExists := false
// update stream when it exists and EventStreams array differs // update stream when it exists and EventStreams array differs
for _, stream := range streams.Items { for _, stream := range streams.Items {
if appId == stream.Spec.ApplicationId { if appId == stream.Spec.ApplicationId {
streamExists = true
desiredStreams := c.generateFabricEventStream(appId) desiredStreams := c.generateFabricEventStream(appId)
if match, reason := sameStreams(stream.Spec.EventStreams, desiredStreams.Spec.EventStreams); !match { if match, reason := sameStreams(stream.Spec.EventStreams, desiredStreams.Spec.EventStreams); !match {
c.logger.Debugf("updating event streams: %s", reason) c.logger.Debugf("updating event streams: %s", reason)
desiredStreams.ObjectMeta.ResourceVersion = stream.ObjectMeta.ResourceVersion desiredStreams.ObjectMeta = stream.ObjectMeta
err = c.updateStreams(desiredStreams) err = c.updateStreams(desiredStreams)
if err != nil { if err != nil {
return fmt.Errorf("failed updating event stream %s: %v", stream.Name, err) return fmt.Errorf("failed updating event stream %s: %v", stream.Name, err)
@ -390,12 +393,15 @@ func (c *Cluster) createOrUpdateStreams() error {
continue continue
} }
} }
c.logger.Infof("event streams with applicationId %s do not exist, create it", appId)
streamCRD, err := c.createStreams(appId) if !streamExists {
if err != nil { c.logger.Infof("event streams with applicationId %s do not exist, create it", appId)
return fmt.Errorf("failed creating event streams with applicationId %s: %v", appId, err) streamCRD, err := c.createStreams(appId)
if err != nil {
return fmt.Errorf("failed creating event streams with applicationId %s: %v", appId, err)
}
c.logger.Infof("event streams %q have been successfully created", streamCRD.Name)
} }
c.logger.Infof("event streams %q have been successfully created", streamCRD.Name)
} }
return nil return nil

View File

@ -1,7 +1,6 @@
package cluster package cluster
import ( import (
"encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
@ -167,6 +166,15 @@ var (
} }
) )
func TestGatherApplicationIds(t *testing.T) {
testAppIds := []string{appId}
appIds := gatherApplicationIds(pg.Spec.Streams)
if !util.IsEqualIgnoreOrder(testAppIds, appIds) {
t.Errorf("gathered applicationIds do not match, expected %#v, got %#v", testAppIds, appIds)
}
}
func TestGenerateFabricEventStream(t *testing.T) { func TestGenerateFabricEventStream(t *testing.T) {
client, _ := newFakeK8sStreamClient() client, _ := newFakeK8sStreamClient()
@ -206,12 +214,18 @@ func TestGenerateFabricEventStream(t *testing.T) {
t.Errorf("malformed FabricEventStream, expected %#v, got %#v", fes, result) t.Errorf("malformed FabricEventStream, expected %#v, got %#v", fes, result)
} }
// compare stream returned from API with expected stream
listOptions := metav1.ListOptions{ listOptions := metav1.ListOptions{
LabelSelector: cluster.labelsSet(true).String(), LabelSelector: cluster.labelsSet(true).String(),
} }
streams, err := cluster.KubeClient.FabricEventStreams(namespace).List(context.TODO(), listOptions) streams, err := cluster.KubeClient.FabricEventStreams(namespace).List(context.TODO(), listOptions)
assert.NoError(t, err) assert.NoError(t, err)
// check if there is only one stream
if len(streams.Items) > 1 {
t.Errorf("too many stream CRDs found: got %d, but expected only one", len(streams.Items))
}
// compare stream returned from API with expected stream
if match, _ := sameStreams(streams.Items[0].Spec.EventStreams, fes.Spec.EventStreams); !match { if match, _ := sameStreams(streams.Items[0].Spec.EventStreams, fes.Spec.EventStreams); !match {
t.Errorf("malformed FabricEventStream returned from API, expected %#v, got %#v", fes, streams.Items[0]) t.Errorf("malformed FabricEventStream returned from API, expected %#v, got %#v", fes, streams.Items[0])
} }
@ -220,9 +234,15 @@ func TestGenerateFabricEventStream(t *testing.T) {
err = cluster.createOrUpdateStreams() err = cluster.createOrUpdateStreams()
assert.NoError(t, err) assert.NoError(t, err)
// compare stream resturned from API with generated stream
streams, err = cluster.KubeClient.FabricEventStreams(namespace).List(context.TODO(), listOptions) streams, err = cluster.KubeClient.FabricEventStreams(namespace).List(context.TODO(), listOptions)
assert.NoError(t, err) assert.NoError(t, err)
// check if there is still only one stream
if len(streams.Items) > 1 {
t.Errorf("too many stream CRDs found after sync: got %d, but expected only one", len(streams.Items))
}
// compare stream resturned from API with generated stream
if match, _ := sameStreams(streams.Items[0].Spec.EventStreams, result.Spec.EventStreams); !match { if match, _ := sameStreams(streams.Items[0].Spec.EventStreams, result.Spec.EventStreams); !match {
t.Errorf("returned FabricEventStream differs from generated one, expected %#v, got %#v", result, streams.Items[0]) t.Errorf("returned FabricEventStream differs from generated one, expected %#v, got %#v", result, streams.Items[0])
} }
@ -335,31 +355,26 @@ func TestUpdateFabricEventStream(t *testing.T) {
_, err = cluster.createStatefulSet() _, err = cluster.createStatefulSet()
assert.NoError(t, err) assert.NoError(t, err)
// now create the stream
err = cluster.createOrUpdateStreams() err = cluster.createOrUpdateStreams()
assert.NoError(t, err) assert.NoError(t, err)
var pgSpec acidv1.PostgresSpec // change specs of streams and patch CRD
pgSpec.Streams = []acidv1.Stream{ for i, stream := range pg.Spec.Streams {
{ if stream.ApplicationId == appId {
ApplicationId: appId, streamTable := stream.Tables["data.bar"]
Database: dbName, streamTable.EventType = "stream-type-c"
Tables: map[string]acidv1.StreamTable{ stream.Tables["data.bar"] = streamTable
"data.bar": acidv1.StreamTable{ stream.BatchSize = k8sutil.UInt32ToPointer(uint32(250))
EventType: "stream-type-c", pg.Spec.Streams[i] = stream
IdColumn: k8sutil.StringToPointer("b_id"), }
PayloadColumn: k8sutil.StringToPointer("b_payload"),
},
},
BatchSize: k8sutil.UInt32ToPointer(uint32(250)),
},
} }
patch, err := json.Marshal(struct {
PostgresSpec interface{} `json:"spec"` patchData, err := specPatch(pg.Spec)
}{&pgSpec})
assert.NoError(t, err) assert.NoError(t, err)
pgPatched, err := cluster.KubeClient.Postgresqls(namespace).Patch( pgPatched, err := cluster.KubeClient.Postgresqls(namespace).Patch(
context.TODO(), cluster.Name, types.MergePatchType, patch, metav1.PatchOptions{}, "spec") context.TODO(), cluster.Name, types.MergePatchType, patchData, metav1.PatchOptions{}, "spec")
assert.NoError(t, err) assert.NoError(t, err)
cluster.Postgresql.Spec = pgPatched.Spec cluster.Postgresql.Spec = pgPatched.Spec