Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(AwsRedisInstance): make authEnabled mutable #589

Merged
merged 2 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/cloud-control/v1beta1/redisinstance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ type RedisInstanceAzure struct {
ReplicasPerPrimary int `json:"replicasPerPrimary,omitempty"`
}

// +kubebuilder:validation:XValidation:rule=(self.authEnabled == false || self.transitEncryptionEnabled == true), message="authEnabled can only be true if TransitEncryptionEnabled is also true"
ijovovic marked this conversation as resolved.
Show resolved Hide resolved
type RedisInstanceAws struct {
// +kubebuilder:validation:Required
CacheNodeType string `json:"cacheNodeType"`
Expand All @@ -230,7 +231,6 @@ type RedisInstanceAws struct {

// +optional
// +kubebuilder:default=false
// +kubebuilder:validation:XValidation:rule=(self == oldSelf), message="AuthEnabled is immutable."
AuthEnabled bool `json:"authEnabled"`

// Specifies the weekly time range during which maintenance on the cluster is
Expand Down
2 changes: 1 addition & 1 deletion api/cloud-resources/v1beta1/awsredisinstance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
)

// AwsRedisInstanceSpec defines the desired state of AwsRedisInstance
// +kubebuilder:validation:XValidation:rule=(self.authEnabled == false || self.transitEncryptionEnabled == true), message="authEnabled can only be true if TransitEncryptionEnabled is also true"
type AwsRedisInstanceSpec struct {
// +optional
IpRange IpRangeRef `json:"ipRange"`
Expand All @@ -48,7 +49,6 @@ type AwsRedisInstanceSpec struct {

// +optional
// +kubebuilder:default=false
// +kubebuilder:validation:XValidation:rule=(self == oldSelf), message="AuthEnabled is immutable."
AuthEnabled bool `json:"authEnabled"`

// Specifies the weekly time range during which maintenance on the cluster is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ spec:
authEnabled:
default: false
type: boolean
x-kubernetes-validations:
- message: AuthEnabled is immutable.
rule: (self == oldSelf)
autoMinorVersionUpgrade:
default: false
type: boolean
Expand Down Expand Up @@ -84,6 +81,11 @@ spec:
required:
- cacheNodeType
type: object
x-kubernetes-validations:
- message: authEnabled can only be true if TransitEncryptionEnabled
is also true
rule: (self.authEnabled == false || self.transitEncryptionEnabled
== true)
azure:
properties:
enableNonSslPort:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
cloud-resources.kyma-project.io/version: v0.0.11
cloud-resources.kyma-project.io/version: v0.0.12
name: awsredisinstances.cloud-resources.kyma-project.io
spec:
group: cloud-resources.kyma-project.io
Expand Down Expand Up @@ -47,9 +47,6 @@ spec:
authEnabled:
default: false
type: boolean
x-kubernetes-validations:
- message: AuthEnabled is immutable.
rule: (self == oldSelf)
authSecret:
properties:
annotations:
Expand Down Expand Up @@ -106,6 +103,9 @@ spec:
required:
- cacheNodeType
type: object
x-kubernetes-validations:
- message: authEnabled can only be true if TransitEncryptionEnabled is also true
rule: (self.authEnabled == false || self.transitEncryptionEnabled == true)
status:
description: AwsRedisInstanceStatus defines the observed state of AwsRedisInstance
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ spec:
authEnabled:
default: false
type: boolean
x-kubernetes-validations:
- message: AuthEnabled is immutable.
rule: (self == oldSelf)
autoMinorVersionUpgrade:
default: false
type: boolean
Expand Down Expand Up @@ -84,6 +81,11 @@ spec:
required:
- cacheNodeType
type: object
x-kubernetes-validations:
- message: authEnabled can only be true if TransitEncryptionEnabled
is also true
rule: (self.authEnabled == false || self.transitEncryptionEnabled
== true)
azure:
properties:
enableNonSslPort:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
cloud-resources.kyma-project.io/version: v0.0.11
cloud-resources.kyma-project.io/version: v0.0.12
name: awsredisinstances.cloud-resources.kyma-project.io
spec:
group: cloud-resources.kyma-project.io
Expand Down Expand Up @@ -47,9 +47,6 @@ spec:
authEnabled:
default: false
type: boolean
x-kubernetes-validations:
- message: AuthEnabled is immutable.
rule: (self == oldSelf)
authSecret:
properties:
annotations:
Expand Down Expand Up @@ -106,6 +103,9 @@ spec:
required:
- cacheNodeType
type: object
x-kubernetes-validations:
- message: authEnabled can only be true if TransitEncryptionEnabled is also true
rule: (self.authEnabled == false || self.transitEncryptionEnabled == true)
status:
description: AwsRedisInstanceStatus defines the observed state of AwsRedisInstance
properties:
Expand Down
2 changes: 1 addition & 1 deletion config/patchAfterMakeManifests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ echo "Patching CRDs..."
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.1.0"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_ipranges.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.2"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_awsnfsvolumes.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.2"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_awsnfsvolumebackups.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.11"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_awsredisinstances.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.12"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_awsredisinstances.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.4"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_gcpnfsvolumes.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.9"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_gcpredisinstances.yaml
yq -i '.metadata.annotations."cloud-resources.kyma-project.io/version" = "v0.0.1"' $SCRIPT_DIR/crd/bases/cloud-resources.kyma-project.io_azurevpcpeerings.yaml
Expand Down
8 changes: 8 additions & 0 deletions internal/controller/cloud-control/redisinstance_aws_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ var _ = Describe("Feature: KCP RedisInstance", func() {
infra.AwsMock().SetAwsElastiCacheLifeCycleState(*awsElastiCacheClusterInstance.ReplicationGroupId, awsmeta.ElastiCache_AVAILABLE)
})

By("And when AWS Redis UserGroup is Active", func() {
infra.AwsMock().SetAwsElastiCacheUserGroupLifeCycleState(*awsElastiCacheClusterInstance.ReplicationGroupId, awsmeta.ElastiCache_UserGroup_ACTIVE)
})

By("Then RedisInstance has Ready condition", func() {
Eventually(LoadAndCheck).
WithArguments(infra.Ctx(), infra.KCP().Client(), redisInstance,
Expand Down Expand Up @@ -139,6 +143,10 @@ var _ = Describe("Feature: KCP RedisInstance", func() {
infra.AwsMock().DeleteAwsElastiCacheByName(*awsElastiCacheClusterInstance.ReplicationGroupId)
})

By("And When AWS Redis user group is deleted", func() {
infra.AwsMock().DeleteAwsElastiCacheUserGroupByName(*awsElastiCacheClusterInstance.ReplicationGroupId)
})

By("Then RedisInstance does not exist", func() {
Eventually(IsDeleted, 5*time.Second).
WithArguments(infra.Ctx(), infra.KCP().Client(), redisInstance).
Expand Down
9 changes: 9 additions & 0 deletions pkg/kcp/provider/aws/meta/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,12 @@ const (
ElastiCache_CREATE_FAILED ElastiCacheState = "create-failed"
ElastiCache_SNAPSHOTTING ElastiCacheState = "snapshotting"
)

type ElastiCacheUserGroupState = string

const (
ElastiCache_UserGroup_ACTIVE ElastiCacheUserGroupState = "active"
ElastiCache_UserGroup_CREATING ElastiCacheUserGroupState = "creating"
ElastiCache_UserGroup_DELETING ElastiCacheUserGroupState = "deleting"
ElastiCache_UserGroup_MODIFYING ElastiCacheUserGroupState = "modifying"
)
71 changes: 71 additions & 0 deletions pkg/kcp/provider/aws/mock/elastiCacheClientFake.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import (
type AwsElastiCacheMockUtils interface {
GetAwsElastiCacheByName(name string) *elasticacheTypes.ReplicationGroup
SetAwsElastiCacheLifeCycleState(name string, state awsmeta.ElastiCacheState)
SetAwsElastiCacheUserGroupLifeCycleState(name string, state awsmeta.ElastiCacheUserGroupState)
DeleteAwsElastiCacheByName(name string)
DeleteAwsElastiCacheUserGroupByName(name string)
DescribeAwsElastiCacheParametersByName(groupName string) map[string]string
}

Expand All @@ -45,11 +47,13 @@ type elastiCacheClientFake struct {
parameterGroupMutex *sync.Mutex
elasticacheMutex *sync.Mutex
secretStoreMutex *sync.Mutex
userGroupsMutex *sync.Mutex
replicationGroups map[string]*elasticacheTypes.ReplicationGroup
cacheClusters map[string]*elasticacheTypes.CacheCluster
parameters map[string]map[string]elasticacheTypes.Parameter
parameterGroups map[string]*elasticacheTypes.CacheParameterGroup
subnetGroups map[string]*elasticacheTypes.CacheSubnetGroup
userGroups map[string]*elasticacheTypes.UserGroup
secretStore map[string]*secretsmanager.GetSecretValueOutput
}

Expand All @@ -63,13 +67,26 @@ func (client *elastiCacheClientFake) SetAwsElastiCacheLifeCycleState(name string
}
}

func (client *elastiCacheClientFake) SetAwsElastiCacheUserGroupLifeCycleState(name string, state awsmeta.ElastiCacheUserGroupState) {
if instance, ok := client.userGroups[name]; ok {
instance.Status = ptr.To(state)
}
}

func (client *elastiCacheClientFake) DeleteAwsElastiCacheByName(name string) {
client.elasticacheMutex.Lock()
defer client.elasticacheMutex.Unlock()

delete(client.replicationGroups, name)
}

func (client *elastiCacheClientFake) DeleteAwsElastiCacheUserGroupByName(name string) {
client.userGroupsMutex.Lock()
defer client.userGroupsMutex.Unlock()

delete(client.userGroups, name)
}

func (client *elastiCacheClientFake) DescribeAwsElastiCacheParametersByName(groupName string) map[string]string {
result := map[string]string{}

Expand Down Expand Up @@ -225,13 +242,20 @@ func (client *elastiCacheClientFake) CreateElastiCacheReplicationGroup(ctx conte
PreferredMaintenanceWindow: options.PreferredMaintenanceWindow,
}

authTokenEnabled := false
if options.AuthTokenSecretString != nil {
authTokenEnabled = true
}

client.replicationGroups[options.Name] = &elasticacheTypes.ReplicationGroup{
ReplicationGroupId: ptr.To(options.Name),
Status: ptr.To("creating"),
CacheNodeType: ptr.To(options.CacheNodeType),
AutoMinorVersionUpgrade: ptr.To(options.AutoMinorVersionUpgrade),
TransitEncryptionEnabled: ptr.To(options.TransitEncryptionEnabled),
AuthTokenEnabled: ptr.To(authTokenEnabled),
MemberClusters: []string{options.Name},
UserGroupIds: []string{},
NodeGroups: []elasticacheTypes.NodeGroup{
{
PrimaryEndpoint: &elasticacheTypes.Endpoint{
Expand Down Expand Up @@ -275,6 +299,19 @@ func (client *elastiCacheClientFake) ModifyElastiCacheReplicationGroup(ctx conte
if options.TransitEncryptionMode != nil {
instance.TransitEncryptionMode = *options.TransitEncryptionMode
}

if len(options.UserGroupIdsToAdd) > 0 {
instance.UserGroupIds = append(instance.UserGroupIds, options.UserGroupIdsToAdd...)
instance.AuthTokenEnabled = ptr.To(false)
}
if len(options.UserGroupIdsToRemove) > 0 {
_, remaining := pie.Diff(instance.UserGroupIds, options.UserGroupIdsToRemove)
instance.UserGroupIds = remaining
}

if options.AuthTokenSecretString != nil {
instance.AuthTokenEnabled = ptr.To(true)
}
}

return &elasticache.ModifyReplicationGroupOutput{}, nil
Expand Down Expand Up @@ -303,3 +340,37 @@ func (client *elastiCacheClientFake) DescribeElastiCacheCluster(ctx context.Cont

return []elasticacheTypes.CacheCluster{*cacheCluster}, nil
}

func (client *elastiCacheClientFake) DescribeUserGroup(ctx context.Context, id string) (*elasticacheTypes.UserGroup, error) {
client.userGroupsMutex.Lock()
defer client.userGroupsMutex.Unlock()

userGroup := client.userGroups[id]

return userGroup, nil
}

func (client *elastiCacheClientFake) CreateUserGroup(ctx context.Context, id string, tags []elasticacheTypes.Tag) (*elasticache.CreateUserGroupOutput, error) {
client.userGroupsMutex.Lock()
defer client.userGroupsMutex.Unlock()

client.userGroups[id] = &elasticacheTypes.UserGroup{
Engine: ptr.To("redis"),
UserGroupId: ptr.To(id),
Status: ptr.To("creating"),
UserIds: []string{"default"},
}

return &elasticache.CreateUserGroupOutput{UserGroupId: ptr.To(id)}, nil
}

func (client *elastiCacheClientFake) DeleteUserGroup(ctx context.Context, id string) error {
client.userGroupsMutex.Lock()
defer client.userGroupsMutex.Unlock()

if instance, ok := client.userGroups[id]; ok {
instance.Status = ptr.To("deleting")
}

return nil
}
2 changes: 2 additions & 0 deletions pkg/kcp/provider/aws/mock/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ func New() Server {
subnetGroupMutex: &sync.Mutex{},
parameterGroupMutex: &sync.Mutex{},
secretStoreMutex: &sync.Mutex{},
userGroupsMutex: &sync.Mutex{},
replicationGroups: map[string]*elasticacheTypes.ReplicationGroup{},
cacheClusters: map[string]*elasticacheTypes.CacheCluster{},
subnetGroups: map[string]*elasticacheTypes.CacheSubnetGroup{},
parameterGroups: map[string]*elasticacheTypes.CacheParameterGroup{},
parameters: map[string]map[string]elasticacheTypes.Parameter{},
secretStore: map[string]*secretsmanager.GetSecretValueOutput{},
userGroups: map[string]*elasticacheTypes.UserGroup{},
},
}
}
Expand Down
Loading
Loading