Skip to content

Commit

Permalink
Fix 1838 - nil panic from elasticache newEndpoint
Browse files Browse the repository at this point in the history
Signed-off-by: d.small@sap.com <d.small@sap.com>
  • Loading branch information
dee0sap committed Aug 29, 2023
1 parent c62342b commit fd1cd2e
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pkg/clients/elasticache/elasticache.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ func generateReplicationGroupPendingModifiedValues(in elasticachetypes.Replicati
func newEndpoint(rg elasticachetypes.ReplicationGroup) v1beta1.Endpoint {
var e *elasticachetypes.Endpoint
switch {
case !aws.ToBool(rg.ClusterEnabled) && len(rg.NodeGroups) > 0:
case !aws.ToBool(rg.ClusterEnabled) && len(rg.NodeGroups) > 0 && rg.NodeGroups[0].PrimaryEndpoint != nil:
e = rg.NodeGroups[0].PrimaryEndpoint
case aws.ToBool(rg.ClusterEnabled) && rg.ConfigurationEndpoint != nil:
e = rg.ConfigurationEndpoint
Expand Down
95 changes: 95 additions & 0 deletions pkg/controller/cache/replicationgroup/managed_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package replicationgroup
import (
"context"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/elasticache"
Expand Down Expand Up @@ -76,6 +77,12 @@ type testCase struct {

type replicationGroupModifier func(*v1beta1.ReplicationGroup)

func withAutomaticFailover(v types.AutomaticFailoverStatus) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) {
r.Status.AtProvider.AutomaticFailover = string(v)
}
}

func withConditions(c ...xpv1.Condition) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { r.Status.ConditionedStatus.Conditions = c }
}
Expand All @@ -84,6 +91,10 @@ func withProviderStatus(s string) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { r.Status.AtProvider.Status = s }
}

func withProviderStatusNodeGroups(n []v1beta1.NodeGroup) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { r.Status.AtProvider.NodeGroups = n }
}

func withReplicationGroupID(n string) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { meta.SetExternalName(r, n) }
}
Expand Down Expand Up @@ -122,6 +133,10 @@ func withNumNodeGroups(n int) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { r.Spec.ForProvider.NumNodeGroups = &n }
}

func withAtRestEncryptionEnabled(b bool) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { r.Spec.ForProvider.AtRestEncryptionEnabled = &b }
}

func withNumCacheClusters(n int) replicationGroupModifier {
return func(r *v1beta1.ReplicationGroup) { r.Spec.ForProvider.NumCacheClusters = &n }
}
Expand Down Expand Up @@ -205,6 +220,30 @@ func TestCreate(t *testing.T) {
}

func TestObserve(t *testing.T) {
var makeStringPtr = func(id string) *string {
var p = new(string)
*p = id
return p
}
var makeBoolPtr = func(v bool) *bool {
var p = new(bool)
*p = v
return p
}
var makeTimePtr = func(t time.Time) *time.Time {
var p = new(time.Time)
*p = t
return p
}
var makeArn = func(id string) *string {
return makeStringPtr("arn:aws:elasticache:eu-central-1:1001001ESOES:replicationgroup:" + id)
}
var makeDescription = func(id string) *string {
return makeStringPtr("Redis Group:" + id)
}

var successfulObserveAfterCreationFailed = "SuccessfulObserveAfterCreationFailed"

cases := []testCase{
{
name: "SuccessfulObserveWhileGroupCreating",
Expand Down Expand Up @@ -294,6 +333,62 @@ func TestObserve(t *testing.T) {
),
tokenCreated: true,
},
{
name: successfulObserveAfterCreationFailed, // Replicates issue #1838
e: &external{client: &fake.MockClient{
MockDescribeReplicationGroups: func(ctx context.Context, _ *elasticache.DescribeReplicationGroupsInput, opts []func(*elasticache.Options)) (*elasticache.DescribeReplicationGroupsOutput, error) {
return &elasticache.DescribeReplicationGroupsOutput{
ReplicationGroups: []types.ReplicationGroup{{
ARN: makeArn(successfulObserveAfterCreationFailed),
AtRestEncryptionEnabled: makeBoolPtr(true),
AuthTokenEnabled: makeBoolPtr(true),
AutomaticFailover: types.AutomaticFailoverStatusEnabled,
AuthTokenLastModifiedDate: makeTimePtr(time.Date(2023, 6, 15, 12, 21, 05, 0, time.UTC)),
DataTiering: types.DataTieringStatusDisabled,
Description: makeDescription(successfulObserveAfterCreationFailed),
MultiAZ: types.MultiAZStatusDisabled,
NodeGroups: []types.NodeGroup{
{NodeGroupId: aws.String("0001"), Status: makeStringPtr(v1beta1.StatusCreateFailed)},
{NodeGroupId: aws.String("0002"), Status: makeStringPtr(v1beta1.StatusCreateFailed)},
},
ReplicationGroupCreateTime: makeTimePtr(time.Date(2023, 6, 15, 12, 21, 05, 0, time.UTC)),
Status: aws.String(v1beta1.StatusCreateFailed),
TransitEncryptionEnabled: makeBoolPtr(true),
}},
}, nil
},
MockListTagsForResource: func(ctx context.Context, _ *elasticache.ListTagsForResourceInput, opts []func(*elasticache.Options)) (*elasticache.ListTagsForResourceOutput, error) {
return &elasticache.ListTagsForResourceOutput{
TagList: []types.Tag{
{Key: aws.String("key1"), Value: aws.String("val1")},
{Key: aws.String("key2"), Value: aws.String("val2")},
},
}, nil
},
}},
r: replicationGroup(
withReplicationGroupID(name),
withConditions(xpv1.Creating()),
withClusterEnabled(true),
withNumNodeGroups(2),
withAtRestEncryptionEnabled(true),
withAuthEnabled(true),
),
want: replicationGroup(
withReplicationGroupID(name),
withProviderStatus(v1beta1.StatusCreateFailed),
withConditions(xpv1.Unavailable()),
withNumNodeGroups(2),
withAutomaticFailover(types.AutomaticFailoverStatusEnabled),
withProviderStatusNodeGroups([]v1beta1.NodeGroup{
{NodeGroupID: "0001", Status: v1beta1.StatusCreateFailed},
{NodeGroupID: "0002", Status: v1beta1.StatusCreateFailed},
}),
withAtRestEncryptionEnabled(true),
withAuthEnabled(true),
),
tokenCreated: false,
},
{
name: "SuccessfulObserveLateInitialized",
e: &external{
Expand Down

0 comments on commit fd1cd2e

Please sign in to comment.