From a836aab18b377a5c4c0917fc642ff578ec367e7f Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:06:27 +0530 Subject: [PATCH 001/203] [Fix] : Nil pointer de-reference in conversion webhook (#615) * fix nil ptr derefer & volume issue Signed-off-by: Shubham Gupta * fix : nil ptr derefer error Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- api/v1beta1/common_types.go | 2 +- api/v1beta1/redis_conversion.go | 25 +++++++++++++++++++--- api/v1beta1/rediscluster_conversion.go | 22 ++++++++++++------- api/v1beta1/redisreplication_conversion.go | 21 +++++++++++++----- api/v1beta1/redissentinel_conversion.go | 12 +++++++---- api/v1beta1/zz_generated.deepcopy.go | 2 +- api/v1beta2/common_types.go | 4 ++-- api/v1beta2/zz_generated.deepcopy.go | 4 ++-- k8sutils/redis-cluster.go | 10 ++++----- k8sutils/redis-replication.go | 10 ++++----- k8sutils/redis-standalone.go | 10 ++++----- 11 files changed, 81 insertions(+), 41 deletions(-) diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index 66c3f5981..bb15d4bb7 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -45,7 +45,7 @@ type ExistingPasswordSecret struct { // Storage is the inteface to add pvc and pv support in redis type Storage struct { - CommonAttributes common.Storage `json:",inline"` + common.Storage `json:",inline"` } // RedisExporter interface will have the information for redis exporter related stuff diff --git a/api/v1beta1/redis_conversion.go b/api/v1beta1/redis_conversion.go index dd3722040..297eb7e3f 100644 --- a/api/v1beta1/redis_conversion.go +++ b/api/v1beta1/redis_conversion.go @@ -9,6 +9,9 @@ import ( func (src *Redis) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*redisv1beta2.Redis) + // if src == nil { + // return errors.New("source is nil") + // } // ObjectMeta dst.ObjectMeta = src.ObjectMeta @@ -16,15 +19,19 @@ func (src *Redis) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.KubernetesConfig.KubernetesConfig = src.Spec.KubernetesConfig.KubernetesConfig // RedisExporter if src.Spec.RedisExporter != nil { + dst.Spec.RedisExporter = &redisv1beta2.RedisExporter{} dst.Spec.RedisExporter.RedisExporter = src.Spec.RedisExporter.RedisExporter } // RedisConfig if src.Spec.RedisConfig != nil { + dst.Spec.RedisConfig = &redisv1beta2.RedisConfig{} dst.Spec.RedisConfig.RedisConfig = src.Spec.RedisConfig.RedisConfig } // Storage if src.Spec.Storage != nil { - dst.Spec.Storage.CommonAttributes = src.Spec.Storage.CommonAttributes + dst.Spec.Storage = &redisv1beta2.Storage{} + dst.Spec.Storage.VolumeClaimTemplate = src.Spec.Storage.VolumeClaimTemplate + dst.Spec.Storage.VolumeMount = src.Spec.Storage.VolumeMount } // NodeSelector if src.Spec.NodeSelector != nil { @@ -48,14 +55,17 @@ func (src *Redis) ConvertTo(dstRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &redisv1beta2.TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // ReadinessProbe if src.Spec.ReadinessProbe != nil { + dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe } // LivenessProbe if src.Spec.LivenessProbe != nil { + dst.Spec.LivenessProbe = &redisv1beta2.Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars @@ -80,6 +90,9 @@ func (src *Redis) ConvertTo(dstRaw conversion.Hub) error { func (dst *Redis) ConvertFrom(srcRaw conversion.Hub) error { src := srcRaw.(*redisv1beta2.Redis) + // if src == nil { + // return errors.New("source is nil") + // } // ObjectMeta dst.ObjectMeta = src.ObjectMeta @@ -87,15 +100,19 @@ func (dst *Redis) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.KubernetesConfig.KubernetesConfig = src.Spec.KubernetesConfig.KubernetesConfig // RedisExporter if src.Spec.RedisExporter != nil { + dst.Spec.RedisExporter = &RedisExporter{} dst.Spec.RedisExporter.RedisExporter = src.Spec.RedisExporter.RedisExporter } // RedisConfig if src.Spec.RedisConfig != nil { + dst.Spec.RedisConfig = &RedisConfig{} dst.Spec.RedisConfig.RedisConfig = src.Spec.RedisConfig.RedisConfig } // Storage if src.Spec.Storage != nil { - dst.Spec.Storage.CommonAttributes = src.Spec.Storage.CommonAttributes + dst.Spec.Storage = &Storage{} + dst.Spec.Storage.VolumeClaimTemplate = src.Spec.Storage.VolumeClaimTemplate + dst.Spec.Storage.VolumeMount = src.Spec.Storage.VolumeMount } // NodeSelector if src.Spec.NodeSelector != nil { @@ -119,14 +136,17 @@ func (dst *Redis) ConvertFrom(srcRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // ReadinessProbe if src.Spec.ReadinessProbe != nil { + dst.Spec.ReadinessProbe = &Probe{} dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe } // LivenessProbe if src.Spec.LivenessProbe != nil { + dst.Spec.LivenessProbe = &Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars @@ -139,7 +159,6 @@ func (dst *Redis) ConvertFrom(srcRaw conversion.Hub) error { } dst.Spec.Sidecars = &sidecars } - // ServiceAccountName if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName diff --git a/api/v1beta1/rediscluster_conversion.go b/api/v1beta1/rediscluster_conversion.go index 3eeeb8984..c5e715b4a 100644 --- a/api/v1beta1/rediscluster_conversion.go +++ b/api/v1beta1/rediscluster_conversion.go @@ -5,7 +5,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/conversion" ) -// ConvertTo converts this RedisCluster to the Hub version (v1beta2). +// ConvertTo converts this RedisCluster to the Hub version (v1beta2) from the current version (v1beta1) + func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*redisv1beta2.RedisCluster) @@ -28,12 +29,15 @@ func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.RedisFollower.CommonAttributes = src.Spec.RedisFollower.CommonAttributes // RedisExporter if src.Spec.RedisExporter != nil { + dst.Spec.RedisExporter = &redisv1beta2.RedisExporter{} dst.Spec.RedisExporter.RedisExporter = src.Spec.RedisExporter.RedisExporter } - // Storage + // Storage-v1bet1 >> ClusterStorage-v1beta2 if src.Spec.Storage != nil { // Note : Add the Check the creation of node-conf later - dst.Spec.Storage.CommonAttributes = src.Spec.Storage.CommonAttributes + dst.Spec.Storage = &redisv1beta2.ClusterStorage{} + dst.Spec.Storage.VolumeClaimTemplate = src.Spec.Storage.VolumeClaimTemplate + dst.Spec.Storage.VolumeMount = src.Spec.Storage.VolumeMount } // SecurityContext >> PodSecurityContext if src.Spec.SecurityContext != nil { @@ -49,6 +53,7 @@ func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &redisv1beta2.TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // Sidecars @@ -61,7 +66,6 @@ func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { } dst.Spec.Sidecars = &sidecars } - // ServiceAccountName if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName @@ -70,7 +74,6 @@ func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { if src.Spec.PersistenceEnabled != nil { dst.Spec.PersistenceEnabled = src.Spec.PersistenceEnabled } - return nil } @@ -97,11 +100,14 @@ func (dst *RedisCluster) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.RedisFollower.CommonAttributes = src.Spec.RedisFollower.CommonAttributes // RedisExporter if src.Spec.RedisExporter != nil { + dst.Spec.RedisExporter = &RedisExporter{} dst.Spec.RedisExporter.RedisExporter = src.Spec.RedisExporter.RedisExporter } - // Storage + // ClusterStorage(v1beta2) >> Storage(v1beta1) if src.Spec.Storage != nil { - dst.Spec.Storage.CommonAttributes = src.Spec.Storage.CommonAttributes + dst.Spec.Storage = &Storage{} + dst.Spec.Storage.VolumeClaimTemplate = src.Spec.Storage.VolumeClaimTemplate + dst.Spec.Storage.VolumeMount = src.Spec.Storage.VolumeMount } // PodSecurityContext >> SecurityContext if src.Spec.PodSecurityContext != nil { @@ -117,6 +123,7 @@ func (dst *RedisCluster) ConvertFrom(srcRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // Sidecars @@ -129,7 +136,6 @@ func (dst *RedisCluster) ConvertFrom(srcRaw conversion.Hub) error { } dst.Spec.Sidecars = &sidecars } - // ServiceAccountName if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName diff --git a/api/v1beta1/redisreplication_conversion.go b/api/v1beta1/redisreplication_conversion.go index 9c3f1a0fb..5555dfc5a 100644 --- a/api/v1beta1/redisreplication_conversion.go +++ b/api/v1beta1/redisreplication_conversion.go @@ -18,15 +18,19 @@ func (src *RedisReplication) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.KubernetesConfig.KubernetesConfig = src.Spec.KubernetesConfig.KubernetesConfig // RedisExporter if src.Spec.RedisExporter != nil { + dst.Spec.RedisExporter = &redisv1beta2.RedisExporter{} dst.Spec.RedisExporter.RedisExporter = src.Spec.RedisExporter.RedisExporter } // RedisConfig if src.Spec.RedisConfig != nil { + dst.Spec.RedisConfig = &redisv1beta2.RedisConfig{} dst.Spec.RedisConfig.RedisConfig = src.Spec.RedisConfig.RedisConfig } // Storage if src.Spec.Storage != nil { - dst.Spec.Storage.CommonAttributes = src.Spec.Storage.CommonAttributes + dst.Spec.Storage = &redisv1beta2.Storage{} + dst.Spec.Storage.VolumeClaimTemplate = src.Spec.Storage.VolumeClaimTemplate + dst.Spec.Storage.VolumeMount = src.Spec.Storage.VolumeMount } // NodeSelector if src.Spec.NodeSelector != nil { @@ -50,18 +54,20 @@ func (src *RedisReplication) ConvertTo(dstRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &redisv1beta2.TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // ReadinessProbe if src.Spec.ReadinessProbe != nil { + dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe } // LivenessProbe if src.Spec.LivenessProbe != nil { + dst.Spec.LivenessProbe = &redisv1beta2.Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars - // Sidecars if src.Spec.Sidecars != nil { var sidecars []redisv1beta2.Sidecar for _, sidecar := range *src.Spec.Sidecars { @@ -75,7 +81,6 @@ func (src *RedisReplication) ConvertTo(dstRaw conversion.Hub) error { if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName } - return nil } @@ -92,15 +97,19 @@ func (dst *RedisReplication) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.KubernetesConfig.KubernetesConfig = src.Spec.KubernetesConfig.KubernetesConfig // RedisExporter if src.Spec.RedisExporter != nil { + dst.Spec.RedisExporter = &RedisExporter{} dst.Spec.RedisExporter.RedisExporter = src.Spec.RedisExporter.RedisExporter } // RedisConfig if src.Spec.RedisConfig != nil { + dst.Spec.RedisConfig = &RedisConfig{} dst.Spec.RedisConfig.RedisConfig = src.Spec.RedisConfig.RedisConfig } // Storage if src.Spec.Storage != nil { - dst.Spec.Storage.CommonAttributes = src.Spec.Storage.CommonAttributes + dst.Spec.Storage = &Storage{} + dst.Spec.Storage.VolumeClaimTemplate = src.Spec.Storage.VolumeClaimTemplate + dst.Spec.Storage.VolumeMount = src.Spec.Storage.VolumeMount } // NodeSelector if src.Spec.NodeSelector != nil { @@ -124,14 +133,17 @@ func (dst *RedisReplication) ConvertFrom(srcRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // ReadinessProbe if src.Spec.ReadinessProbe != nil { + dst.Spec.ReadinessProbe = &Probe{} dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe } // LivenessProbe if src.Spec.LivenessProbe != nil { + dst.Spec.ReadinessProbe = &Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars @@ -144,7 +156,6 @@ func (dst *RedisReplication) ConvertFrom(srcRaw conversion.Hub) error { } dst.Spec.Sidecars = &sidecars } - // ServiceAccountName if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName diff --git a/api/v1beta1/redissentinel_conversion.go b/api/v1beta1/redissentinel_conversion.go index b0926ff7f..479f76cad 100644 --- a/api/v1beta1/redissentinel_conversion.go +++ b/api/v1beta1/redissentinel_conversion.go @@ -18,6 +18,7 @@ func (src *RedisSentinel) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.KubernetesConfig.KubernetesConfig = src.Spec.KubernetesConfig.KubernetesConfig // RedisSentinelConfig if src.Spec.RedisSentinelConfig != nil { + dst.Spec.RedisSentinelConfig = &redisv1beta2.RedisSentinelConfig{} dst.Spec.RedisSentinelConfig.RedisSentinelConfig = src.Spec.RedisSentinelConfig.RedisSentinelConfig } // NodeSelector @@ -42,18 +43,20 @@ func (src *RedisSentinel) ConvertTo(dstRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &redisv1beta2.TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // ReadinessProbe if src.Spec.ReadinessProbe != nil { + dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe } // LivenessProbe if src.Spec.LivenessProbe != nil { + dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars - // Sidecars if src.Spec.Sidecars != nil { var sidecars []redisv1beta2.Sidecar for _, sidecar := range *src.Spec.Sidecars { @@ -63,12 +66,10 @@ func (src *RedisSentinel) ConvertTo(dstRaw conversion.Hub) error { } dst.Spec.Sidecars = &sidecars } - // ServiceAccountName if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName } - return nil } @@ -85,6 +86,7 @@ func (dst *RedisSentinel) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.KubernetesConfig.KubernetesConfig = src.Spec.KubernetesConfig.KubernetesConfig // RedisSentinelConfig if src.Spec.RedisSentinelConfig != nil { + dst.Spec.RedisSentinelConfig = &RedisSentinelConfig{} dst.Spec.RedisSentinelConfig.RedisSentinelConfig = src.Spec.RedisSentinelConfig.RedisSentinelConfig } // NodeSelector @@ -109,14 +111,17 @@ func (dst *RedisSentinel) ConvertFrom(srcRaw conversion.Hub) error { } // TLS if src.Spec.TLS != nil { + dst.Spec.TLS = &TLSConfig{} dst.Spec.TLS.TLSConfig = src.Spec.TLS.TLSConfig } // ReadinessProbe if src.Spec.ReadinessProbe != nil { + dst.Spec.ReadinessProbe = &Probe{} dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe } // LivenessProbe if src.Spec.LivenessProbe != nil { + dst.Spec.ReadinessProbe = &Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars @@ -129,7 +134,6 @@ func (dst *RedisSentinel) ConvertFrom(srcRaw conversion.Hub) error { } dst.Spec.Sidecars = &sidecars } - // ServiceAccountName if src.Spec.ServiceAccountName != nil { dst.Spec.ServiceAccountName = src.Spec.ServiceAccountName diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 319233b6c..60c4a668c 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -850,7 +850,7 @@ func (in *Sidecar) DeepCopy() *Sidecar { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Storage) DeepCopyInto(out *Storage) { *out = *in - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.Storage.DeepCopyInto(&out.Storage) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Storage. diff --git a/api/v1beta2/common_types.go b/api/v1beta2/common_types.go index bd65fdb2e..76a3adcd0 100644 --- a/api/v1beta2/common_types.go +++ b/api/v1beta2/common_types.go @@ -46,7 +46,7 @@ type ExistingPasswordSecret struct { // Storage is the inteface to add pvc and pv support in redis type Storage struct { - CommonAttributes common.Storage `json:",inline"` + common.Storage `json:",inline"` } // Node-conf needs to be added only in redis cluster @@ -54,7 +54,7 @@ type ClusterStorage struct { // +kubebuilder:default=false NodeConfVolume bool `json:"nodeConfVolume,omitempty"` NodeConfVolumeClaimTemplate corev1.PersistentVolumeClaim `json:"nodeConfVolumeClaimTemplate,omitempty"` - CommonAttributes common.Storage `json:",inline"` + common.Storage `json:",inline"` } // RedisExporter interface will have the information for redis exporter related stuff diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 26abd705b..df9897888 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -51,7 +51,7 @@ func (in *ACLConfig) DeepCopy() *ACLConfig { func (in *ClusterStorage) DeepCopyInto(out *ClusterStorage) { *out = *in in.NodeConfVolumeClaimTemplate.DeepCopyInto(&out.NodeConfVolumeClaimTemplate) - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.Storage.DeepCopyInto(&out.Storage) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterStorage. @@ -1048,7 +1048,7 @@ func (in *Sidecar) DeepCopy() *Sidecar { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Storage) DeepCopyInto(out *Storage) { *out = *in - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.Storage.DeepCopyInto(&out.Storage) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Storage. diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 8dbe71642..44a051c39 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -47,7 +47,7 @@ func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, e res.ImagePullSecrets = cr.Spec.KubernetesConfig.ImagePullSecrets } if cr.Spec.Storage != nil { - res.PersistentVolumeClaim = cr.Spec.Storage.CommonAttributes.VolumeClaimTemplate + res.PersistentVolumeClaim = cr.Spec.Storage.VolumeClaimTemplate res.NodeConfPersistentVolumeClaim = cr.Spec.Storage.NodeConfVolumeClaimTemplate } if externalConfig != nil { @@ -78,8 +78,8 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init } if cr.Spec.Storage != nil { - initcontainerProp.AdditionalVolume = cr.Spec.Storage.CommonAttributes.VolumeMount.Volume - initcontainerProp.AdditionalMountPath = cr.Spec.Storage.CommonAttributes.VolumeMount.MountPath + initcontainerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume + initcontainerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath } if cr.Spec.Storage != nil { initcontainerProp.PersistenceEnabled = &trueProperty @@ -102,8 +102,8 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security SecurityContext: securityContext, } if cr.Spec.Storage != nil { - containerProp.AdditionalVolume = cr.Spec.Storage.CommonAttributes.VolumeMount.Volume - containerProp.AdditionalMountPath = cr.Spec.Storage.CommonAttributes.VolumeMount.MountPath + containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume + containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { containerProp.EnabledPassword = &trueProperty diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 756a03464..4d8c4234f 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -81,7 +81,7 @@ func generateRedisReplicationParams(cr *redisv1beta2.RedisReplication) statefulS res.ImagePullSecrets = cr.Spec.KubernetesConfig.ImagePullSecrets } if cr.Spec.Storage != nil { - res.PersistentVolumeClaim = cr.Spec.Storage.CommonAttributes.VolumeClaimTemplate + res.PersistentVolumeClaim = cr.Spec.Storage.VolumeClaimTemplate } if cr.Spec.RedisConfig != nil { res.ExternalConfig = cr.Spec.RedisConfig.AdditionalRedisConfig @@ -111,8 +111,8 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) } if cr.Spec.Storage != nil { - containerProp.AdditionalVolume = cr.Spec.Storage.CommonAttributes.VolumeMount.Volume - containerProp.AdditionalMountPath = cr.Spec.Storage.CommonAttributes.VolumeMount.MountPath + containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume + containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -173,8 +173,8 @@ func generateRedisReplicationInitContainerParams(cr *redisv1beta2.RedisReplicati } if cr.Spec.Storage != nil { - initcontainerProp.AdditionalVolume = cr.Spec.Storage.CommonAttributes.VolumeMount.Volume - initcontainerProp.AdditionalMountPath = cr.Spec.Storage.CommonAttributes.VolumeMount.MountPath + initcontainerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume + initcontainerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath } if cr.Spec.Storage != nil { initcontainerProp.PersistenceEnabled = &trueProperty diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 80c96e536..71e3ea56e 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -85,7 +85,7 @@ func generateRedisStandaloneParams(cr *redisv1beta2.Redis) statefulSetParameters res.ImagePullSecrets = cr.Spec.KubernetesConfig.ImagePullSecrets } if cr.Spec.Storage != nil { - res.PersistentVolumeClaim = cr.Spec.Storage.CommonAttributes.VolumeClaimTemplate + res.PersistentVolumeClaim = cr.Spec.Storage.VolumeClaimTemplate } if cr.Spec.RedisConfig != nil { res.ExternalConfig = cr.Spec.RedisConfig.AdditionalRedisConfig @@ -116,8 +116,8 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar } if cr.Spec.Storage != nil { - containerProp.AdditionalVolume = cr.Spec.Storage.CommonAttributes.VolumeMount.Volume - containerProp.AdditionalMountPath = cr.Spec.Storage.CommonAttributes.VolumeMount.MountPath + containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume + containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -178,8 +178,8 @@ func generateRedisStandaloneInitContainerParams(cr *redisv1beta2.Redis) initCont } if cr.Spec.Storage != nil { - initcontainerProp.AdditionalVolume = cr.Spec.Storage.CommonAttributes.VolumeMount.Volume - initcontainerProp.AdditionalMountPath = cr.Spec.Storage.CommonAttributes.VolumeMount.MountPath + initcontainerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume + initcontainerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath } if cr.Spec.Storage != nil { initcontainerProp.PersistenceEnabled = &trueProperty From 857f81636f0c8c843ece18afbaf41fd23eb45a88 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:11:19 +0530 Subject: [PATCH 002/203] Split Example v1beta1 & v1beta2 (#616) Signed-off-by: Shubham Gupta --- .../v1beta1/additional_config/clusterd.yaml | 32 +++++++++ .../additional_config/configmap.yaml | 0 .../additional_config/replication.yaml | 2 +- .../additional_config/standalone.yaml | 2 +- example/v1beta1/advance_config/clusterd.yaml | 39 ++++++++++ .../v1beta1/advance_config/standalone.yaml | 35 +++++++++ example/v1beta1/affinity/clusterd.yaml | 50 +++++++++++++ .../{ => v1beta1}/affinity/replication.yaml | 2 +- .../{ => v1beta1}/affinity/standalone.yaml | 2 +- .../v1beta1/disruption_budget/clusterd.yaml | 58 +++++++++++++++ example/{ => v1beta1}/eks-cluster.yaml | 0 .../external_service/cluster-svc.yaml | 0 .../v1beta1/external_service/clusterd.yaml | 26 +++++++ .../external_service/replication-svc.yaml | 0 .../external_service/replication.yaml | 2 +- .../external_service/standalone-svc.yaml | 0 .../external_service/standalone.yaml | 2 +- example/v1beta1/node-selector/clusterd.yaml | 32 +++++++++ .../node-selector/replication.yaml | 2 +- .../node-selector/standalone.yaml | 2 +- .../v1beta1/password_protected/clusterd.yaml | 29 ++++++++ .../password_protected/replication.yaml | 2 +- .../password_protected/secret.yaml | 0 .../password_protected/standalone.yaml | 2 +- .../v1beta1/private_registry/clusterd.yaml | 28 ++++++++ .../private_registry/replication.yaml | 2 +- .../private_registry/standalone.yaml | 2 +- example/v1beta1/probes/clusterd.yaml | 51 +++++++++++++ example/{ => v1beta1}/probes/replication.yaml | 2 +- example/{ => v1beta1}/probes/standalone.yaml | 2 +- .../recreate-statefulset/clusterd.yaml | 29 ++++++++ .../recreate-statefulset/replication.yaml | 2 +- .../recreate-statefulset/standalone.yaml | 2 +- example/v1beta1/redis-cluster.yaml | 71 +++++++++++++++++++ example/v1beta1/redis-replication.yaml | 60 ++++++++++++++++ example/v1beta1/redis-sentinel.yaml | 22 ++++++ example/v1beta1/redis-standalone.yaml | 62 ++++++++++++++++ .../v1beta1/redis_monitoring/clusterd.yaml | 29 ++++++++ .../redis_monitoring/replication.yaml | 2 +- .../redis_monitoring/standalone.yaml | 2 +- .../redis_sentinel/sentinel.yaml | 2 +- .../v1beta1/tls_enabled/redis-cluster.yaml | 51 +++++++++++++ .../tls_enabled/redis-replication.yaml | 2 +- .../tls_enabled/redis-standalone.yaml | 2 +- example/v1beta1/tolerations/clusterd.yaml | 38 ++++++++++ .../{ => v1beta1}/tolerations/standalone.yaml | 2 +- .../v1beta1/upgrade-strategy/clusterd.yaml | 29 ++++++++ .../upgrade-strategy/standalone.yaml | 2 +- .../{ => v1beta1}/volume_mount/configmap.yaml | 0 .../v1beta1/volume_mount/redis-cluster.yaml | 53 ++++++++++++++ .../volume_mount/redis-replication.yaml | 0 .../volume_mount/redis-standalone.yaml | 0 .../{ => v1beta2}/acl_config/acl-secret.yaml | 0 example/{ => v1beta2}/acl_config/cluster.yaml | 2 +- .../{ => v1beta2}/acl_config/replication.yaml | 2 +- .../{ => v1beta2}/acl_config/standalone.yaml | 2 +- example/{ => v1beta2}/acl_config/user.acl | 0 .../additional_config/clusterd.yaml | 2 +- .../v1beta2/additional_config/configmap.yaml | 10 +++ .../additional_config/replication.yaml | 26 +++++++ .../v1beta2/additional_config/standalone.yaml | 25 +++++++ .../advance_config/clusterd.yaml | 2 +- .../advance_config/standalone.yaml | 2 +- example/{ => v1beta2}/affinity/clusterd.yaml | 2 +- example/v1beta2/affinity/replication.yaml | 34 +++++++++ example/v1beta2/affinity/standalone.yaml | 33 +++++++++ .../backup_restore/configmap.yaml | 0 .../backup_restore/env-secret.yaml | 0 .../backup_restore/redis-cluster.yaml | 2 +- .../disruption_budget/clusterd.yaml | 2 +- example/v1beta2/eks-cluster.yaml | 26 +++++++ .../v1beta2/external_service/cluster-svc.yaml | 44 ++++++++++++ .../external_service/clusterd.yaml | 2 +- .../external_service/replication-svc.yaml | 21 ++++++ .../v1beta2/external_service/replication.yaml | 24 +++++++ .../external_service/standalone-svc.yaml | 21 ++++++ .../v1beta2/external_service/standalone.yaml | 23 ++++++ .../{ => v1beta2}/node-selector/clusterd.yaml | 2 +- .../v1beta2/node-selector/replication.yaml | 26 +++++++ example/v1beta2/node-selector/standalone.yaml | 25 +++++++ .../password_protected/clusterd.yaml | 2 +- .../password_protected/replication.yaml | 27 +++++++ .../v1beta2/password_protected/secret.yaml | 8 +++ .../password_protected/standalone.yaml | 26 +++++++ .../private_registry/clusterd.yaml | 2 +- .../v1beta2/private_registry/replication.yaml | 26 +++++++ .../v1beta2/private_registry/standalone.yaml | 25 +++++++ example/{ => v1beta2}/probes/clusterd.yaml | 2 +- example/v1beta2/probes/replication.yaml | 36 ++++++++++ example/v1beta2/probes/standalone.yaml | 35 +++++++++ .../recreate-statefulset/clusterd.yaml | 2 +- .../recreate-statefulset/replication.yaml | 27 +++++++ .../recreate-statefulset/standalone.yaml | 26 +++++++ example/{ => v1beta2}/redis-cluster.yaml | 2 +- example/{ => v1beta2}/redis-replication.yaml | 2 +- example/{ => v1beta2}/redis-sentinel.yaml | 2 +- example/{ => v1beta2}/redis-standalone.yaml | 2 +- .../redis_monitoring/clusterd.yaml | 2 +- .../v1beta2/redis_monitoring/replication.yaml | 30 ++++++++ .../v1beta2/redis_monitoring/standalone.yaml | 29 ++++++++ example/v1beta2/redis_sentinel/sentinel.yaml | 22 ++++++ .../sidecar_features/configmap.yaml | 0 .../sidecar_features/sidecar.yaml | 2 +- .../tls_enabled/redis-cluster.yaml | 2 +- .../tls_enabled/redis-replication.yaml | 45 ++++++++++++ .../v1beta2/tls_enabled/redis-standalone.yaml | 44 ++++++++++++ .../{ => v1beta2}/tolerations/clusterd.yaml | 2 +- .../tolerations/replication.yaml | 2 +- example/v1beta2/tolerations/standalone.yaml | 28 ++++++++ .../upgrade-strategy/clusterd.yaml | 2 +- .../upgrade-strategy/replication.yaml | 2 +- .../v1beta2/upgrade-strategy/standalone.yaml | 26 +++++++ example/v1beta2/volume_mount/configmap.yaml | 8 +++ .../volume_mount/redis-cluster.yaml | 2 +- .../volume_mount/redis-replication.yaml | 50 +++++++++++++ .../volume_mount/redis-standalone.yaml | 49 +++++++++++++ 116 files changed, 1779 insertions(+), 50 deletions(-) create mode 100644 example/v1beta1/additional_config/clusterd.yaml rename example/{ => v1beta1}/additional_config/configmap.yaml (100%) rename example/{ => v1beta1}/additional_config/replication.yaml (96%) rename example/{ => v1beta1}/additional_config/standalone.yaml (96%) create mode 100644 example/v1beta1/advance_config/clusterd.yaml create mode 100644 example/v1beta1/advance_config/standalone.yaml create mode 100644 example/v1beta1/affinity/clusterd.yaml rename example/{ => v1beta1}/affinity/replication.yaml (97%) rename example/{ => v1beta1}/affinity/standalone.yaml (97%) create mode 100644 example/v1beta1/disruption_budget/clusterd.yaml rename example/{ => v1beta1}/eks-cluster.yaml (100%) rename example/{ => v1beta1}/external_service/cluster-svc.yaml (100%) create mode 100644 example/v1beta1/external_service/clusterd.yaml rename example/{ => v1beta1}/external_service/replication-svc.yaml (100%) rename example/{ => v1beta1}/external_service/replication.yaml (96%) rename example/{ => v1beta1}/external_service/standalone-svc.yaml (100%) rename example/{ => v1beta1}/external_service/standalone.yaml (95%) create mode 100644 example/v1beta1/node-selector/clusterd.yaml rename example/{ => v1beta1}/node-selector/replication.yaml (96%) rename example/{ => v1beta1}/node-selector/standalone.yaml (96%) create mode 100644 example/v1beta1/password_protected/clusterd.yaml rename example/{ => v1beta1}/password_protected/replication.yaml (96%) rename example/{ => v1beta1}/password_protected/secret.yaml (100%) rename example/{ => v1beta1}/password_protected/standalone.yaml (96%) create mode 100644 example/v1beta1/private_registry/clusterd.yaml rename example/{ => v1beta1}/private_registry/replication.yaml (96%) rename example/{ => v1beta1}/private_registry/standalone.yaml (96%) create mode 100644 example/v1beta1/probes/clusterd.yaml rename example/{ => v1beta1}/probes/replication.yaml (97%) rename example/{ => v1beta1}/probes/standalone.yaml (97%) create mode 100644 example/v1beta1/recreate-statefulset/clusterd.yaml rename example/{ => v1beta1}/recreate-statefulset/replication.yaml (96%) rename example/{ => v1beta1}/recreate-statefulset/standalone.yaml (96%) create mode 100644 example/v1beta1/redis-cluster.yaml create mode 100644 example/v1beta1/redis-replication.yaml create mode 100644 example/v1beta1/redis-sentinel.yaml create mode 100644 example/v1beta1/redis-standalone.yaml create mode 100644 example/v1beta1/redis_monitoring/clusterd.yaml rename example/{ => v1beta1}/redis_monitoring/replication.yaml (97%) rename example/{ => v1beta1}/redis_monitoring/standalone.yaml (96%) rename example/{ => v1beta1}/redis_sentinel/sentinel.yaml (95%) create mode 100644 example/v1beta1/tls_enabled/redis-cluster.yaml rename example/{ => v1beta1}/tls_enabled/redis-replication.yaml (97%) rename example/{ => v1beta1}/tls_enabled/redis-standalone.yaml (97%) create mode 100644 example/v1beta1/tolerations/clusterd.yaml rename example/{ => v1beta1}/tolerations/standalone.yaml (96%) create mode 100644 example/v1beta1/upgrade-strategy/clusterd.yaml rename example/{ => v1beta1}/upgrade-strategy/standalone.yaml (96%) rename example/{ => v1beta1}/volume_mount/configmap.yaml (100%) create mode 100644 example/v1beta1/volume_mount/redis-cluster.yaml rename example/{ => v1beta1}/volume_mount/redis-replication.yaml (100%) rename example/{ => v1beta1}/volume_mount/redis-standalone.yaml (100%) rename example/{ => v1beta2}/acl_config/acl-secret.yaml (100%) rename example/{ => v1beta2}/acl_config/cluster.yaml (96%) rename example/{ => v1beta2}/acl_config/replication.yaml (95%) rename example/{ => v1beta2}/acl_config/standalone.yaml (95%) rename example/{ => v1beta2}/acl_config/user.acl (100%) rename example/{ => v1beta2}/additional_config/clusterd.yaml (94%) create mode 100644 example/v1beta2/additional_config/configmap.yaml create mode 100644 example/v1beta2/additional_config/replication.yaml create mode 100644 example/v1beta2/additional_config/standalone.yaml rename example/{ => v1beta2}/advance_config/clusterd.yaml (95%) rename example/{ => v1beta2}/advance_config/standalone.yaml (93%) rename example/{ => v1beta2}/affinity/clusterd.yaml (96%) create mode 100644 example/v1beta2/affinity/replication.yaml create mode 100644 example/v1beta2/affinity/standalone.yaml rename example/{ => v1beta2}/backup_restore/configmap.yaml (100%) rename example/{ => v1beta2}/backup_restore/env-secret.yaml (100%) rename example/{ => v1beta2}/backup_restore/redis-cluster.yaml (98%) rename example/{ => v1beta2}/disruption_budget/clusterd.yaml (97%) create mode 100644 example/v1beta2/eks-cluster.yaml create mode 100644 example/v1beta2/external_service/cluster-svc.yaml rename example/{ => v1beta2}/external_service/clusterd.yaml (93%) create mode 100644 example/v1beta2/external_service/replication-svc.yaml create mode 100644 example/v1beta2/external_service/replication.yaml create mode 100644 example/v1beta2/external_service/standalone-svc.yaml create mode 100644 example/v1beta2/external_service/standalone.yaml rename example/{ => v1beta2}/node-selector/clusterd.yaml (94%) create mode 100644 example/v1beta2/node-selector/replication.yaml create mode 100644 example/v1beta2/node-selector/standalone.yaml rename example/{ => v1beta2}/password_protected/clusterd.yaml (94%) create mode 100644 example/v1beta2/password_protected/replication.yaml create mode 100644 example/v1beta2/password_protected/secret.yaml create mode 100644 example/v1beta2/password_protected/standalone.yaml rename example/{ => v1beta2}/private_registry/clusterd.yaml (94%) create mode 100644 example/v1beta2/private_registry/replication.yaml create mode 100644 example/v1beta2/private_registry/standalone.yaml rename example/{ => v1beta2}/probes/clusterd.yaml (96%) create mode 100644 example/v1beta2/probes/replication.yaml create mode 100644 example/v1beta2/probes/standalone.yaml rename example/{ => v1beta2}/recreate-statefulset/clusterd.yaml (94%) create mode 100644 example/v1beta2/recreate-statefulset/replication.yaml create mode 100644 example/v1beta2/recreate-statefulset/standalone.yaml rename example/{ => v1beta2}/redis-cluster.yaml (97%) rename example/{ => v1beta2}/redis-replication.yaml (96%) rename example/{ => v1beta2}/redis-sentinel.yaml (91%) rename example/{ => v1beta2}/redis-standalone.yaml (96%) rename example/{ => v1beta2}/redis_monitoring/clusterd.yaml (94%) create mode 100644 example/v1beta2/redis_monitoring/replication.yaml create mode 100644 example/v1beta2/redis_monitoring/standalone.yaml create mode 100644 example/v1beta2/redis_sentinel/sentinel.yaml rename example/{ => v1beta2}/sidecar_features/configmap.yaml (100%) rename example/{ => v1beta2}/sidecar_features/sidecar.yaml (96%) rename example/{ => v1beta2}/tls_enabled/redis-cluster.yaml (96%) create mode 100644 example/v1beta2/tls_enabled/redis-replication.yaml create mode 100644 example/v1beta2/tls_enabled/redis-standalone.yaml rename example/{ => v1beta2}/tolerations/clusterd.yaml (95%) rename example/{ => v1beta2}/tolerations/replication.yaml (92%) create mode 100644 example/v1beta2/tolerations/standalone.yaml rename example/{ => v1beta2}/upgrade-strategy/clusterd.yaml (94%) rename example/{ => v1beta2}/upgrade-strategy/replication.yaml (92%) create mode 100644 example/v1beta2/upgrade-strategy/standalone.yaml create mode 100644 example/v1beta2/volume_mount/configmap.yaml rename example/{ => v1beta2}/volume_mount/redis-cluster.yaml (96%) create mode 100644 example/v1beta2/volume_mount/redis-replication.yaml create mode 100644 example/v1beta2/volume_mount/redis-standalone.yaml diff --git a/example/v1beta1/additional_config/clusterd.yaml b/example/v1beta1/additional_config/clusterd.yaml new file mode 100644 index 000000000..a546cc114 --- /dev/null +++ b/example/v1beta1/additional_config/clusterd.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + redisLeader: + redisConfig: + additionalRedisConfig: redis-external-config + redisFollower: + redisConfig: + additionalRedisConfig: redis-external-config + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/additional_config/configmap.yaml b/example/v1beta1/additional_config/configmap.yaml similarity index 100% rename from example/additional_config/configmap.yaml rename to example/v1beta1/additional_config/configmap.yaml diff --git a/example/additional_config/replication.yaml b/example/v1beta1/additional_config/replication.yaml similarity index 96% rename from example/additional_config/replication.yaml rename to example/v1beta1/additional_config/replication.yaml index 4e243da19..5bfd37d9d 100644 --- a/example/additional_config/replication.yaml +++ b/example/v1beta1/additional_config/replication.yaml @@ -10,7 +10,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/additional_config/standalone.yaml b/example/v1beta1/additional_config/standalone.yaml similarity index 96% rename from example/additional_config/standalone.yaml rename to example/v1beta1/additional_config/standalone.yaml index a6055b940..94ea81831 100644 --- a/example/additional_config/standalone.yaml +++ b/example/v1beta1/additional_config/standalone.yaml @@ -9,7 +9,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/v1beta1/advance_config/clusterd.yaml b/example/v1beta1/advance_config/clusterd.yaml new file mode 100644 index 000000000..305a13c19 --- /dev/null +++ b/example/v1beta1/advance_config/clusterd.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + imagePullSecrets: + - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # nodeSelector: {} + # securityContext: {} + # priorityClassName: "" + # affinity: {} + # Tolerations: [] diff --git a/example/v1beta1/advance_config/standalone.yaml b/example/v1beta1/advance_config/standalone.yaml new file mode 100644 index 000000000..e76625154 --- /dev/null +++ b/example/v1beta1/advance_config/standalone.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + securityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + # nodeSelector: {} + # securityContext: {} + # priorityClassName: "" + # affinity: {} + # Tolerations: [] diff --git a/example/v1beta1/affinity/clusterd.yaml b/example/v1beta1/affinity/clusterd.yaml new file mode 100644 index 000000000..535a98fde --- /dev/null +++ b/example/v1beta1/affinity/clusterd.yaml @@ -0,0 +1,50 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + redisLeader: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - redis-cluster-leader + - redis-cluster-follower + topologyKey: "kubernetes.io/hostname" + redisFollower: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - redis-cluster-follower + - redis-cluster-leader + topologyKey: "kubernetes.io/hostname" + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/affinity/replication.yaml b/example/v1beta1/affinity/replication.yaml similarity index 97% rename from example/affinity/replication.yaml rename to example/v1beta1/affinity/replication.yaml index 5ec87a954..7efc207ed 100644 --- a/example/affinity/replication.yaml +++ b/example/v1beta1/affinity/replication.yaml @@ -8,7 +8,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/affinity/standalone.yaml b/example/v1beta1/affinity/standalone.yaml similarity index 97% rename from example/affinity/standalone.yaml rename to example/v1beta1/affinity/standalone.yaml index 8a0278b5d..e5703a51c 100644 --- a/example/affinity/standalone.yaml +++ b/example/v1beta1/affinity/standalone.yaml @@ -7,7 +7,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/v1beta1/disruption_budget/clusterd.yaml b/example/v1beta1/disruption_budget/clusterd.yaml new file mode 100644 index 000000000..2059162ad --- /dev/null +++ b/example/v1beta1/disruption_budget/clusterd.yaml @@ -0,0 +1,58 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: "quay.io/opstree/redis-exporter:v1.44.0" + redisFollower: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - + labelSelector: + matchExpressions: + - + key: app + operator: In + values: + - redis-cluster-follower + topologyKey: kubernetes.io/hostname + pdb: + enabled: true + minAvailable: 1 + redisLeader: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - + labelSelector: + matchExpressions: + - + key: app + operator: In + values: + - redis-cluster-leader + topologyKey: kubernetes.io/hostname + pdb: + enabled: true + minAvailable: 1 + storage: + volumeClaimTemplate: + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/example/eks-cluster.yaml b/example/v1beta1/eks-cluster.yaml similarity index 100% rename from example/eks-cluster.yaml rename to example/v1beta1/eks-cluster.yaml diff --git a/example/external_service/cluster-svc.yaml b/example/v1beta1/external_service/cluster-svc.yaml similarity index 100% rename from example/external_service/cluster-svc.yaml rename to example/v1beta1/external_service/cluster-svc.yaml diff --git a/example/v1beta1/external_service/clusterd.yaml b/example/v1beta1/external_service/clusterd.yaml new file mode 100644 index 000000000..26b89a8fb --- /dev/null +++ b/example/v1beta1/external_service/clusterd.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/external_service/replication-svc.yaml b/example/v1beta1/external_service/replication-svc.yaml similarity index 100% rename from example/external_service/replication-svc.yaml rename to example/v1beta1/external_service/replication-svc.yaml diff --git a/example/external_service/replication.yaml b/example/v1beta1/external_service/replication.yaml similarity index 96% rename from example/external_service/replication.yaml rename to example/v1beta1/external_service/replication.yaml index 4c806ca73..4f84f2467 100644 --- a/example/external_service/replication.yaml +++ b/example/v1beta1/external_service/replication.yaml @@ -8,7 +8,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/external_service/standalone-svc.yaml b/example/v1beta1/external_service/standalone-svc.yaml similarity index 100% rename from example/external_service/standalone-svc.yaml rename to example/v1beta1/external_service/standalone-svc.yaml diff --git a/example/external_service/standalone.yaml b/example/v1beta1/external_service/standalone.yaml similarity index 95% rename from example/external_service/standalone.yaml rename to example/v1beta1/external_service/standalone.yaml index fb93de629..bfc4ff974 100644 --- a/example/external_service/standalone.yaml +++ b/example/v1beta1/external_service/standalone.yaml @@ -7,7 +7,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/v1beta1/node-selector/clusterd.yaml b/example/v1beta1/node-selector/clusterd.yaml new file mode 100644 index 000000000..df8520ca8 --- /dev/null +++ b/example/v1beta1/node-selector/clusterd.yaml @@ -0,0 +1,32 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + redisLeader: + nodeSelector: + kubernetes.io/os: linux + redisFollower: + nodeSelector: + kubernetes.io/os: linux + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/node-selector/replication.yaml b/example/v1beta1/node-selector/replication.yaml similarity index 96% rename from example/node-selector/replication.yaml rename to example/v1beta1/node-selector/replication.yaml index a1dbd5002..991de4243 100644 --- a/example/node-selector/replication.yaml +++ b/example/v1beta1/node-selector/replication.yaml @@ -8,7 +8,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/node-selector/standalone.yaml b/example/v1beta1/node-selector/standalone.yaml similarity index 96% rename from example/node-selector/standalone.yaml rename to example/v1beta1/node-selector/standalone.yaml index 6837c955c..72596236b 100644 --- a/example/node-selector/standalone.yaml +++ b/example/v1beta1/node-selector/standalone.yaml @@ -7,7 +7,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/v1beta1/password_protected/clusterd.yaml b/example/v1beta1/password_protected/clusterd.yaml new file mode 100644 index 000000000..a978fdfe8 --- /dev/null +++ b/example/v1beta1/password_protected/clusterd.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisSecret: + name: redis-secret + key: password + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/password_protected/replication.yaml b/example/v1beta1/password_protected/replication.yaml similarity index 96% rename from example/password_protected/replication.yaml rename to example/v1beta1/password_protected/replication.yaml index f925b36e7..ef3311d61 100644 --- a/example/password_protected/replication.yaml +++ b/example/v1beta1/password_protected/replication.yaml @@ -22,6 +22,6 @@ spec: redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 diff --git a/example/password_protected/secret.yaml b/example/v1beta1/password_protected/secret.yaml similarity index 100% rename from example/password_protected/secret.yaml rename to example/v1beta1/password_protected/secret.yaml diff --git a/example/password_protected/standalone.yaml b/example/v1beta1/password_protected/standalone.yaml similarity index 96% rename from example/password_protected/standalone.yaml rename to example/v1beta1/password_protected/standalone.yaml index e0da3beb4..8be97ea57 100644 --- a/example/password_protected/standalone.yaml +++ b/example/v1beta1/password_protected/standalone.yaml @@ -21,6 +21,6 @@ spec: redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 diff --git a/example/v1beta1/private_registry/clusterd.yaml b/example/v1beta1/private_registry/clusterd.yaml new file mode 100644 index 000000000..3e41c0caa --- /dev/null +++ b/example/v1beta1/private_registry/clusterd.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/private_registry/replication.yaml b/example/v1beta1/private_registry/replication.yaml similarity index 96% rename from example/private_registry/replication.yaml rename to example/v1beta1/private_registry/replication.yaml index 4d14e3254..c33ca9d1a 100644 --- a/example/private_registry/replication.yaml +++ b/example/v1beta1/private_registry/replication.yaml @@ -21,6 +21,6 @@ spec: redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 diff --git a/example/private_registry/standalone.yaml b/example/v1beta1/private_registry/standalone.yaml similarity index 96% rename from example/private_registry/standalone.yaml rename to example/v1beta1/private_registry/standalone.yaml index 3b83130fa..dc1d640b6 100644 --- a/example/private_registry/standalone.yaml +++ b/example/v1beta1/private_registry/standalone.yaml @@ -20,6 +20,6 @@ spec: redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 diff --git a/example/v1beta1/probes/clusterd.yaml b/example/v1beta1/probes/clusterd.yaml new file mode 100644 index 000000000..9c2992d88 --- /dev/null +++ b/example/v1beta1/probes/clusterd.yaml @@ -0,0 +1,51 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + redisLeader: + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 + livenessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 + redisFollower: + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 + livenessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/probes/replication.yaml b/example/v1beta1/probes/replication.yaml similarity index 97% rename from example/probes/replication.yaml rename to example/v1beta1/probes/replication.yaml index cda33b96b..02513b28c 100644 --- a/example/probes/replication.yaml +++ b/example/v1beta1/probes/replication.yaml @@ -5,7 +5,7 @@ metadata: name: redis-replication spec: clusterSize: 3 - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: diff --git a/example/probes/standalone.yaml b/example/v1beta1/probes/standalone.yaml similarity index 97% rename from example/probes/standalone.yaml rename to example/v1beta1/probes/standalone.yaml index af5d5fc93..70797aced 100644 --- a/example/probes/standalone.yaml +++ b/example/v1beta1/probes/standalone.yaml @@ -4,7 +4,7 @@ kind: Redis metadata: name: redis-standalone spec: - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: diff --git a/example/v1beta1/recreate-statefulset/clusterd.yaml b/example/v1beta1/recreate-statefulset/clusterd.yaml new file mode 100644 index 000000000..f944f8b2c --- /dev/null +++ b/example/v1beta1/recreate-statefulset/clusterd.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster + annotations: + redis.opstreelabs.in/recreate-statefulset: "true" +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + priorityClassName: priority-100 diff --git a/example/recreate-statefulset/replication.yaml b/example/v1beta1/recreate-statefulset/replication.yaml similarity index 96% rename from example/recreate-statefulset/replication.yaml rename to example/v1beta1/recreate-statefulset/replication.yaml index 08fc3406a..bdeb9db87 100644 --- a/example/recreate-statefulset/replication.yaml +++ b/example/v1beta1/recreate-statefulset/replication.yaml @@ -10,7 +10,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/recreate-statefulset/standalone.yaml b/example/v1beta1/recreate-statefulset/standalone.yaml similarity index 96% rename from example/recreate-statefulset/standalone.yaml rename to example/v1beta1/recreate-statefulset/standalone.yaml index 5d9fb97f5..03b62796f 100644 --- a/example/recreate-statefulset/standalone.yaml +++ b/example/v1beta1/recreate-statefulset/standalone.yaml @@ -9,7 +9,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/v1beta1/redis-cluster.yaml b/example/v1beta1/redis-cluster.yaml new file mode 100644 index 000000000..148c4f74b --- /dev/null +++ b/example/v1beta1/redis-cluster.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + securityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi +# Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username +# redisLeader: +# redisConfig: +# additionalRedisConfig: redis-external-config +# redisFollower: +# redisConfig: +# additionalRedisConfig: redis-external-config + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # nodeSelector: + # kubernetes.io/hostname: minikube + # priorityClassName: + # Affinity: + # Tolerations: [] diff --git a/example/v1beta1/redis-replication.yaml b/example/v1beta1/redis-replication.yaml new file mode 100644 index 000000000..5170612f9 --- /dev/null +++ b/example/v1beta1/redis-replication.yaml @@ -0,0 +1,60 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + # redisConfig: + # additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi +# Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/example/v1beta1/redis-sentinel.yaml b/example/v1beta1/redis-sentinel.yaml new file mode 100644 index 000000000..4eec84b51 --- /dev/null +++ b/example/v1beta1/redis-sentinel.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 3 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:v7.0.7 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi diff --git a/example/v1beta1/redis-standalone.yaml b/example/v1beta1/redis-standalone.yaml new file mode 100644 index 000000000..00340ed64 --- /dev/null +++ b/example/v1beta1/redis-standalone.yaml @@ -0,0 +1,62 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: Redis +metadata: + name: redis-standalone +spec: + # redisConfig: + # additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi +# Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # nodeSelector: + # kubernetes.io/hostname: minikube + # securityContext: {} + # priorityClassName: + # affinity: + # Tolerations: [] diff --git a/example/v1beta1/redis_monitoring/clusterd.yaml b/example/v1beta1/redis_monitoring/clusterd.yaml new file mode 100644 index 000000000..119d86ef2 --- /dev/null +++ b/example/v1beta1/redis_monitoring/clusterd.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +# annotations: +# rediscluster.opstreelabs.in/skip-reconcile: "true" +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: Always + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # storageClassName: standard diff --git a/example/redis_monitoring/replication.yaml b/example/v1beta1/redis_monitoring/replication.yaml similarity index 97% rename from example/redis_monitoring/replication.yaml rename to example/v1beta1/redis_monitoring/replication.yaml index a2a22ce2d..bf3602ae2 100644 --- a/example/redis_monitoring/replication.yaml +++ b/example/v1beta1/redis_monitoring/replication.yaml @@ -25,6 +25,6 @@ spec: # env: # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS # value: "true" - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 diff --git a/example/redis_monitoring/standalone.yaml b/example/v1beta1/redis_monitoring/standalone.yaml similarity index 96% rename from example/redis_monitoring/standalone.yaml rename to example/v1beta1/redis_monitoring/standalone.yaml index 4484970f9..500010068 100644 --- a/example/redis_monitoring/standalone.yaml +++ b/example/v1beta1/redis_monitoring/standalone.yaml @@ -24,6 +24,6 @@ spec: # env: # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS # value: "true" - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 diff --git a/example/redis_sentinel/sentinel.yaml b/example/v1beta1/redis_sentinel/sentinel.yaml similarity index 95% rename from example/redis_sentinel/sentinel.yaml rename to example/v1beta1/redis_sentinel/sentinel.yaml index 4e790b4e2..4eec84b51 100644 --- a/example/redis_sentinel/sentinel.yaml +++ b/example/v1beta1/redis_sentinel/sentinel.yaml @@ -5,7 +5,7 @@ metadata: name: redis-sentinel spec: clusterSize: 3 - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 redisSentinelConfig: diff --git a/example/v1beta1/tls_enabled/redis-cluster.yaml b/example/v1beta1/tls_enabled/redis-cluster.yaml new file mode 100644 index 000000000..2bda3bf2a --- /dev/null +++ b/example/v1beta1/tls_enabled/redis-cluster.yaml @@ -0,0 +1,51 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + clusterVersion: v7 + persistenceEnabled: true + securityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/tls_enabled/redis-replication.yaml b/example/v1beta1/tls_enabled/redis-replication.yaml similarity index 97% rename from example/tls_enabled/redis-replication.yaml rename to example/v1beta1/tls_enabled/redis-replication.yaml index ad722400d..ac8b34490 100644 --- a/example/tls_enabled/redis-replication.yaml +++ b/example/v1beta1/tls_enabled/redis-replication.yaml @@ -12,7 +12,7 @@ spec: key: tls.key secret: secretName: redis-tls-cert - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: diff --git a/example/tls_enabled/redis-standalone.yaml b/example/v1beta1/tls_enabled/redis-standalone.yaml similarity index 97% rename from example/tls_enabled/redis-standalone.yaml rename to example/v1beta1/tls_enabled/redis-standalone.yaml index 3fea31c00..3e254fd65 100644 --- a/example/tls_enabled/redis-standalone.yaml +++ b/example/v1beta1/tls_enabled/redis-standalone.yaml @@ -11,7 +11,7 @@ spec: key: tls.key secret: secretName: redis-tls-cert - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: diff --git a/example/v1beta1/tolerations/clusterd.yaml b/example/v1beta1/tolerations/clusterd.yaml new file mode 100644 index 000000000..77fe6a068 --- /dev/null +++ b/example/v1beta1/tolerations/clusterd.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + redisLeader: + tolerations: + - key: "key1" + operator: "Equal" + value: "value1" + effect: "NoSchedule" + redisFollower: + tolerations: + - key: "key1" + operator: "Equal" + value: "value1" + effect: "NoSchedule" + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/tolerations/standalone.yaml b/example/v1beta1/tolerations/standalone.yaml similarity index 96% rename from example/tolerations/standalone.yaml rename to example/v1beta1/tolerations/standalone.yaml index 3f6362182..378409fa9 100644 --- a/example/tolerations/standalone.yaml +++ b/example/v1beta1/tolerations/standalone.yaml @@ -7,7 +7,7 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/v1beta1/upgrade-strategy/clusterd.yaml b/example/v1beta1/upgrade-strategy/clusterd.yaml new file mode 100644 index 000000000..32e7cd7f0 --- /dev/null +++ b/example/v1beta1/upgrade-strategy/clusterd.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + securityContext: + runAsUser: 1000 + fsGroup: 1000 + persistenceEnabled: true + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + updateStrategy: + type: OnDelete + # type: RollingUpdate + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/upgrade-strategy/standalone.yaml b/example/v1beta1/upgrade-strategy/standalone.yaml similarity index 96% rename from example/upgrade-strategy/standalone.yaml rename to example/v1beta1/upgrade-strategy/standalone.yaml index 9038464cc..bfc1b445e 100644 --- a/example/upgrade-strategy/standalone.yaml +++ b/example/v1beta1/upgrade-strategy/standalone.yaml @@ -10,7 +10,7 @@ spec: updateStrategy: type: OnDelete # type: RollingUpdate - podSecurityContext: + securityContext: runAsUser: 1000 fsGroup: 1000 storage: diff --git a/example/volume_mount/configmap.yaml b/example/v1beta1/volume_mount/configmap.yaml similarity index 100% rename from example/volume_mount/configmap.yaml rename to example/v1beta1/volume_mount/configmap.yaml diff --git a/example/v1beta1/volume_mount/redis-cluster.yaml b/example/v1beta1/volume_mount/redis-cluster.yaml new file mode 100644 index 000000000..1b74ee260 --- /dev/null +++ b/example/v1beta1/volume_mount/redis-cluster.yaml @@ -0,0 +1,53 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + securityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumemount: + volume: + - name: example-config + configMap: + name: example-configmap + mount: + - mountPath: /config + name: example-config \ No newline at end of file diff --git a/example/volume_mount/redis-replication.yaml b/example/v1beta1/volume_mount/redis-replication.yaml similarity index 100% rename from example/volume_mount/redis-replication.yaml rename to example/v1beta1/volume_mount/redis-replication.yaml diff --git a/example/volume_mount/redis-standalone.yaml b/example/v1beta1/volume_mount/redis-standalone.yaml similarity index 100% rename from example/volume_mount/redis-standalone.yaml rename to example/v1beta1/volume_mount/redis-standalone.yaml diff --git a/example/acl_config/acl-secret.yaml b/example/v1beta2/acl_config/acl-secret.yaml similarity index 100% rename from example/acl_config/acl-secret.yaml rename to example/v1beta2/acl_config/acl-secret.yaml diff --git a/example/acl_config/cluster.yaml b/example/v1beta2/acl_config/cluster.yaml similarity index 96% rename from example/acl_config/cluster.yaml rename to example/v1beta2/acl_config/cluster.yaml index 5f025c9ae..70671263f 100644 --- a/example/acl_config/cluster.yaml +++ b/example/v1beta2/acl_config/cluster.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/acl_config/replication.yaml b/example/v1beta2/acl_config/replication.yaml similarity index 95% rename from example/acl_config/replication.yaml rename to example/v1beta2/acl_config/replication.yaml index c30998e1a..fbc8d0ccc 100644 --- a/example/acl_config/replication.yaml +++ b/example/v1beta2/acl_config/replication.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: name: redis-replication diff --git a/example/acl_config/standalone.yaml b/example/v1beta2/acl_config/standalone.yaml similarity index 95% rename from example/acl_config/standalone.yaml rename to example/v1beta2/acl_config/standalone.yaml index a711260cd..f586f9727 100644 --- a/example/acl_config/standalone.yaml +++ b/example/v1beta2/acl_config/standalone.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: name: redis-standalone diff --git a/example/acl_config/user.acl b/example/v1beta2/acl_config/user.acl similarity index 100% rename from example/acl_config/user.acl rename to example/v1beta2/acl_config/user.acl diff --git a/example/additional_config/clusterd.yaml b/example/v1beta2/additional_config/clusterd.yaml similarity index 94% rename from example/additional_config/clusterd.yaml rename to example/v1beta2/additional_config/clusterd.yaml index a02e2c6a4..fa1f21078 100644 --- a/example/additional_config/clusterd.yaml +++ b/example/v1beta2/additional_config/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/additional_config/configmap.yaml b/example/v1beta2/additional_config/configmap.yaml new file mode 100644 index 000000000..f68ea80ac --- /dev/null +++ b/example/v1beta2/additional_config/configmap.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: redis-external-config +data: + redis-additional.conf: | + tcp-keepalive 400 + slowlog-max-len 158 + stream-node-max-bytes 2048 diff --git a/example/v1beta2/additional_config/replication.yaml b/example/v1beta2/additional_config/replication.yaml new file mode 100644 index 000000000..1f1aad416 --- /dev/null +++ b/example/v1beta2/additional_config/replication.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + redisConfig: + additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta2/additional_config/standalone.yaml b/example/v1beta2/additional_config/standalone.yaml new file mode 100644 index 000000000..2a1cacb70 --- /dev/null +++ b/example/v1beta2/additional_config/standalone.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + redisConfig: + additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/advance_config/clusterd.yaml b/example/v1beta2/advance_config/clusterd.yaml similarity index 95% rename from example/advance_config/clusterd.yaml rename to example/v1beta2/advance_config/clusterd.yaml index 0bd59383a..8390e5589 100644 --- a/example/advance_config/clusterd.yaml +++ b/example/v1beta2/advance_config/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/advance_config/standalone.yaml b/example/v1beta2/advance_config/standalone.yaml similarity index 93% rename from example/advance_config/standalone.yaml rename to example/v1beta2/advance_config/standalone.yaml index 3d4fb7b93..88fb2ec4a 100644 --- a/example/advance_config/standalone.yaml +++ b/example/v1beta2/advance_config/standalone.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: name: redis-standalone diff --git a/example/affinity/clusterd.yaml b/example/v1beta2/affinity/clusterd.yaml similarity index 96% rename from example/affinity/clusterd.yaml rename to example/v1beta2/affinity/clusterd.yaml index 6b9bdd541..d1c555efe 100644 --- a/example/affinity/clusterd.yaml +++ b/example/v1beta2/affinity/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/affinity/replication.yaml b/example/v1beta2/affinity/replication.yaml new file mode 100644 index 000000000..82da8e355 --- /dev/null +++ b/example/v1beta2/affinity/replication.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - redis-replication + topologyKey: "kubernetes.io/hostname" diff --git a/example/v1beta2/affinity/standalone.yaml b/example/v1beta2/affinity/standalone.yaml new file mode 100644 index 000000000..22b6c39a5 --- /dev/null +++ b/example/v1beta2/affinity/standalone.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - redis-standalone + topologyKey: "kubernetes.io/hostname" diff --git a/example/backup_restore/configmap.yaml b/example/v1beta2/backup_restore/configmap.yaml similarity index 100% rename from example/backup_restore/configmap.yaml rename to example/v1beta2/backup_restore/configmap.yaml diff --git a/example/backup_restore/env-secret.yaml b/example/v1beta2/backup_restore/env-secret.yaml similarity index 100% rename from example/backup_restore/env-secret.yaml rename to example/v1beta2/backup_restore/env-secret.yaml diff --git a/example/backup_restore/redis-cluster.yaml b/example/v1beta2/backup_restore/redis-cluster.yaml similarity index 98% rename from example/backup_restore/redis-cluster.yaml rename to example/v1beta2/backup_restore/redis-cluster.yaml index 150b041d2..8744c451f 100644 --- a/example/backup_restore/redis-cluster.yaml +++ b/example/v1beta2/backup_restore/redis-cluster.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/disruption_budget/clusterd.yaml b/example/v1beta2/disruption_budget/clusterd.yaml similarity index 97% rename from example/disruption_budget/clusterd.yaml rename to example/v1beta2/disruption_budget/clusterd.yaml index f1de2aeab..d58ba0db2 100644 --- a/example/disruption_budget/clusterd.yaml +++ b/example/v1beta2/disruption_budget/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/eks-cluster.yaml b/example/v1beta2/eks-cluster.yaml new file mode 100644 index 000000000..4474537e3 --- /dev/null +++ b/example/v1beta2/eks-cluster.yaml @@ -0,0 +1,26 @@ +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig +metadata: + name: operator-testing + region: us-west-2 + version: "1.22" +managedNodeGroups: + - name: ng-1 + instanceType: t3a.medium + desiredCapacity: 3 + volumeSize: 30 + ssh: + allow: true + volumeType: gp3 +kubernetesNetworkConfig: + ipFamily: IPv4 +# ipFamily: IPv6 +addons: + - name: vpc-cni + - name: coredns + - name: kube-proxy + - name: aws-ebs-csi-driver + attachPolicyARNs: + - arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy +iam: + withOIDC: true diff --git a/example/v1beta2/external_service/cluster-svc.yaml b/example/v1beta2/external_service/cluster-svc.yaml new file mode 100644 index 000000000..8e68ca75f --- /dev/null +++ b/example/v1beta2/external_service/cluster-svc.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-leaders +spec: + clusterIP: 10.102.152.77 + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-leader + redis_setup_type: cluster + role: leader +# type: LoadBalancer + type: NodePort +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-followers +spec: + clusterIP: 10.108.109.134 + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-follower + redis_setup_type: cluster + role: follower +# type: LoadBalancer + type: NodePort diff --git a/example/external_service/clusterd.yaml b/example/v1beta2/external_service/clusterd.yaml similarity index 93% rename from example/external_service/clusterd.yaml rename to example/v1beta2/external_service/clusterd.yaml index 4bc986da5..fb7da8bf8 100644 --- a/example/external_service/clusterd.yaml +++ b/example/v1beta2/external_service/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/external_service/replication-svc.yaml b/example/v1beta2/external_service/replication-svc.yaml new file mode 100644 index 000000000..5e412de80 --- /dev/null +++ b/example/v1beta2/external_service/replication-svc.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication +# type: LoadBalancer + type: NodePort diff --git a/example/v1beta2/external_service/replication.yaml b/example/v1beta2/external_service/replication.yaml new file mode 100644 index 000000000..d8fa554e7 --- /dev/null +++ b/example/v1beta2/external_service/replication.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta2/external_service/standalone-svc.yaml b/example/v1beta2/external_service/standalone-svc.yaml new file mode 100644 index 000000000..df4efe038 --- /dev/null +++ b/example/v1beta2/external_service/standalone-svc.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-standalone + redis_setup_type: standalone + role: standalone + name: redis-standalone +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone + redis_setup_type: standalone + role: standalone +# type: LoadBalancer + type: NodePort diff --git a/example/v1beta2/external_service/standalone.yaml b/example/v1beta2/external_service/standalone.yaml new file mode 100644 index 000000000..2eb1d3ab6 --- /dev/null +++ b/example/v1beta2/external_service/standalone.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/node-selector/clusterd.yaml b/example/v1beta2/node-selector/clusterd.yaml similarity index 94% rename from example/node-selector/clusterd.yaml rename to example/v1beta2/node-selector/clusterd.yaml index 82b4ccf7b..ff4cd4b5c 100644 --- a/example/node-selector/clusterd.yaml +++ b/example/v1beta2/node-selector/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/node-selector/replication.yaml b/example/v1beta2/node-selector/replication.yaml new file mode 100644 index 000000000..5d9c08cb6 --- /dev/null +++ b/example/v1beta2/node-selector/replication.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + nodeSelector: + kubernetes.io/os: linux diff --git a/example/v1beta2/node-selector/standalone.yaml b/example/v1beta2/node-selector/standalone.yaml new file mode 100644 index 000000000..16c5b73cc --- /dev/null +++ b/example/v1beta2/node-selector/standalone.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + nodeSelector: + kubernetes.io/os: linux diff --git a/example/password_protected/clusterd.yaml b/example/v1beta2/password_protected/clusterd.yaml similarity index 94% rename from example/password_protected/clusterd.yaml rename to example/v1beta2/password_protected/clusterd.yaml index 18cbf4900..9a1c54de3 100644 --- a/example/password_protected/clusterd.yaml +++ b/example/v1beta2/password_protected/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/password_protected/replication.yaml b/example/v1beta2/password_protected/replication.yaml new file mode 100644 index 000000000..074d8c2ff --- /dev/null +++ b/example/v1beta2/password_protected/replication.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisSecret: + name: redis-secret + key: password + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 diff --git a/example/v1beta2/password_protected/secret.yaml b/example/v1beta2/password_protected/secret.yaml new file mode 100644 index 000000000..2a91c0d81 --- /dev/null +++ b/example/v1beta2/password_protected/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret +data: + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque \ No newline at end of file diff --git a/example/v1beta2/password_protected/standalone.yaml b/example/v1beta2/password_protected/standalone.yaml new file mode 100644 index 000000000..5c223cc5f --- /dev/null +++ b/example/v1beta2/password_protected/standalone.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + redisSecret: + name: redis-secret + key: password + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 diff --git a/example/private_registry/clusterd.yaml b/example/v1beta2/private_registry/clusterd.yaml similarity index 94% rename from example/private_registry/clusterd.yaml rename to example/v1beta2/private_registry/clusterd.yaml index 9202d2dd4..da1430ab4 100644 --- a/example/private_registry/clusterd.yaml +++ b/example/v1beta2/private_registry/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/private_registry/replication.yaml b/example/v1beta2/private_registry/replication.yaml new file mode 100644 index 000000000..03defed0a --- /dev/null +++ b/example/v1beta2/private_registry/replication.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: regcred + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 diff --git a/example/v1beta2/private_registry/standalone.yaml b/example/v1beta2/private_registry/standalone.yaml new file mode 100644 index 000000000..35ae6b94d --- /dev/null +++ b/example/v1beta2/private_registry/standalone.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: regcred + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 diff --git a/example/probes/clusterd.yaml b/example/v1beta2/probes/clusterd.yaml similarity index 96% rename from example/probes/clusterd.yaml rename to example/v1beta2/probes/clusterd.yaml index 981483c08..ff4741c98 100644 --- a/example/probes/clusterd.yaml +++ b/example/v1beta2/probes/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/probes/replication.yaml b/example/v1beta2/probes/replication.yaml new file mode 100644 index 000000000..e0b525882 --- /dev/null +++ b/example/v1beta2/probes/replication.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 + livenessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 diff --git a/example/v1beta2/probes/standalone.yaml b/example/v1beta2/probes/standalone.yaml new file mode 100644 index 000000000..632c18d53 --- /dev/null +++ b/example/v1beta2/probes/standalone.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + readinessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 + livenessProbe: + failureThreshold: 5 + initialDelaySeconds: 15 + periodSeconds: 15 + successThreshold: 1 + timeoutSeconds: 5 diff --git a/example/recreate-statefulset/clusterd.yaml b/example/v1beta2/recreate-statefulset/clusterd.yaml similarity index 94% rename from example/recreate-statefulset/clusterd.yaml rename to example/v1beta2/recreate-statefulset/clusterd.yaml index cf7098e15..028271cab 100644 --- a/example/recreate-statefulset/clusterd.yaml +++ b/example/v1beta2/recreate-statefulset/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/recreate-statefulset/replication.yaml b/example/v1beta2/recreate-statefulset/replication.yaml new file mode 100644 index 000000000..127833fc7 --- /dev/null +++ b/example/v1beta2/recreate-statefulset/replication.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication + annotations: + redis.opstreelabs.in/recreate-statefulset: "true" +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + priorityClassName: system-cluster-critical diff --git a/example/v1beta2/recreate-statefulset/standalone.yaml b/example/v1beta2/recreate-statefulset/standalone.yaml new file mode 100644 index 000000000..8ff47e8ab --- /dev/null +++ b/example/v1beta2/recreate-statefulset/standalone.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone + annotations: + redis.opstreelabs.in/recreate-statefulset: "true" +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + priorityClassName: system-cluster-critical diff --git a/example/redis-cluster.yaml b/example/v1beta2/redis-cluster.yaml similarity index 97% rename from example/redis-cluster.yaml rename to example/v1beta2/redis-cluster.yaml index cfde99863..f32a8f4a5 100644 --- a/example/redis-cluster.yaml +++ b/example/v1beta2/redis-cluster.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/redis-replication.yaml b/example/v1beta2/redis-replication.yaml similarity index 96% rename from example/redis-replication.yaml rename to example/v1beta2/redis-replication.yaml index db96e4c0c..aab7d798c 100644 --- a/example/redis-replication.yaml +++ b/example/v1beta2/redis-replication.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: name: redis-replication diff --git a/example/redis-sentinel.yaml b/example/v1beta2/redis-sentinel.yaml similarity index 91% rename from example/redis-sentinel.yaml rename to example/v1beta2/redis-sentinel.yaml index 7692e7e09..cd9a3a4ec 100644 --- a/example/redis-sentinel.yaml +++ b/example/v1beta2/redis-sentinel.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisSentinel metadata: name: redis-sentinel diff --git a/example/redis-standalone.yaml b/example/v1beta2/redis-standalone.yaml similarity index 96% rename from example/redis-standalone.yaml rename to example/v1beta2/redis-standalone.yaml index 88632f7e1..f2aa1aa70 100644 --- a/example/redis-standalone.yaml +++ b/example/v1beta2/redis-standalone.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: name: redis-standalone diff --git a/example/redis_monitoring/clusterd.yaml b/example/v1beta2/redis_monitoring/clusterd.yaml similarity index 94% rename from example/redis_monitoring/clusterd.yaml rename to example/v1beta2/redis_monitoring/clusterd.yaml index 617f9c3a2..7a8a08276 100644 --- a/example/redis_monitoring/clusterd.yaml +++ b/example/v1beta2/redis_monitoring/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/redis_monitoring/replication.yaml b/example/v1beta2/redis_monitoring/replication.yaml new file mode 100644 index 000000000..02b9bc498 --- /dev/null +++ b/example/v1beta2/redis_monitoring/replication.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +# annotations: +# redis.opstreelabs.in/skip-reconcile: "true" +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 diff --git a/example/v1beta2/redis_monitoring/standalone.yaml b/example/v1beta2/redis_monitoring/standalone.yaml new file mode 100644 index 000000000..1753c2558 --- /dev/null +++ b/example/v1beta2/redis_monitoring/standalone.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +# annotations: +# redis.opstreelabs.in/skip-reconcile: "true" +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 diff --git a/example/v1beta2/redis_sentinel/sentinel.yaml b/example/v1beta2/redis_sentinel/sentinel.yaml new file mode 100644 index 000000000..c2840cd53 --- /dev/null +++ b/example/v1beta2/redis_sentinel/sentinel.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:v7.0.7 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi diff --git a/example/sidecar_features/configmap.yaml b/example/v1beta2/sidecar_features/configmap.yaml similarity index 100% rename from example/sidecar_features/configmap.yaml rename to example/v1beta2/sidecar_features/configmap.yaml diff --git a/example/sidecar_features/sidecar.yaml b/example/v1beta2/sidecar_features/sidecar.yaml similarity index 96% rename from example/sidecar_features/sidecar.yaml rename to example/v1beta2/sidecar_features/sidecar.yaml index d40ee0611..eb69bd8fc 100644 --- a/example/sidecar_features/sidecar.yaml +++ b/example/v1beta2/sidecar_features/sidecar.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: name: redis-standalone2 diff --git a/example/tls_enabled/redis-cluster.yaml b/example/v1beta2/tls_enabled/redis-cluster.yaml similarity index 96% rename from example/tls_enabled/redis-cluster.yaml rename to example/v1beta2/tls_enabled/redis-cluster.yaml index af57922fe..9da46d137 100644 --- a/example/tls_enabled/redis-cluster.yaml +++ b/example/v1beta2/tls_enabled/redis-cluster.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/tls_enabled/redis-replication.yaml b/example/v1beta2/tls_enabled/redis-replication.yaml new file mode 100644 index 000000000..2496a896f --- /dev/null +++ b/example/v1beta2/tls_enabled/redis-replication.yaml @@ -0,0 +1,45 @@ +# Examples of creating a valid TLS certificate can be found at ./config/certmanager via Cert-manager +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/v1beta2/tls_enabled/redis-standalone.yaml b/example/v1beta2/tls_enabled/redis-standalone.yaml new file mode 100644 index 000000000..800cda7f9 --- /dev/null +++ b/example/v1beta2/tls_enabled/redis-standalone.yaml @@ -0,0 +1,44 @@ +# Examples of creating a valid TLS certificate can be found at ./config/certmanager via Cert-manager +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/example/tolerations/clusterd.yaml b/example/v1beta2/tolerations/clusterd.yaml similarity index 95% rename from example/tolerations/clusterd.yaml rename to example/v1beta2/tolerations/clusterd.yaml index 80fecb237..a4de514a8 100644 --- a/example/tolerations/clusterd.yaml +++ b/example/v1beta2/tolerations/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/tolerations/replication.yaml b/example/v1beta2/tolerations/replication.yaml similarity index 92% rename from example/tolerations/replication.yaml rename to example/v1beta2/tolerations/replication.yaml index 5644cf61f..62789ae90 100644 --- a/example/tolerations/replication.yaml +++ b/example/v1beta2/tolerations/replication.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: name: redis-replication diff --git a/example/v1beta2/tolerations/standalone.yaml b/example/v1beta2/tolerations/standalone.yaml new file mode 100644 index 000000000..2fe7eff94 --- /dev/null +++ b/example/v1beta2/tolerations/standalone.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + tolerations: + - key: "key1" + operator: "Equal" + value: "value1" + effect: "NoSchedule" diff --git a/example/upgrade-strategy/clusterd.yaml b/example/v1beta2/upgrade-strategy/clusterd.yaml similarity index 94% rename from example/upgrade-strategy/clusterd.yaml rename to example/v1beta2/upgrade-strategy/clusterd.yaml index 8fdf0a545..81dd36d73 100644 --- a/example/upgrade-strategy/clusterd.yaml +++ b/example/v1beta2/upgrade-strategy/clusterd.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/upgrade-strategy/replication.yaml b/example/v1beta2/upgrade-strategy/replication.yaml similarity index 92% rename from example/upgrade-strategy/replication.yaml rename to example/v1beta2/upgrade-strategy/replication.yaml index d53a25af7..5b8537785 100644 --- a/example/upgrade-strategy/replication.yaml +++ b/example/v1beta2/upgrade-strategy/replication.yaml @@ -1,5 +1,5 @@ --- -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: name: redis-replication diff --git a/example/v1beta2/upgrade-strategy/standalone.yaml b/example/v1beta2/upgrade-strategy/standalone.yaml new file mode 100644 index 000000000..ca413bb57 --- /dev/null +++ b/example/v1beta2/upgrade-strategy/standalone.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + updateStrategy: + type: OnDelete +# type: RollingUpdate + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 \ No newline at end of file diff --git a/example/v1beta2/volume_mount/configmap.yaml b/example/v1beta2/volume_mount/configmap.yaml new file mode 100644 index 000000000..eb5501a23 --- /dev/null +++ b/example/v1beta2/volume_mount/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: example-configmap + labels: + app: myapplication +data: + my-key: my-value \ No newline at end of file diff --git a/example/volume_mount/redis-cluster.yaml b/example/v1beta2/volume_mount/redis-cluster.yaml similarity index 96% rename from example/volume_mount/redis-cluster.yaml rename to example/v1beta2/volume_mount/redis-cluster.yaml index c65ddfa6b..50c8af66e 100644 --- a/example/volume_mount/redis-cluster.yaml +++ b/example/v1beta2/volume_mount/redis-cluster.yaml @@ -1,4 +1,4 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster diff --git a/example/v1beta2/volume_mount/redis-replication.yaml b/example/v1beta2/volume_mount/redis-replication.yaml new file mode 100644 index 000000000..8adf9e300 --- /dev/null +++ b/example/v1beta2/volume_mount/redis-replication.yaml @@ -0,0 +1,50 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + # redisConfig: + # additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumemount: + volume: + - name: example-config + configMap: + name: example-configmap + mount: + - mountPath: /config + name: example-config diff --git a/example/v1beta2/volume_mount/redis-standalone.yaml b/example/v1beta2/volume_mount/redis-standalone.yaml new file mode 100644 index 000000000..e3257876d --- /dev/null +++ b/example/v1beta2/volume_mount/redis-standalone.yaml @@ -0,0 +1,49 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + # redisConfig: + # additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.5 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumemount: + volume: + - name: example-config + configMap: + name: example-configmap + mount: + - mountPath: /config + name: example-config From ebc0a527cb02dbf5b0d86d9819b562b60f99f9e0 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 10 Sep 2023 21:04:00 +0530 Subject: [PATCH 003/203] fix bugs in redis cluster conversion (#618) Signed-off-by: Shubham Gupta --- api/v1beta1/rediscluster_conversion.go | 107 +++++++++++++++++++++++-- api/v1beta1/rediscluster_types.go | 12 +-- api/v1beta1/zz_generated.deepcopy.go | 4 +- api/v1beta2/rediscluster_types.go | 12 +-- api/v1beta2/zz_generated.deepcopy.go | 4 +- controllers/rediscluster_controller.go | 4 +- k8sutils/poddisruption.go | 2 +- k8sutils/redis-cluster.go | 28 +++---- 8 files changed, 135 insertions(+), 38 deletions(-) diff --git a/api/v1beta1/rediscluster_conversion.go b/api/v1beta1/rediscluster_conversion.go index c5e715b4a..0ee4f3018 100644 --- a/api/v1beta1/rediscluster_conversion.go +++ b/api/v1beta1/rediscluster_conversion.go @@ -9,7 +9,6 @@ import ( func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*redisv1beta2.RedisCluster) - // ObjectMeta dst.ObjectMeta = src.ObjectMeta @@ -24,9 +23,58 @@ func (src *RedisCluster) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.ClusterVersion = src.Spec.ClusterVersion } // RedisLeader - dst.Spec.RedisLeader.CommonAttributes = src.Spec.RedisLeader.CommonAttributes + dst.Spec.RedisLeader = redisv1beta2.RedisLeader{} + if src.Spec.RedisLeader.Replicas != nil { + dst.Spec.RedisLeader.Replicas = src.Spec.RedisLeader.Replicas + } + if src.Spec.RedisLeader.RedisConfig != nil { + dst.Spec.RedisLeader.RedisConfig = src.Spec.RedisLeader.RedisConfig + } + if src.Spec.RedisLeader.Affinity != nil { + dst.Spec.RedisLeader.Affinity = src.Spec.RedisLeader.Affinity + } + if src.Spec.RedisLeader.PodDisruptionBudget != nil { + dst.Spec.RedisLeader.PodDisruptionBudget = src.Spec.RedisLeader.PodDisruptionBudget + } + if src.Spec.RedisLeader.ReadinessProbe != nil { + dst.Spec.RedisLeader.ReadinessProbe = src.Spec.RedisLeader.ReadinessProbe + } + if src.Spec.RedisLeader.LivenessProbe != nil { + dst.Spec.RedisLeader.LivenessProbe = src.Spec.RedisLeader.LivenessProbe + } + if src.Spec.RedisLeader.Tolerations != nil { + dst.Spec.RedisLeader.Tolerations = src.Spec.RedisLeader.Tolerations + } + if src.Spec.RedisLeader.NodeSelector != nil { + dst.Spec.RedisLeader.NodeSelector = src.Spec.RedisLeader.NodeSelector + } + // RedisFollower - dst.Spec.RedisFollower.CommonAttributes = src.Spec.RedisFollower.CommonAttributes + dst.Spec.RedisFollower = redisv1beta2.RedisFollower{} + if src.Spec.RedisFollower.Replicas != nil { + dst.Spec.RedisFollower.Replicas = src.Spec.RedisFollower.Replicas + } + if src.Spec.RedisFollower.RedisConfig != nil { + dst.Spec.RedisFollower.RedisConfig = src.Spec.RedisFollower.RedisConfig + } + if src.Spec.RedisFollower.Affinity != nil { + dst.Spec.RedisFollower.Affinity = src.Spec.RedisFollower.Affinity + } + if src.Spec.RedisFollower.PodDisruptionBudget != nil { + dst.Spec.RedisFollower.PodDisruptionBudget = src.Spec.RedisFollower.PodDisruptionBudget + } + if src.Spec.RedisFollower.ReadinessProbe != nil { + dst.Spec.RedisFollower.ReadinessProbe = src.Spec.RedisFollower.ReadinessProbe + } + if src.Spec.RedisFollower.LivenessProbe != nil { + dst.Spec.RedisFollower.LivenessProbe = src.Spec.RedisFollower.LivenessProbe + } + if src.Spec.RedisFollower.Tolerations != nil { + dst.Spec.RedisFollower.Tolerations = src.Spec.RedisFollower.Tolerations + } + if src.Spec.RedisFollower.NodeSelector != nil { + dst.Spec.RedisFollower.NodeSelector = src.Spec.RedisFollower.NodeSelector + } // RedisExporter if src.Spec.RedisExporter != nil { dst.Spec.RedisExporter = &redisv1beta2.RedisExporter{} @@ -95,9 +143,58 @@ func (dst *RedisCluster) ConvertFrom(srcRaw conversion.Hub) error { dst.Spec.ClusterVersion = src.Spec.ClusterVersion } // RedisLeader - dst.Spec.RedisLeader.CommonAttributes = src.Spec.RedisLeader.CommonAttributes + dst.Spec.RedisLeader = RedisLeader{} + if src.Spec.RedisLeader.Replicas != nil { + dst.Spec.RedisLeader.Replicas = src.Spec.RedisLeader.Replicas + } + if src.Spec.RedisLeader.RedisConfig != nil { + dst.Spec.RedisLeader.RedisConfig = src.Spec.RedisLeader.RedisConfig + } + if src.Spec.RedisLeader.Affinity != nil { + dst.Spec.RedisLeader.Affinity = src.Spec.RedisLeader.Affinity + } + if src.Spec.RedisLeader.PodDisruptionBudget != nil { + dst.Spec.RedisLeader.PodDisruptionBudget = src.Spec.RedisLeader.PodDisruptionBudget + } + if src.Spec.RedisLeader.ReadinessProbe != nil { + dst.Spec.RedisLeader.ReadinessProbe = src.Spec.RedisLeader.ReadinessProbe + } + if src.Spec.RedisLeader.LivenessProbe != nil { + dst.Spec.RedisLeader.LivenessProbe = src.Spec.RedisLeader.LivenessProbe + } + if src.Spec.RedisLeader.Tolerations != nil { + dst.Spec.RedisLeader.Tolerations = src.Spec.RedisLeader.Tolerations + } + if src.Spec.RedisLeader.NodeSelector != nil { + dst.Spec.RedisLeader.NodeSelector = src.Spec.RedisLeader.NodeSelector + } + // RedisFollower - dst.Spec.RedisFollower.CommonAttributes = src.Spec.RedisFollower.CommonAttributes + dst.Spec.RedisFollower = RedisFollower{} + if src.Spec.RedisFollower.Replicas != nil { + dst.Spec.RedisFollower.Replicas = src.Spec.RedisFollower.Replicas + } + if src.Spec.RedisFollower.RedisConfig != nil { + dst.Spec.RedisFollower.RedisConfig = src.Spec.RedisFollower.RedisConfig + } + if src.Spec.RedisFollower.Affinity != nil { + dst.Spec.RedisFollower.Affinity = src.Spec.RedisFollower.Affinity + } + if src.Spec.RedisFollower.PodDisruptionBudget != nil { + dst.Spec.RedisFollower.PodDisruptionBudget = src.Spec.RedisFollower.PodDisruptionBudget + } + if src.Spec.RedisFollower.ReadinessProbe != nil { + dst.Spec.RedisFollower.ReadinessProbe = src.Spec.RedisFollower.ReadinessProbe + } + if src.Spec.RedisFollower.LivenessProbe != nil { + dst.Spec.RedisFollower.LivenessProbe = src.Spec.RedisFollower.LivenessProbe + } + if src.Spec.RedisFollower.Tolerations != nil { + dst.Spec.RedisFollower.Tolerations = src.Spec.RedisFollower.Tolerations + } + if src.Spec.RedisFollower.NodeSelector != nil { + dst.Spec.RedisFollower.NodeSelector = src.Spec.RedisFollower.NodeSelector + } // RedisExporter if src.Spec.RedisExporter != nil { dst.Spec.RedisExporter = &RedisExporter{} diff --git a/api/v1beta1/rediscluster_types.go b/api/v1beta1/rediscluster_types.go index ebe37792d..4076e71c0 100644 --- a/api/v1beta1/rediscluster_types.go +++ b/api/v1beta1/rediscluster_types.go @@ -45,22 +45,22 @@ type RedisClusterSpec struct { func (cr *RedisClusterSpec) GetReplicaCounts(t string) int32 { replica := cr.Size - if t == "leader" && cr.RedisLeader.CommonAttributes.Replicas != nil { - replica = cr.RedisLeader.CommonAttributes.Replicas - } else if t == "follower" && cr.RedisFollower.CommonAttributes.Replicas != nil { - replica = cr.RedisFollower.CommonAttributes.Replicas + if t == "leader" && cr.RedisLeader.Replicas != nil { + replica = cr.RedisLeader.Replicas + } else if t == "follower" && cr.RedisFollower.Replicas != nil { + replica = cr.RedisFollower.Replicas } return *replica } // RedisLeader interface will have the redis leader configuration type RedisLeader struct { - CommonAttributes common.RedisLeader `json:",inline"` + common.RedisLeader `json:",inline"` } // RedisFollower interface will have the redis follower configuration type RedisFollower struct { - CommonAttributes common.RedisFollower `json:",inline"` + common.RedisFollower `json:",inline"` } // RedisClusterStatus defines the observed state of RedisCluster diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 60c4a668c..ff2aa9844 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -294,7 +294,7 @@ func (in *RedisExporter) DeepCopy() *RedisExporter { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFollower) DeepCopyInto(out *RedisFollower) { *out = *in - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.RedisFollower.DeepCopyInto(&out.RedisFollower) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFollower. @@ -310,7 +310,7 @@ func (in *RedisFollower) DeepCopy() *RedisFollower { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLeader) DeepCopyInto(out *RedisLeader) { *out = *in - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.RedisLeader.DeepCopyInto(&out.RedisLeader) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLeader. diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index 829737a2f..64c7c881b 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -47,24 +47,24 @@ type RedisClusterSpec struct { func (cr *RedisClusterSpec) GetReplicaCounts(t string) int32 { replica := cr.Size - if t == "leader" && cr.RedisLeader.CommonAttributes.Replicas != nil { - replica = cr.RedisLeader.CommonAttributes.Replicas - } else if t == "follower" && cr.RedisFollower.CommonAttributes.Replicas != nil { - replica = cr.RedisFollower.CommonAttributes.Replicas + if t == "leader" && cr.RedisLeader.Replicas != nil { + replica = cr.RedisLeader.Replicas + } else if t == "follower" && cr.RedisFollower.Replicas != nil { + replica = cr.RedisFollower.Replicas } return *replica } // RedisLeader interface will have the redis leader configuration type RedisLeader struct { - CommonAttributes common.RedisLeader `json:",inline"` + common.RedisLeader `json:",inline"` SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` } // RedisFollower interface will have the redis follower configuration type RedisFollower struct { - CommonAttributes common.RedisFollower `json:",inline"` + common.RedisFollower `json:",inline"` SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` } diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index df9897888..a813ba2c5 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -387,7 +387,7 @@ func (in *RedisExporter) DeepCopy() *RedisExporter { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisFollower) DeepCopyInto(out *RedisFollower) { *out = *in - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.RedisFollower.DeepCopyInto(&out.RedisFollower) if in.SecurityContext != nil { in, out := &in.SecurityContext, &out.SecurityContext *out = new(v1.SecurityContext) @@ -413,7 +413,7 @@ func (in *RedisFollower) DeepCopy() *RedisFollower { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisLeader) DeepCopyInto(out *RedisLeader) { *out = *in - in.CommonAttributes.DeepCopyInto(&out.CommonAttributes) + in.RedisLeader.DeepCopyInto(&out.RedisLeader) if in.SecurityContext != nil { in, out := &in.SecurityContext, &out.SecurityContext *out = new(v1.SecurityContext) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 9f7f17291..57c605ae5 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -104,7 +104,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } } - err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.CommonAttributes.PodDisruptionBudget) + err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } @@ -126,7 +126,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{RequeueAfter: time.Second * 60}, err } } - err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.CommonAttributes.PodDisruptionBudget) + err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.PodDisruptionBudget) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 0dd5131dd..ca398efb3 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -22,7 +22,7 @@ func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role strin labels := getRedisLabels(cr.ObjectMeta.Name, "cluster", role, cr.ObjectMeta.GetLabels()) annotations := generateStatefulSetsAnots(cr.ObjectMeta) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) - pdbDef := generatePodDisruptionBudgetDef(cr, role, pdbMeta, cr.Spec.RedisLeader.CommonAttributes.PodDisruptionBudget) + pdbDef := generatePodDisruptionBudgetDef(cr, role, pdbMeta, cr.Spec.RedisLeader.PodDisruptionBudget) return CreateOrUpdatePodDisruptionBudget(pdbDef) } else { // Check if one exists, and delete it. diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 44a051c39..b17ea6b97 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -151,15 +151,15 @@ func CreateRedisLeader(cr *redisv1beta2.RedisCluster) error { prop := RedisClusterSTS{ RedisStateFulType: "leader", SecurityContext: cr.Spec.RedisLeader.SecurityContext, - Affinity: cr.Spec.RedisLeader.CommonAttributes.Affinity, + Affinity: cr.Spec.RedisLeader.Affinity, TerminationGracePeriodSeconds: cr.Spec.RedisLeader.TerminationGracePeriodSeconds, - NodeSelector: cr.Spec.RedisLeader.CommonAttributes.NodeSelector, - Tolerations: cr.Spec.RedisLeader.CommonAttributes.Tolerations, - ReadinessProbe: cr.Spec.RedisLeader.CommonAttributes.ReadinessProbe, - LivenessProbe: cr.Spec.RedisLeader.CommonAttributes.LivenessProbe, + NodeSelector: cr.Spec.RedisLeader.NodeSelector, + Tolerations: cr.Spec.RedisLeader.Tolerations, + ReadinessProbe: cr.Spec.RedisLeader.ReadinessProbe, + LivenessProbe: cr.Spec.RedisLeader.LivenessProbe, } - if cr.Spec.RedisLeader.CommonAttributes.RedisConfig != nil { - prop.ExternalConfig = cr.Spec.RedisLeader.CommonAttributes.RedisConfig.AdditionalRedisConfig + if cr.Spec.RedisLeader.RedisConfig != nil { + prop.ExternalConfig = cr.Spec.RedisLeader.RedisConfig.AdditionalRedisConfig } return prop.CreateRedisClusterSetup(cr) } @@ -169,15 +169,15 @@ func CreateRedisFollower(cr *redisv1beta2.RedisCluster) error { prop := RedisClusterSTS{ RedisStateFulType: "follower", SecurityContext: cr.Spec.RedisFollower.SecurityContext, - Affinity: cr.Spec.RedisFollower.CommonAttributes.Affinity, + Affinity: cr.Spec.RedisFollower.Affinity, TerminationGracePeriodSeconds: cr.Spec.RedisFollower.TerminationGracePeriodSeconds, - NodeSelector: cr.Spec.RedisFollower.CommonAttributes.NodeSelector, - Tolerations: cr.Spec.RedisFollower.CommonAttributes.Tolerations, - ReadinessProbe: cr.Spec.RedisFollower.CommonAttributes.ReadinessProbe, - LivenessProbe: cr.Spec.RedisFollower.CommonAttributes.LivenessProbe, + NodeSelector: cr.Spec.RedisFollower.NodeSelector, + Tolerations: cr.Spec.RedisFollower.Tolerations, + ReadinessProbe: cr.Spec.RedisFollower.ReadinessProbe, + LivenessProbe: cr.Spec.RedisFollower.LivenessProbe, } - if cr.Spec.RedisFollower.CommonAttributes.RedisConfig != nil { - prop.ExternalConfig = cr.Spec.RedisFollower.CommonAttributes.RedisConfig.AdditionalRedisConfig + if cr.Spec.RedisFollower.RedisConfig != nil { + prop.ExternalConfig = cr.Spec.RedisFollower.RedisConfig.AdditionalRedisConfig } return prop.CreateRedisClusterSetup(cr) } From 1cd61a2cad23876eb5d07d8ae9e368600557b489 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 11 Sep 2023 01:19:14 +0530 Subject: [PATCH 004/203] [Fix] : Status Field to Redis Cluster (#612) * Add : Status Field to Redis Cluster Signed-off-by: Shubham Gupta * fix status bugs Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- api/rbac.go | 4 +- api/status/redis-cluster_status.go | 18 +++++++ api/v1beta2/rediscluster_types.go | 16 +++++-- ...is.redis.opstreelabs.in_redisclusters.yaml | 36 +++++++++++--- config/rbac/role.yaml | 6 +++ controllers/rediscluster_controller.go | 40 +++++++++++++++- k8sutils/status.go | 48 +++++++++++++++++++ 7 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 api/status/redis-cluster_status.go create mode 100644 k8sutils/status.go diff --git a/api/rbac.go b/api/rbac.go index 585cae78b..9510243ec 100644 --- a/api/rbac.go +++ b/api/rbac.go @@ -3,8 +3,8 @@ package api // +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=rediss;redisclusters;redisreplications;redis;rediscluster;redissentinel;redissentinels;redisreplication,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:urls=*,verbs=get // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch -// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/finalizers;rediscluster/finalizers;redissentinel/finalizers;redisreplication/finalizers,verbs=update -// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/status;rediscluster/status;redissentinel/status;redisreplication/status,verbs=get;patch;update +// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/finalizers;rediscluster/finalizers;redisclusters/finalizers;redissentinel/finalizers;redissentinels/finalizers;redisreplication/finalizers;redisreplications/finalizers,verbs=update +// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/status;rediscluster/status;redisclusters/status;redissentinel/status;redissentinels/status;redisreplication/status;redisreplications/status,verbs=get;patch;update // +kubebuilder:rbac:groups=,resources=secrets;pods/exec;pods;services;configmaps;events;persistentvolumeclaims;namespaces,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=create;delete;get;list;patch;update;watch diff --git a/api/status/redis-cluster_status.go b/api/status/redis-cluster_status.go new file mode 100644 index 000000000..d80b6fca0 --- /dev/null +++ b/api/status/redis-cluster_status.go @@ -0,0 +1,18 @@ +package status + +type RedisClusterState string + +const ( + ReadyClusterReason string = "RedisCluster is ready" + InitializingClusterLeaderReason string = "RedisCluster is initializing leaders" + InitializingClusterFollowerReason string = "RedisCluster is initializing followers" + BootstrapClusterReason string = "RedisCluster is bootstrapping" +) + +// Status Field of the Redis Cluster +const ( + RedisClusterReady RedisClusterState = "Ready" + RedisClusterInitializing RedisClusterState = "Initializing" + RedisClusterBootstrap RedisClusterState = "Bootstrap" + // RedisClusterFailed RedisClusterState = "Failed" +) diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index 64c7c881b..1de719f9c 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -18,6 +18,7 @@ package v1beta2 import ( common "github.com/OT-CONTAINER-KIT/redis-operator/api" + status "github.com/OT-CONTAINER-KIT/redis-operator/api/status" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -71,15 +72,24 @@ type RedisFollower struct { // RedisClusterStatus defines the observed state of RedisCluster type RedisClusterStatus struct { + State status.RedisClusterState `json:"state,omitempty"` + Reason string `json:"reason,omitempty"` + // +kubebuilder:default=0 + ReadyLeaderReplicas int32 `json:"readyLeaderReplicas,omitempty"` + // +kubebuilder:default=0 + ReadyFollowerReplicas int32 `json:"readyFollowerReplicas,omitempty"` } // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:storageversion // +kubebuilder:printcolumn:name="ClusterSize",type=integer,JSONPath=`.spec.clusterSize`,description=Current cluster node count -// +kubebuilder:printcolumn:name="LeaderReplicas",type=integer,JSONPath=`.spec.redisLeader.CommonAttributes.Replicas`,description=Overridden Leader replica count -// +kubebuilder:printcolumn:name="FollowerReplicas",type=integer,JSONPath=`.spec.redisFollower.CommonAttributes.Replicas`,description=Overridden Follower replica count -// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`,description=Age of Cluster +// +kubebuilder:printcolumn:name="ReadyLeaderReplicas",type="integer",JSONPath=".status.readyLeaderReplicas",description="Number of ready leader replicas" +// +kubebuilder:printcolumn:name="ReadyFollowerReplicas",type="integer",JSONPath=".status.readyFollowerReplicas",description="Number of ready follower replicas" +// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.state",description="The current state of the Redis Cluster",priority=1 +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`,description="Age of Cluster",priority=1 +// +kubebuilder:printcolumn:name="Reason",type="string",JSONPath=".status.reason",description="The reason for the current state",priority=1 + // RedisCluster is the Schema for the redisclusters API type RedisCluster struct { metav1.TypeMeta `json:",inline"` diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 77ac2b80d..2c6967d6d 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -4728,18 +4728,29 @@ spec: jsonPath: .spec.clusterSize name: ClusterSize type: integer - - description: Overridden Leader replica count - jsonPath: .spec.redisLeader.CommonAttributes.Replicas - name: LeaderReplicas + - description: Number of ready leader replicas + jsonPath: .status.readyLeaderReplicas + name: ReadyLeaderReplicas type: integer - - description: Overridden Follower replica count - jsonPath: .spec.redisFollower.CommonAttributes.Replicas - name: FollowerReplicas + - description: Number of ready follower replicas + jsonPath: .status.readyFollowerReplicas + name: ReadyFollowerReplicas type: integer + - description: The current state of the Redis Cluster + jsonPath: .status.state + name: State + priority: 1 + type: string - description: Age of Cluster jsonPath: .metadata.creationTimestamp name: Age + priority: 1 type: date + - description: The reason for the current state + jsonPath: .status.reason + name: Reason + priority: 1 + type: string name: v1beta2 schema: openAPIV3Schema: @@ -10354,6 +10365,19 @@ spec: type: object status: description: RedisClusterStatus defines the observed state of RedisCluster + properties: + readyFollowerReplicas: + default: 0 + format: int32 + type: integer + readyLeaderReplicas: + default: 0 + format: int32 + type: integer + reason: + type: string + state: + type: string type: object required: - spec diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 16adb95fa..75c1dc55a 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -95,8 +95,11 @@ rules: resources: - redis/finalizers - rediscluster/finalizers + - redisclusters/finalizers - redisreplication/finalizers + - redisreplications/finalizers - redissentinel/finalizers + - redissentinels/finalizers verbs: - update - apiGroups: @@ -104,8 +107,11 @@ rules: resources: - redis/status - rediscluster/status + - redisclusters/status - redisreplication/status + - redisreplications/status - redissentinel/status + - redissentinels/status verbs: - get - patch diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 57c605ae5..02b577055 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -21,6 +21,7 @@ import ( "strconv" "time" + "github.com/OT-CONTAINER-KIT/redis-operator/api/status" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" "github.com/go-logr/logr" @@ -69,7 +70,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Check if the cluster is downscaled - if leaderReplicas < k8sutils.CheckRedisNodeCount(instance, "leader") { + if leaderReplicas < instance.Status.ReadyLeaderReplicas { // Imp if the last index of leader sts is not leader make it then // check whether the redis is leader or not ? @@ -93,6 +94,14 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{RequeueAfter: time.Second * 100}, nil } + // Mark the cluster status as initializing if there are no leader or follower nodes + if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, 0, 0) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err + } + } + err = k8sutils.CreateRedisLeader(instance) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err @@ -115,6 +124,15 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } if int32(redisLeaderInfo.Status.ReadyReplicas) == leaderReplicas { + + // Mark the cluster status as initializing if there are no follower nodes + if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, 0) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err + } + } + err = k8sutils.CreateRedisFollower(instance) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err @@ -145,6 +163,17 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request reqLogger.Info("Redis leader and follower nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) return ctrl.Result{RequeueAfter: time.Second * 120}, nil } + + // Mark the cluster status as bootstrapping if all the leader and follower nodes are ready + if int32(redisLeaderInfo.Status.ReadyReplicas) == leaderReplicas && int32(redisFollowerInfo.Status.ReadyReplicas) == followerReplicas { + if instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == 0 { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err + } + } + } + reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) if k8sutils.CheckRedisNodeCount(instance, "") != totalReplicas { leaderCount := k8sutils.CheckRedisNodeCount(instance, "leader") @@ -186,6 +215,15 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request k8sutils.CheckIfEmptyMasters(instance) } reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") + + // Mark the cluster status as ready if all the leader and follower nodes are ready + if instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err + } + } + return ctrl.Result{RequeueAfter: time.Second * 10}, nil } diff --git a/k8sutils/status.go b/k8sutils/status.go new file mode 100644 index 000000000..1232b2384 --- /dev/null +++ b/k8sutils/status.go @@ -0,0 +1,48 @@ +package k8sutils + +import ( + "context" + + status "github.com/OT-CONTAINER-KIT/redis-operator/api/status" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// statusLogger will generate logging interface for status +func statusLogger(namespace string, name string) logr.Logger { + reqLogger := log.WithValues("Request.Namespace", namespace, "Request.Name", name) + return reqLogger +} + +// UpdateRedisClusterStatus will update the status of the RedisCluster +func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.RedisClusterState, resaon string, readyLeaderReplicas, readyFollowerReplicas int32) error { + logger := statusLogger(cr.Namespace, cr.Name) + cr.Status.State = status + cr.Status.Reason = resaon + cr.Status.ReadyLeaderReplicas = readyLeaderReplicas + cr.Status.ReadyFollowerReplicas = readyFollowerReplicas + + client := generateK8sDynamicClient() + gvr := schema.GroupVersionResource{ + Group: "redis.redis.opstreelabs.in", + Version: "v1beta2", + Resource: "redisclusters", + } + unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(cr) + if err != nil { + logger.Error(err, "Failed to convert CR to unstructured object") + return err + } + unstructuredRedisCluster := &unstructured.Unstructured{Object: unstructuredObj} + + _, err = client.Resource(gvr).Namespace(cr.Namespace).UpdateStatus(context.TODO(), unstructuredRedisCluster, metav1.UpdateOptions{}) + if err != nil { + logger.Error(err, "Failed to update status") + return err + } + return nil +} From 71ef65b5546f7beb08bae78bebb0ff59b6fa67a7 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 11 Sep 2023 16:07:08 +0800 Subject: [PATCH 005/203] Support ENABLE_WEBHOOKS env which cloud disable webhook server locally (#617) * Support ENABLE_WEBHOOKS env which cloud disable webhook server on locally Signed-off-by: drivebyer * Add related flag Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- main.go | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/main.go b/main.go index 1ee4ec28a..d6b1cb761 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,8 @@ func main() { var metricsAddr string var enableLeaderElection bool var probeAddr string + var enableWebhooks bool + flag.BoolVar(&enableWebhooks, "enable-webhooks", os.Getenv("ENABLE_WEBHOOKS") != "false", "Enable webhooks") flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, @@ -122,21 +124,24 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "RedisSentinel") os.Exit(1) } - if err = (&redisv1beta2.Redis{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "Redis") - os.Exit(1) - } - if err = (&redisv1beta2.RedisCluster{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "RedisCluster") - os.Exit(1) - } - if err = (&redisv1beta2.RedisReplication{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "RedisReplication") - os.Exit(1) - } - if err = (&redisv1beta2.RedisSentinel{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "RedisSentinel") - os.Exit(1) + + if enableWebhooks { + if err = (&redisv1beta2.Redis{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Redis") + os.Exit(1) + } + if err = (&redisv1beta2.RedisCluster{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "RedisCluster") + os.Exit(1) + } + if err = (&redisv1beta2.RedisReplication{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "RedisReplication") + os.Exit(1) + } + if err = (&redisv1beta2.RedisSentinel{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "RedisSentinel") + os.Exit(1) + } } // +kubebuilder:scaffold:builder From 323dc4092027f10e2dd3f72e2ae99944e62ecb52 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 15 Sep 2023 12:10:27 +0530 Subject: [PATCH 006/203] Merge the e2e Test Files (#623) Signed-off-by: Shubham Gupta --- api/v1beta2/rediscluster_types.go | 1 + kuttl-test.yaml | 12 ------ .../_config/kind-config.yaml | 0 tests/_config/kuttl-test.yaml | 8 ++++ tests/e2e/setup/ready-standalone.yaml | 7 ---- tests/e2e/{ => v1beta1}/setup/00-install.yaml | 5 +-- .../setup/cluster.yaml} | 32 +++++++------- .../setup/ready-cluster-sts.yaml} | 4 +- tests/e2e/v1beta1/setup/ready-cluster.yaml | 7 ++++ tests/e2e/v1beta2/setup/00-install.yaml | 7 ++++ tests/e2e/{ => v1beta2}/setup/cluster.yaml | 11 ++--- .../e2e/v1beta2/setup/ready-cluster-sts.yaml | 17 ++++++++ tests/e2e/v1beta2/setup/ready-cluster.yaml | 7 ++++ tests/readme.md | 42 +++++++++++++++++++ 14 files changed, 116 insertions(+), 44 deletions(-) delete mode 100644 kuttl-test.yaml rename kind-config.yaml => tests/_config/kind-config.yaml (100%) create mode 100644 tests/_config/kuttl-test.yaml delete mode 100644 tests/e2e/setup/ready-standalone.yaml rename tests/e2e/{ => v1beta1}/setup/00-install.yaml (54%) rename tests/e2e/{setup/standalone.yaml => v1beta1/setup/cluster.yaml} (57%) rename tests/e2e/{setup/ready-cluster.yaml => v1beta1/setup/ready-cluster-sts.yaml} (70%) create mode 100644 tests/e2e/v1beta1/setup/ready-cluster.yaml create mode 100644 tests/e2e/v1beta2/setup/00-install.yaml rename tests/e2e/{ => v1beta2}/setup/cluster.yaml (82%) create mode 100644 tests/e2e/v1beta2/setup/ready-cluster-sts.yaml create mode 100644 tests/e2e/v1beta2/setup/ready-cluster.yaml create mode 100644 tests/readme.md diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index 1de719f9c..69e0e5ff9 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -71,6 +71,7 @@ type RedisFollower struct { } // RedisClusterStatus defines the observed state of RedisCluster +// +kubebuilder:subresource:status type RedisClusterStatus struct { State status.RedisClusterState `json:"state,omitempty"` Reason string `json:"reason,omitempty"` diff --git a/kuttl-test.yaml b/kuttl-test.yaml deleted file mode 100644 index e39b34d9b..000000000 --- a/kuttl-test.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestSuite -startKIND: true -kindConfig: "./kind-config.yaml" -crdDir: "./config/crd/bases" -testDirs: -- "./tests/e2e/" -# parallel: 3 -timeout: 1000 -namespace : ot-container -suppress : - - events \ No newline at end of file diff --git a/kind-config.yaml b/tests/_config/kind-config.yaml similarity index 100% rename from kind-config.yaml rename to tests/_config/kind-config.yaml diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml new file mode 100644 index 000000000..ab9b63777 --- /dev/null +++ b/tests/_config/kuttl-test.yaml @@ -0,0 +1,8 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestSuite +startKIND: false +kindConfig: "./kind-config.yaml" +parallel: 1 +timeout: 300 +suppress : + - events \ No newline at end of file diff --git a/tests/e2e/setup/ready-standalone.yaml b/tests/e2e/setup/ready-standalone.yaml deleted file mode 100644 index 8e92cf47b..000000000 --- a/tests/e2e/setup/ready-standalone.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-standalone -status: - replicas: 1 - readyReplicas: 1 \ No newline at end of file diff --git a/tests/e2e/setup/00-install.yaml b/tests/e2e/v1beta1/setup/00-install.yaml similarity index 54% rename from tests/e2e/setup/00-install.yaml rename to tests/e2e/v1beta1/setup/00-install.yaml index e9c279616..94b166978 100644 --- a/tests/e2e/setup/00-install.yaml +++ b/tests/e2e/v1beta1/setup/00-install.yaml @@ -1,8 +1,7 @@ apiVersion: kuttl.dev/v1beta1 kind: TestStep apply : - - standalone.yaml - cluster.yaml assert : - - ready-standalone.yaml - - ready-cluster.yaml \ No newline at end of file + - ready-cluster.yaml + - ready-cluster-sts.yaml \ No newline at end of file diff --git a/tests/e2e/setup/standalone.yaml b/tests/e2e/v1beta1/setup/cluster.yaml similarity index 57% rename from tests/e2e/setup/standalone.yaml rename to tests/e2e/v1beta1/setup/cluster.yaml index bbd480202..73afc2b4a 100644 --- a/tests/e2e/setup/standalone.yaml +++ b/tests/e2e/v1beta1/setup/cluster.yaml @@ -1,33 +1,35 @@ ---- apiVersion: redis.redis.opstreelabs.in/v1beta1 -kind: Redis +kind: RedisCluster metadata: - name: redis-standalone + name: redis-cluster-v1beta1 spec: - podSecurityContext: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + securityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.12 + image: quay.io/opstree/redis:v7.0.7 imagePullPolicy: IfNotPresent resources: requests: - cpu: 10m - memory: 10Mi + cpu: 101m + memory: 128Mi limits: - cpu: 10m - memory: 10Mi + cpu: 101m + memory: 128Mi redisExporter: - enabled: false + enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 imagePullPolicy: Always resources: requests: - cpu: 10m - memory: 10Mi + cpu: 100m + memory: 128Mi limits: - cpu: 10m - memory: 12Mi + cpu: 100m + memory: 128Mi storage: volumeClaimTemplate: spec: diff --git a/tests/e2e/setup/ready-cluster.yaml b/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml similarity index 70% rename from tests/e2e/setup/ready-cluster.yaml rename to tests/e2e/v1beta1/setup/ready-cluster-sts.yaml index a232d81f1..8c0fec94c 100644 --- a/tests/e2e/setup/ready-cluster.yaml +++ b/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml @@ -1,7 +1,7 @@ apiVersion: apps/v1 kind: StatefulSet metadata: - name: redis-cluster-leader + name: redis-cluster-v1beta1-leader status: replicas: 3 readyReplicas: 3 @@ -11,7 +11,7 @@ status: apiVersion: apps/v1 kind: StatefulSet metadata: - name: redis-cluster-follower + name: redis-cluster-v1beta1-follower status: replicas: 3 readyReplicas: 3 diff --git a/tests/e2e/v1beta1/setup/ready-cluster.yaml b/tests/e2e/v1beta1/setup/ready-cluster.yaml new file mode 100644 index 000000000..79a48407b --- /dev/null +++ b/tests/e2e/v1beta1/setup/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta1 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/00-install.yaml b/tests/e2e/v1beta2/setup/00-install.yaml new file mode 100644 index 000000000..94b166978 --- /dev/null +++ b/tests/e2e/v1beta2/setup/00-install.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - cluster.yaml +assert : + - ready-cluster.yaml + - ready-cluster-sts.yaml \ No newline at end of file diff --git a/tests/e2e/setup/cluster.yaml b/tests/e2e/v1beta2/setup/cluster.yaml similarity index 82% rename from tests/e2e/setup/cluster.yaml rename to tests/e2e/v1beta2/setup/cluster.yaml index 80aa3efaa..09b11b18b 100644 --- a/tests/e2e/setup/cluster.yaml +++ b/tests/e2e/v1beta2/setup/cluster.yaml @@ -1,7 +1,7 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: - name: redis-cluster + name: redis-cluster-v1beta2 spec: clusterSize: 3 clusterVersion: v7 @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.12 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: @@ -20,7 +20,7 @@ spec: cpu: 101m memory: 128Mi redisExporter: - enabled: false + enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 imagePullPolicy: Always resources: @@ -38,9 +38,10 @@ spec: resources: requests: storage: 1Gi + nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: accessModes: ["ReadWriteOnce"] resources: requests: - storage: 1Gi + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/ready-cluster-sts.yaml b/tests/e2e/v1beta2/setup/ready-cluster-sts.yaml new file mode 100644 index 000000000..2b6704dbe --- /dev/null +++ b/tests/e2e/v1beta2/setup/ready-cluster-sts.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/ready-cluster.yaml b/tests/e2e/v1beta2/setup/ready-cluster.yaml new file mode 100644 index 000000000..57d53c708 --- /dev/null +++ b/tests/e2e/v1beta2/setup/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta1 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + # readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/readme.md b/tests/readme.md new file mode 100644 index 000000000..155b89fb3 --- /dev/null +++ b/tests/readme.md @@ -0,0 +1,42 @@ +# E2E Testing of the Redis Cluster with Kuttl + +This guide will walk you through the process of end-to-end (E2E) testing a Redis cluster using the `kuttl` utility. + +## **Prerequisites** + +Ensure you have the following tools installed: + +- **kuttl**: For testing. [Installation Guide](https://kuttl.dev/docs/installation/) +- **kind**: For local Kubernetes clusters. [Installation Guide](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) +- **kubectl**: Kubernetes command-line tool. [Installation Guide](https://kubernetes.io/docs/tasks/tools/install-kubectl/) +- **helm**: Package manager for Kubernetes. [Installation Guide](https://helm.sh/docs/intro/install/) + +## **Steps** + +### **1. Set Up a 3-node Kind Cluster** + +## Steps to Follow + +### 1. Set Up a 3-node Kind Cluster + +Create a 3-node kind cluster using the provided configuration: + +```bash +kind create cluster --config /redis-operator/tests/_config/kind-example-config.yaml +``` + +### 2. Install the Redis Operator + +To install the Redis operator, utilize the Helm chart from the repository provided: + +- [OT-CONTAINER-KIT Redis Operator Helm Chart](https://github.com/OT-CONTAINER-KIT/helm-charts/tree/main/charts/redis-operator#readme) + +Please refer to the repository's README for detailed instructions on installing the operator using Helm. + +### 3. Execute Kuttl Test + +Execute the kuttl test using the following command: + +```bash +kubectl kuttl test redis-operator/tests/e2e/v1beta2 --config /redis-operator/tests/_config/kuttl-test.yaml --timeout 10m +``` From 3c7779af3b6946c1daed59c2949f4ca1fe3547cc Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 15 Sep 2023 15:16:12 +0530 Subject: [PATCH 007/203] [Fix] : Fix the backup and restore script and manifest (#624) * Add : job for bacup from the redis cluster Signed-off-by: Shubham Gupta * remove unwanted var rom env_vars.env Signed-off-by: Shubham Gupta * fix the backup scripts Signed-off-by: Shubham Gupta * docker file Signed-off-by: Shubham Gupta * write manifest for easy backup and restore Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .../backup_restore/backup/env-secrets.yaml | 18 ++++ .../v1beta2/backup_restore/backup/job.yaml | 20 ++++ .../backup_restore/backup/role-binding.yaml | 11 +++ .../v1beta2/backup_restore/backup/role.yaml | 8 ++ .../backup/service-account.yaml | 4 + .../{ => restore}/configmap.yaml | 0 .../{ => restore}/env-secret.yaml | 3 - .../{ => restore}/redis-cluster.yaml | 18 +--- example/v1beta2/redis-cluster.yaml | 3 +- scripts/backup/Dockerfile.kubectlpod | 9 +- scripts/backup/backup-user.bash | 9 +- scripts/backup/backup-v0.15.1.bash | 91 +++++++++++++++++++ scripts/backup/backup.bash | 17 ++-- scripts/backup/env_vars.env | 3 +- scripts/restore/env_vars.env | 2 +- 15 files changed, 181 insertions(+), 35 deletions(-) create mode 100644 example/v1beta2/backup_restore/backup/env-secrets.yaml create mode 100644 example/v1beta2/backup_restore/backup/job.yaml create mode 100644 example/v1beta2/backup_restore/backup/role-binding.yaml create mode 100644 example/v1beta2/backup_restore/backup/role.yaml create mode 100644 example/v1beta2/backup_restore/backup/service-account.yaml rename example/v1beta2/backup_restore/{ => restore}/configmap.yaml (100%) rename example/v1beta2/backup_restore/{ => restore}/env-secret.yaml (79%) rename example/v1beta2/backup_restore/{ => restore}/redis-cluster.yaml (87%) create mode 100644 scripts/backup/backup-v0.15.1.bash diff --git a/example/v1beta2/backup_restore/backup/env-secrets.yaml b/example/v1beta2/backup_restore/backup/env-secrets.yaml new file mode 100644 index 000000000..ae124980b --- /dev/null +++ b/example/v1beta2/backup_restore/backup/env-secrets.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Secret +metadata: + name: env-secrets + namespace: default +type: Opaque +stringData: + CLUSTER_NAME: redis-cluster + CLUSTER_NAMESPACE: default + RESTIC_PASSWORD: abc@123 + RESTIC_CACHE_DIR: "/tmp/restic_cache" + REDIS_PORT: "6379" + REDIS_PASSWORD: "" + BACKUP_DESTINATION: AWS_S3 + AWS_S3_BUCKET: shubham-redis + AWS_DEFAULT_REGION: ap-south-1 + AWS_ACCESS_KEY_ID: "" + AWS_SECRET_ACCESS_KEY: "" \ No newline at end of file diff --git a/example/v1beta2/backup_restore/backup/job.yaml b/example/v1beta2/backup_restore/backup/job.yaml new file mode 100644 index 000000000..6b9fcdc87 --- /dev/null +++ b/example/v1beta2/backup_restore/backup/job.yaml @@ -0,0 +1,20 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: redis-operator-backup-job + namespace: default +spec: + template: + metadata: + name: redis-operator-backup-pod + spec: + serviceAccountName: backup-service-account + containers: + - name: redis-operator-backup-container + image: "quay.io/opstree/redis-operator-backup:v0.15.1" + command: ["/bin/bash", "-c", "/backup/backup.bash"] + imagePullPolicy: Always + envFrom: + - secretRef: + name: env-secrets + restartPolicy: Never diff --git a/example/v1beta2/backup_restore/backup/role-binding.yaml b/example/v1beta2/backup_restore/backup/role-binding.yaml new file mode 100644 index 000000000..bdab12539 --- /dev/null +++ b/example/v1beta2/backup_restore/backup/role-binding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: backup-role-binding +subjects: + - kind: ServiceAccount + name: backup-service-account +roleRef: + kind: Role + name: modify-pods + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/example/v1beta2/backup_restore/backup/role.yaml b/example/v1beta2/backup_restore/backup/role.yaml new file mode 100644 index 000000000..1ab15a715 --- /dev/null +++ b/example/v1beta2/backup_restore/backup/role.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: modify-pods +rules: + - apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] \ No newline at end of file diff --git a/example/v1beta2/backup_restore/backup/service-account.yaml b/example/v1beta2/backup_restore/backup/service-account.yaml new file mode 100644 index 000000000..d860c2d63 --- /dev/null +++ b/example/v1beta2/backup_restore/backup/service-account.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: backup-service-account \ No newline at end of file diff --git a/example/v1beta2/backup_restore/configmap.yaml b/example/v1beta2/backup_restore/restore/configmap.yaml similarity index 100% rename from example/v1beta2/backup_restore/configmap.yaml rename to example/v1beta2/backup_restore/restore/configmap.yaml diff --git a/example/v1beta2/backup_restore/env-secret.yaml b/example/v1beta2/backup_restore/restore/env-secret.yaml similarity index 79% rename from example/v1beta2/backup_restore/env-secret.yaml rename to example/v1beta2/backup_restore/restore/env-secret.yaml index d0cdea45a..03748498a 100644 --- a/example/v1beta2/backup_restore/env-secret.yaml +++ b/example/v1beta2/backup_restore/restore/env-secret.yaml @@ -10,9 +10,6 @@ stringData: DEFAULT_FILE_PATH: /data/dump.rdb RESTIC_PASSWORD: abc@123 RESTIC_CACHE_DIR: "/tmp/restic_cache" - DEFAULT_REDIS_HOST: redis-cluster-leader-0 - DEFAULT_REDIS_PORT: "6379" - DEFAULT_REDIS_PASSWORD: "" BACKUP_DESTINATION: AWS_S3 AWS_S3_BUCKET: shubham-redis AWS_DEFAULT_REGION: ap-south-1 diff --git a/example/v1beta2/backup_restore/redis-cluster.yaml b/example/v1beta2/backup_restore/restore/redis-cluster.yaml similarity index 87% rename from example/v1beta2/backup_restore/redis-cluster.yaml rename to example/v1beta2/backup_restore/restore/redis-cluster.yaml index 8744c451f..e8f857fa6 100644 --- a/example/v1beta2/backup_restore/redis-cluster.yaml +++ b/example/v1beta2/backup_restore/restore/redis-cluster.yaml @@ -27,7 +27,7 @@ spec: # - name: regcred initContainer: enabled: true - image: shubham192001/restore:latest + image: quay.io/opstree/redis-operator-restore:latest imagePullPolicy: Always command: ["/bin/bash", "-c", "/app/restore.bash"] resources: @@ -63,21 +63,6 @@ spec: secretKeyRef: name: env-secrets key: RESTIC_CACHE_DIR - - name: DEFAULT_REDIS_HOST - valueFrom: - secretKeyRef: - name: env-secrets - key: DEFAULT_REDIS_HOST - - name: DEFAULT_REDIS_PORT - valueFrom: - secretKeyRef: - name: env-secrets - key: DEFAULT_REDIS_PORT - - name: DEFAULT_REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: env-secrets - key: DEFAULT_REDIS_PASSWORD - name: BACKUP_DESTINATION valueFrom: secretKeyRef: @@ -138,6 +123,7 @@ spec: resources: requests: storage: 1Gi + nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: accessModes: ["ReadWriteOnce"] diff --git a/example/v1beta2/redis-cluster.yaml b/example/v1beta2/redis-cluster.yaml index f32a8f4a5..b9881f06d 100644 --- a/example/v1beta2/redis-cluster.yaml +++ b/example/v1beta2/redis-cluster.yaml @@ -11,7 +11,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: @@ -64,6 +64,7 @@ spec: resources: requests: storage: 1Gi + nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: accessModes: ["ReadWriteOnce"] diff --git a/scripts/backup/Dockerfile.kubectlpod b/scripts/backup/Dockerfile.kubectlpod index c465cf548..bb7d43376 100644 --- a/scripts/backup/Dockerfile.kubectlpod +++ b/scripts/backup/Dockerfile.kubectlpod @@ -15,6 +15,11 @@ RUN curl -LO "https://dl.k8s.io/$(cat stable.txt)/bin/linux/amd64/kubectl" RUN chmod +x kubectl RUN mv kubectl /usr/local/bin/ -COPY backup-user.bash /backup -# COPY backup.bash /backup +# COPY backup-user.bash /backup/backup-user.bash +# COPY backup.bash /backup/backup.bash +COPY backup-v0.15.1.bash /backup/backup.bash + +# Make the script executable +RUN chmod +x /backup/backup.bash +# RUN chmod +x /backup/backup-user.bash # COPY env_vars.env /backup diff --git a/scripts/backup/backup-user.bash b/scripts/backup/backup-user.bash index 912c91006..4fb946d07 100644 --- a/scripts/backup/backup-user.bash +++ b/scripts/backup/backup-user.bash @@ -62,10 +62,13 @@ TOTAL_LEADERS=$(kubectl get redisclusters.redis.redis.opstreelabs.in "${CLUSTER_ MASTERS_IP=($(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --no-auth-warning cluster nodes | grep "master" | awk '{print $2}' | cut -d "@" -f1)) check_total_leaders_from_cr() { - # Check if TOTAL_LEADERS is 0 or nil if [[ -z "$TOTAL_LEADERS" || "$TOTAL_LEADERS" == 0 ]]; then - echo "Error: Total number of leader pods is 0" - exit 1 + TOTAL_LEADERS=$(kubectl get redisclusters.redis.redis.opstreelabs.in "${CLUSTER_NAME}" -n "${CLUSTER_NAMESPACE}" -o jsonpath='{.spec.clusterSize}') + # After setting, check again if it's still zero or empty + if [[ -z "$TOTAL_LEADERS" || "$TOTAL_LEADERS" == 0 ]]; then + echo "Error: Total number of leader pods is 0" + exit 1 + fi fi } diff --git a/scripts/backup/backup-v0.15.1.bash b/scripts/backup/backup-v0.15.1.bash new file mode 100644 index 000000000..6d9ac4954 --- /dev/null +++ b/scripts/backup/backup-v0.15.1.bash @@ -0,0 +1,91 @@ +#!/bin/bash + +set -e # Exit on error + +case "$BACKUP_DESTINATION" in + "aws_s3"|"AWS_S3") + RESTIC_REPOSITORY="s3:s3.${AWS_DEFAULT_REGION}.amazonaws.com/${AWS_S3_BUCKET}/${CLUSTER_NAME}-${CLUSTER_NAMESPACE}" + ;; + "azure_blob"|"AZURE_BLOB") + RESTIC_REPOSITORY="azure:${AZURE_CONTAINER}:${CLUSTER_NAME}-${CLUSTER_NAMESPACE}" + ;; + "google_cloud"|"GOOGLE_CLOUD") + RESTIC_REPOSITORY="gs:${GCP_BUCKET}/${CLUSTER_NAME}-${CLUSTER_NAMESPACE}" + ;; + *) + echo "Invalid choice. Exiting." + exit 1 + ;; +esac + + +REDIS_HOST="${CLUSTER_NAME}-leader-0.${CLUSTER_NAME}-leader-headless.${CLUSTER_NAMESPACE}.svc" + +# Check the Total Leader Present in Redis Cluster using cr and redis-cli +TOTAL_LEADERS=$(kubectl get redisclusters.redis.redis.opstreelabs.in "${CLUSTER_NAME}" -n "${CLUSTER_NAMESPACE}" -o jsonpath='{.spec.redisLeader.replicas}') +MASTERS_IP=($(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --no-auth-warning cluster nodes | grep "master" | awk '{print $2}' | cut -d "@" -f1)) + +check_total_leaders_from_cr() { + if [[ -z "$TOTAL_LEADERS" || "$TOTAL_LEADERS" == 0 ]]; then + TOTAL_LEADERS=$(kubectl get redisclusters.redis.redis.opstreelabs.in "${CLUSTER_NAME}" -n "${CLUSTER_NAMESPACE}" -o jsonpath='{.spec.clusterSize}') + # After setting, check again if it's still zero or empty + if [[ -z "$TOTAL_LEADERS" || "$TOTAL_LEADERS" == 0 ]]; then + echo "Error: Total number of leader pods is 0" + exit 1 + fi + fi +} + +check_total_masters_from_redis() { + # IF the total master by the redis custom-resource and the redis-cli doesn't match throw an error + if [[ "${TOTAL_LEADERS}" -ne "${#MASTERS_IP[@]}" ]]; then + echo "Error: Total number of leaders (${TOTAL_LEADERS}) is not equal to total number of masters (${#MASTERS_IP[@]})!" + exit 1 + fi +} + + +initialize_repository() { + # To set the password of the repo you must pass it the env Variable RESTIC_PASSWORD + if ! restic -r "$RESTIC_REPOSITORY" snapshots &>/dev/null ; then + echo "Initializing restic repository..." + restic init --repo "$RESTIC_REPOSITORY" + else + echo "Restic repository already initialized." + fi +} + + +perform_redis_backup(){ + # Start performing backup + for ((i = 0; i < TOTAL_LEADERS; i++)) + do + # Get the name of the Redis pod + POD="${CLUSTER_NAME}-leader-${i}" + + # Get the IP address and port of the Redis instance + IP_PORT="${MASTERS_IP[${i}]}" + + # Extract the IP address and port from the IP_PORT variable + IP=$(echo "$IP_PORT" | cut -d ':' -f 1) + PORT=$(echo "$IP_PORT" | cut -d ':' -f 2) + + echo "Performing backup on Redis instance at $IP:$PORT" + + # Copy the file from the Redis instance to a local file + redis-cli -h "$IP" -p "$PORT" -a "$REDIS_PASSWORD" --rdb "/tmp/${POD}.rdb" + + # Upload the file to the selected backup destination using restic + restic -r "$RESTIC_REPOSITORY" backup "/tmp/${POD}.rdb" --host "${CLUSTER_NAME}_${CLUSTER_NAMESPACE}" --tag "${POD}" --tag "redis" + + # Clean up the local file + rm "/tmp/${POD}.rdb" + done +} + + +check_total_leaders_from_cr +check_total_masters_from_redis +initialize_repository +perform_redis_backup +echo "Backup completed successfully." diff --git a/scripts/backup/backup.bash b/scripts/backup/backup.bash index 96b9e6541..5e70ddc7e 100644 --- a/scripts/backup/backup.bash +++ b/scripts/backup/backup.bash @@ -23,7 +23,7 @@ REDIS_HOST="${CLUSTER_NAME}-leader-0.${CLUSTER_NAME}-leader-headless.${CLUSTER_N # Check the Total Leader Present in Redis Cluster using cr and redis-cli TOTAL_LEADERS=$(kubectl get redisclusters.redis.redis.opstreelabs.in "${CLUSTER_NAME}" -n "${CLUSTER_NAMESPACE}" -o jsonpath='{.spec.redisLeader.replicas}') -MASTERS_IP=$(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" cluster nodes --no-auth-warning | grep "master" | awk '{print $2}' | cut -d "@" -f1) +MASTERS_IP=($(redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDIS_PASSWORD" --no-auth-warning cluster nodes | grep "master" | awk '{print $2}' | cut -d "@" -f1)) check_total_leaders_from_cr() { # Check if TOTAL_LEADERS is 0 or nil @@ -33,11 +33,14 @@ check_total_leaders_from_cr() { fi } -check_total_masters_from_redis() { - # IF the total master by the redis custom-resource and the redis-cli doesn't match throw an error - if [[ "${TOTAL_LEADERS}" -ne "${#MASTERS_IP[@]}" ]]; then - echo "Error: Total number of leaders (${TOTAL_LEADERS}) is not equal to total number of masters (${#MASTERS_IP[@]})!" - exit 1 +check_total_leaders_from_cr() { + if [[ -z "$TOTAL_LEADERS" || "$TOTAL_LEADERS" == 0 ]]; then + TOTAL_LEADERS=$(kubectl get redisclusters.redis.redis.opstreelabs.in "${CLUSTER_NAME}" -n "${CLUSTER_NAMESPACE}" -o jsonpath='{.spec.clusterSize}') + # After setting, check again if it's still zero or empty + if [[ -z "$TOTAL_LEADERS" || "$TOTAL_LEADERS" == 0 ]]; then + echo "Error: Total number of leader pods is 0" + exit 1 + fi fi } @@ -73,7 +76,7 @@ perform_redis_backup(){ redis-cli -h "$IP" -p "$PORT" -a "$REDIS_PASSWORD" --rdb "/tmp/${POD}.rdb" # Upload the file to the selected backup destination using restic - restic -r "$RESTIC_REPOSITORY" backup "/tmp/${POD}.rdb" --host"${CLUSTER_NAME}_${CLUSTER_NAMESPACE}" --tag "${POD}" --tag "redis" + restic -r "$RESTIC_REPOSITORY" backup "/tmp/${POD}.rdb" --host "${CLUSTER_NAME}_${CLUSTER_NAMESPACE}" --tag "${POD}" --tag "redis" # Clean up the local file rm "/tmp/${POD}.rdb" diff --git a/scripts/backup/env_vars.env b/scripts/backup/env_vars.env index d8ec3829a..110f775f7 100644 --- a/scripts/backup/env_vars.env +++ b/scripts/backup/env_vars.env @@ -7,14 +7,13 @@ export CLUSTER_NAMESPACE="default" # Restic export DEFAULT_FILE_PATH="/data/dump.rdb" export RESTIC_PASSWORD="abc@123" +export RESTIC_CACHE_DIR=/tmp/restic_cache # Redis -export DEFAULT_REDIS_HOST="redis-cluster-leader-0" export DEFAULT_REDIS_PORT="6379" export DEFAULT_REDIS_PASSWORD="" # Backup destination - export BACKUP_DESTINATION=AWS_S3 # AWS diff --git a/scripts/restore/env_vars.env b/scripts/restore/env_vars.env index d8ec3829a..2234e1f14 100644 --- a/scripts/restore/env_vars.env +++ b/scripts/restore/env_vars.env @@ -7,9 +7,9 @@ export CLUSTER_NAMESPACE="default" # Restic export DEFAULT_FILE_PATH="/data/dump.rdb" export RESTIC_PASSWORD="abc@123" +export RESTIC_CACHE_DIR=/tmp/restic_cache # Redis -export DEFAULT_REDIS_HOST="redis-cluster-leader-0" export DEFAULT_REDIS_PORT="6379" export DEFAULT_REDIS_PASSWORD="" From e39e1d1b336a57ccfd4230f2825010c9c903089e Mon Sep 17 00:00:00 2001 From: syedsadath-17 <90619459+sadath-12@users.noreply.github.com> Date: Sat, 16 Sep 2023 18:14:10 +0530 Subject: [PATCH 008/203] [Feature] : Added Custom EnvVars support (#631) * Feature: Added Custom EnvVars support Signed-off-by: syedsadath-17 <90619459+sadath-12@users.noreply.github.com> * Formatted Using fmt Signed-off-by: syedsadath-17 <90619459+sadath-12@users.noreply.github.com> * fixes on pr Signed-off-by: Shubham Gupta * fixes on env Signed-off-by: Shubham Gupta * push env Vars template Signed-off-by: Shubham Gupta --------- Signed-off-by: syedsadath-17 <90619459+sadath-12@users.noreply.github.com> Signed-off-by: Shubham Gupta Co-authored-by: Shubham Gupta --- api/v1beta2/redis_types.go | 13 +++-- api/v1beta2/rediscluster_types.go | 1 + api/v1beta2/redisreplication_types.go | 13 +++-- api/v1beta2/redissentinel_types.go | 11 ++-- example/v1beta2/env_vars/redis-cluster.yaml | 48 ++++++++++++++++ .../v1beta2/env_vars/redis-replication.yaml | 40 +++++++++++++ example/v1beta2/env_vars/redis-sentinel.yaml | 30 ++++++++++ .../v1beta2/env_vars/redis-standalone.yaml | 56 +++++++++++++++++++ example/v1beta2/redis-cluster.yaml | 5 ++ k8sutils/redis-cluster.go | 3 + k8sutils/redis-replication.go | 4 +- k8sutils/redis-sentinel.go | 3 + k8sutils/redis-standalone.go | 3 + k8sutils/statefulset.go | 12 +++- 14 files changed, 223 insertions(+), 19 deletions(-) create mode 100644 example/v1beta2/env_vars/redis-cluster.yaml create mode 100644 example/v1beta2/env_vars/redis-replication.yaml create mode 100644 example/v1beta2/env_vars/redis-sentinel.yaml create mode 100644 example/v1beta2/env_vars/redis-standalone.yaml diff --git a/api/v1beta2/redis_types.go b/api/v1beta2/redis_types.go index f8a05fa4c..091cb19ea 100644 --- a/api/v1beta2/redis_types.go +++ b/api/v1beta2/redis_types.go @@ -41,11 +41,12 @@ type RedisSpec struct { // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - InitContainer *InitContainer `json:"initContainer,omitempty"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` + InitContainer *InitContainer `json:"initContainer,omitempty"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } // RedisStatus defines the observed state of Redis @@ -54,7 +55,7 @@ type RedisStatus struct { // +kubebuilder:object:root=true // +kubebuilder:subresource:status -//+kubebuilder:storageversion +// +kubebuilder:storageversion // Redis is the Schema for the redis API type Redis struct { diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index 69e0e5ff9..913e4f2a1 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -44,6 +44,7 @@ type RedisClusterSpec struct { Sidecars *[]Sidecar `json:"sidecars,omitempty"` ServiceAccountName *string `json:"serviceAccountName,omitempty"` PersistenceEnabled *bool `json:"persistenceEnabled,omitempty"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } func (cr *RedisClusterSpec) GetReplicaCounts(t string) int32 { diff --git a/api/v1beta2/redisreplication_types.go b/api/v1beta2/redisreplication_types.go index b915bc227..cb04c169d 100644 --- a/api/v1beta2/redisreplication_types.go +++ b/api/v1beta2/redisreplication_types.go @@ -22,11 +22,12 @@ type RedisReplicationSpec struct { // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - InitContainer *InitContainer `json:"initContainer,omitempty"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` + InitContainer *InitContainer `json:"initContainer,omitempty"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { @@ -40,7 +41,7 @@ type RedisReplicationStatus struct { // +kubebuilder:object:root=true // +kubebuilder:subresource:status -//+kubebuilder:storageversion +// +kubebuilder:storageversion // Redis is the Schema for the redis API type RedisReplication struct { diff --git a/api/v1beta2/redissentinel_types.go b/api/v1beta2/redissentinel_types.go index e899e581c..b40ee6e10 100644 --- a/api/v1beta2/redissentinel_types.go +++ b/api/v1beta2/redissentinel_types.go @@ -24,11 +24,12 @@ type RedisSentinelSpec struct { // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - InitContainer *InitContainer `json:"initContainer,omitempty"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` + InitContainer *InitContainer `json:"initContainer,omitempty"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } func (cr *RedisSentinelSpec) GetSentinelCounts(t string) int32 { diff --git a/example/v1beta2/env_vars/redis-cluster.yaml b/example/v1beta2/env_vars/redis-cluster.yaml new file mode 100644 index 000000000..44a420efb --- /dev/null +++ b/example/v1beta2/env_vars/redis-cluster.yaml @@ -0,0 +1,48 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.11 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + diff --git a/example/v1beta2/env_vars/redis-replication.yaml b/example/v1beta2/env_vars/redis-replication.yaml new file mode 100644 index 000000000..10fd3a13b --- /dev/null +++ b/example/v1beta2/env_vars/redis-replication.yaml @@ -0,0 +1,40 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + # redisConfig: + # additionalRedisConfig: redis-external-config + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.11 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + # imagePullSecrets: + # - name: regcred + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/example/v1beta2/env_vars/redis-sentinel.yaml b/example/v1beta2/env_vars/redis-sentinel.yaml new file mode 100644 index 000000000..48bea21cc --- /dev/null +++ b/example/v1beta2/env_vars/redis-sentinel.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + pdb: + enabled: false + minAvailable: 1 + redisSentinelConfig: + redisReplicationName : redis-replication + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:v7.0.7 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" \ No newline at end of file diff --git a/example/v1beta2/env_vars/redis-standalone.yaml b/example/v1beta2/env_vars/redis-standalone.yaml new file mode 100644 index 000000000..cbe0fbdf2 --- /dev/null +++ b/example/v1beta2/env_vars/redis-standalone.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone +spec: + # redisConfig: + # additionalRedisConfig: redis-external-config + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.11 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # nodeSelector: + # kubernetes.io/hostname: minikube + # podSecurityContext: {} + # priorityClassName: + # affinity: + # Tolerations: [] diff --git a/example/v1beta2/redis-cluster.yaml b/example/v1beta2/redis-cluster.yaml index b9881f06d..8c232efee 100644 --- a/example/v1beta2/redis-cluster.yaml +++ b/example/v1beta2/redis-cluster.yaml @@ -20,6 +20,11 @@ spec: limits: cpu: 101m memory: 128Mi + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" # redisSecret: # name: redis-secret # key: password diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index b17ea6b97..f9c44e96e 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -101,6 +101,9 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: securityContext, } + if cr.Spec.EnvVars != nil { + containerProp.EnvVars = cr.Spec.EnvVars + } if cr.Spec.Storage != nil { containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 4d8c4234f..100f63cb0 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -109,7 +109,9 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, } - + if cr.Spec.EnvVars != nil { + containerProp.EnvVars = cr.Spec.EnvVars + } if cr.Spec.Storage != nil { containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 1b5e21880..f05aea39c 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -153,6 +153,9 @@ func generateRedisSentinelContainerParams(cr *redisv1beta2.RedisSentinel, readin SecurityContext: cr.Spec.SecurityContext, AdditionalEnvVariable: getSentinelEnvVariable(cr), } + if cr.Spec.EnvVars != nil { + containerProp.EnvVars = cr.Spec.EnvVars + } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { containerProp.EnabledPassword = &trueProperty containerProp.SecretName = cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 71e3ea56e..f044fb432 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -115,6 +115,9 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar SecurityContext: cr.Spec.SecurityContext, } + if cr.Spec.EnvVars != nil { + containerProp.EnvVars = cr.Spec.EnvVars + } if cr.Spec.Storage != nil { containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index f086e5424..373791e33 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -70,6 +70,7 @@ type containerParameters struct { AdditionalEnvVariable *[]corev1.EnvVar AdditionalVolume []corev1.Volume AdditionalMountPath []corev1.VolumeMount + EnvVars *[]corev1.EnvVar } type initContainerParameters struct { @@ -351,6 +352,7 @@ func generateContainerDef(name string, containerParams containerParameters, clus containerParams.RedisExporterEnv, containerParams.TLSConfig, containerParams.ACLConfig, + containerParams.EnvVars, ), ReadinessProbe: getProbeInfo(containerParams.ReadinessProbe), LivenessProbe: getProbeInfo(containerParams.LivenessProbe), @@ -472,6 +474,7 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { params.RedisExporterEnv, params.TLSConfig, params.ACLConfig, + params.EnvVars, ), VolumeMounts: getVolumeMount("", nil, false, false, nil, params.AdditionalMountPath, params.TLSConfig, params.ACLConfig), // We need/want the tls-certs but we DON'T need the PVC (if one is available) Ports: []corev1.ContainerPort{ @@ -554,7 +557,9 @@ func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { } // getEnvironmentVariables returns all the required Environment Variables -func getEnvironmentVariables(role string, enabledMetric bool, enabledPassword *bool, secretName *string, secretKey *string, persistenceEnabled *bool, exporterEnvVar *[]corev1.EnvVar, tlsConfig *redisv1beta2.TLSConfig, aclConfig *redisv1beta2.ACLConfig) []corev1.EnvVar { +func getEnvironmentVariables(role string, enabledMetric bool, enabledPassword *bool, secretName *string, + secretKey *string, persistenceEnabled *bool, exporterEnvVar *[]corev1.EnvVar, tlsConfig *redisv1beta2.TLSConfig, + aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar) []corev1.EnvVar { envVars := []corev1.EnvVar{ {Name: "SERVER_MODE", Value: role}, {Name: "SETUP_MODE", Value: role}, @@ -621,6 +626,11 @@ func getEnvironmentVariables(role string, enabledMetric bool, enabledPassword *b if exporterEnvVar != nil { envVars = append(envVars, *exporterEnvVar...) } + + if envVar != nil { + envVars = append(envVars, *envVar...) + } + sort.SliceStable(envVars, func(i, j int) bool { return envVars[i].Name < envVars[j].Name }) From fff36a7d80626be389a77977e384de1d095ecf60 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 16 Sep 2023 18:15:02 +0530 Subject: [PATCH 009/203] update-image-manifest (#632) Signed-off-by: Shubham Gupta --- example/v1beta2/acl_config/replication.yaml | 2 +- example/v1beta2/additional_config/clusterd.yaml | 2 +- example/v1beta2/additional_config/replication.yaml | 2 +- example/v1beta2/additional_config/standalone.yaml | 2 +- example/v1beta2/advance_config/clusterd.yaml | 2 +- example/v1beta2/advance_config/standalone.yaml | 2 +- example/v1beta2/affinity/clusterd.yaml | 2 +- example/v1beta2/affinity/replication.yaml | 2 +- example/v1beta2/affinity/standalone.yaml | 2 +- example/v1beta2/disruption_budget/clusterd.yaml | 2 +- example/v1beta2/external_service/clusterd.yaml | 2 +- example/v1beta2/external_service/replication.yaml | 2 +- example/v1beta2/external_service/standalone.yaml | 2 +- example/v1beta2/node-selector/clusterd.yaml | 2 +- example/v1beta2/node-selector/replication.yaml | 2 +- example/v1beta2/node-selector/standalone.yaml | 2 +- example/v1beta2/password_protected/clusterd.yaml | 2 +- example/v1beta2/password_protected/replication.yaml | 2 +- example/v1beta2/password_protected/standalone.yaml | 2 +- example/v1beta2/private_registry/clusterd.yaml | 2 +- example/v1beta2/private_registry/replication.yaml | 2 +- example/v1beta2/private_registry/standalone.yaml | 2 +- example/v1beta2/probes/clusterd.yaml | 2 +- example/v1beta2/probes/replication.yaml | 2 +- example/v1beta2/probes/standalone.yaml | 2 +- example/v1beta2/recreate-statefulset/clusterd.yaml | 2 +- example/v1beta2/recreate-statefulset/replication.yaml | 2 +- example/v1beta2/recreate-statefulset/standalone.yaml | 2 +- example/v1beta2/redis-replication.yaml | 2 +- example/v1beta2/redis-standalone.yaml | 2 +- example/v1beta2/redis_monitoring/clusterd.yaml | 2 +- example/v1beta2/redis_monitoring/replication.yaml | 2 +- example/v1beta2/redis_monitoring/standalone.yaml | 2 +- example/v1beta2/sidecar_features/sidecar.yaml | 2 +- example/v1beta2/tls_enabled/redis-cluster.yaml | 2 +- example/v1beta2/tls_enabled/redis-replication.yaml | 2 +- example/v1beta2/tls_enabled/redis-standalone.yaml | 2 +- example/v1beta2/tolerations/clusterd.yaml | 2 +- example/v1beta2/tolerations/replication.yaml | 2 +- example/v1beta2/tolerations/standalone.yaml | 2 +- example/v1beta2/upgrade-strategy/clusterd.yaml | 2 +- example/v1beta2/upgrade-strategy/replication.yaml | 2 +- example/v1beta2/upgrade-strategy/standalone.yaml | 2 +- example/v1beta2/volume_mount/redis-cluster.yaml | 2 +- example/v1beta2/volume_mount/redis-replication.yaml | 2 +- example/v1beta2/volume_mount/redis-standalone.yaml | 2 +- 46 files changed, 46 insertions(+), 46 deletions(-) diff --git a/example/v1beta2/acl_config/replication.yaml b/example/v1beta2/acl_config/replication.yaml index fbc8d0ccc..6d754c26d 100644 --- a/example/v1beta2/acl_config/replication.yaml +++ b/example/v1beta2/acl_config/replication.yaml @@ -11,7 +11,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/additional_config/clusterd.yaml b/example/v1beta2/additional_config/clusterd.yaml index fa1f21078..bb8d825ad 100644 --- a/example/v1beta2/additional_config/clusterd.yaml +++ b/example/v1beta2/additional_config/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/additional_config/replication.yaml b/example/v1beta2/additional_config/replication.yaml index 1f1aad416..001882dbb 100644 --- a/example/v1beta2/additional_config/replication.yaml +++ b/example/v1beta2/additional_config/replication.yaml @@ -8,7 +8,7 @@ spec: redisConfig: additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/additional_config/standalone.yaml b/example/v1beta2/additional_config/standalone.yaml index 2a1cacb70..6458e3631 100644 --- a/example/v1beta2/additional_config/standalone.yaml +++ b/example/v1beta2/additional_config/standalone.yaml @@ -7,7 +7,7 @@ spec: redisConfig: additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/advance_config/clusterd.yaml b/example/v1beta2/advance_config/clusterd.yaml index 8390e5589..9d652ddae 100644 --- a/example/v1beta2/advance_config/clusterd.yaml +++ b/example/v1beta2/advance_config/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 resources: requests: cpu: 101m diff --git a/example/v1beta2/advance_config/standalone.yaml b/example/v1beta2/advance_config/standalone.yaml index 88fb2ec4a..3505c18e2 100644 --- a/example/v1beta2/advance_config/standalone.yaml +++ b/example/v1beta2/advance_config/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/affinity/clusterd.yaml b/example/v1beta2/affinity/clusterd.yaml index d1c555efe..db3845403 100644 --- a/example/v1beta2/affinity/clusterd.yaml +++ b/example/v1beta2/affinity/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/affinity/replication.yaml b/example/v1beta2/affinity/replication.yaml index 82da8e355..f7a102190 100644 --- a/example/v1beta2/affinity/replication.yaml +++ b/example/v1beta2/affinity/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/affinity/standalone.yaml b/example/v1beta2/affinity/standalone.yaml index 22b6c39a5..910bc95d8 100644 --- a/example/v1beta2/affinity/standalone.yaml +++ b/example/v1beta2/affinity/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/disruption_budget/clusterd.yaml b/example/v1beta2/disruption_budget/clusterd.yaml index d58ba0db2..97720f790 100644 --- a/example/v1beta2/disruption_budget/clusterd.yaml +++ b/example/v1beta2/disruption_budget/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/external_service/clusterd.yaml b/example/v1beta2/external_service/clusterd.yaml index fb7da8bf8..c8036c974 100644 --- a/example/v1beta2/external_service/clusterd.yaml +++ b/example/v1beta2/external_service/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/external_service/replication.yaml b/example/v1beta2/external_service/replication.yaml index d8fa554e7..1ca1f9d71 100644 --- a/example/v1beta2/external_service/replication.yaml +++ b/example/v1beta2/external_service/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/external_service/standalone.yaml b/example/v1beta2/external_service/standalone.yaml index 2eb1d3ab6..d51fdf6e0 100644 --- a/example/v1beta2/external_service/standalone.yaml +++ b/example/v1beta2/external_service/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/node-selector/clusterd.yaml b/example/v1beta2/node-selector/clusterd.yaml index ff4cd4b5c..e4f0b9b89 100644 --- a/example/v1beta2/node-selector/clusterd.yaml +++ b/example/v1beta2/node-selector/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/node-selector/replication.yaml b/example/v1beta2/node-selector/replication.yaml index 5d9c08cb6..1e387396a 100644 --- a/example/v1beta2/node-selector/replication.yaml +++ b/example/v1beta2/node-selector/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/node-selector/standalone.yaml b/example/v1beta2/node-selector/standalone.yaml index 16c5b73cc..1213e99f6 100644 --- a/example/v1beta2/node-selector/standalone.yaml +++ b/example/v1beta2/node-selector/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/password_protected/clusterd.yaml b/example/v1beta2/password_protected/clusterd.yaml index 9a1c54de3..4d1068508 100644 --- a/example/v1beta2/password_protected/clusterd.yaml +++ b/example/v1beta2/password_protected/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisSecret: name: redis-secret diff --git a/example/v1beta2/password_protected/replication.yaml b/example/v1beta2/password_protected/replication.yaml index 074d8c2ff..6491b0f75 100644 --- a/example/v1beta2/password_protected/replication.yaml +++ b/example/v1beta2/password_protected/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisSecret: name: redis-secret diff --git a/example/v1beta2/password_protected/standalone.yaml b/example/v1beta2/password_protected/standalone.yaml index 5c223cc5f..9796a3a5d 100644 --- a/example/v1beta2/password_protected/standalone.yaml +++ b/example/v1beta2/password_protected/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisSecret: name: redis-secret diff --git a/example/v1beta2/private_registry/clusterd.yaml b/example/v1beta2/private_registry/clusterd.yaml index da1430ab4..27cdec186 100644 --- a/example/v1beta2/private_registry/clusterd.yaml +++ b/example/v1beta2/private_registry/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent imagePullSecrets: - name: regcred diff --git a/example/v1beta2/private_registry/replication.yaml b/example/v1beta2/private_registry/replication.yaml index 03defed0a..9b9876d29 100644 --- a/example/v1beta2/private_registry/replication.yaml +++ b/example/v1beta2/private_registry/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent imagePullSecrets: - name: regcred diff --git a/example/v1beta2/private_registry/standalone.yaml b/example/v1beta2/private_registry/standalone.yaml index 35ae6b94d..956dc1944 100644 --- a/example/v1beta2/private_registry/standalone.yaml +++ b/example/v1beta2/private_registry/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent imagePullSecrets: - name: regcred diff --git a/example/v1beta2/probes/clusterd.yaml b/example/v1beta2/probes/clusterd.yaml index ff4741c98..0699a7ade 100644 --- a/example/v1beta2/probes/clusterd.yaml +++ b/example/v1beta2/probes/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta2/probes/replication.yaml b/example/v1beta2/probes/replication.yaml index e0b525882..7ea3826e9 100644 --- a/example/v1beta2/probes/replication.yaml +++ b/example/v1beta2/probes/replication.yaml @@ -9,7 +9,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/probes/standalone.yaml b/example/v1beta2/probes/standalone.yaml index 632c18d53..a03d1e4cd 100644 --- a/example/v1beta2/probes/standalone.yaml +++ b/example/v1beta2/probes/standalone.yaml @@ -8,7 +8,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/recreate-statefulset/clusterd.yaml b/example/v1beta2/recreate-statefulset/clusterd.yaml index 028271cab..6f361694f 100644 --- a/example/v1beta2/recreate-statefulset/clusterd.yaml +++ b/example/v1beta2/recreate-statefulset/clusterd.yaml @@ -13,7 +13,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/recreate-statefulset/replication.yaml b/example/v1beta2/recreate-statefulset/replication.yaml index 127833fc7..20c2bcfea 100644 --- a/example/v1beta2/recreate-statefulset/replication.yaml +++ b/example/v1beta2/recreate-statefulset/replication.yaml @@ -8,7 +8,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/recreate-statefulset/standalone.yaml b/example/v1beta2/recreate-statefulset/standalone.yaml index 8ff47e8ab..bacd0b19c 100644 --- a/example/v1beta2/recreate-statefulset/standalone.yaml +++ b/example/v1beta2/recreate-statefulset/standalone.yaml @@ -7,7 +7,7 @@ metadata: redis.opstreelabs.in/recreate-statefulset: "true" spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/redis-replication.yaml b/example/v1beta2/redis-replication.yaml index aab7d798c..73a69b9e2 100644 --- a/example/v1beta2/redis-replication.yaml +++ b/example/v1beta2/redis-replication.yaml @@ -11,7 +11,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis-standalone.yaml b/example/v1beta2/redis-standalone.yaml index f2aa1aa70..567e7f919 100644 --- a/example/v1beta2/redis-standalone.yaml +++ b/example/v1beta2/redis-standalone.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis_monitoring/clusterd.yaml b/example/v1beta2/redis_monitoring/clusterd.yaml index 7a8a08276..bfb6b3894 100644 --- a/example/v1beta2/redis_monitoring/clusterd.yaml +++ b/example/v1beta2/redis_monitoring/clusterd.yaml @@ -13,7 +13,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: Always redisExporter: enabled: true diff --git a/example/v1beta2/redis_monitoring/replication.yaml b/example/v1beta2/redis_monitoring/replication.yaml index 02b9bc498..17c09b8ce 100644 --- a/example/v1beta2/redis_monitoring/replication.yaml +++ b/example/v1beta2/redis_monitoring/replication.yaml @@ -8,7 +8,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/redis_monitoring/standalone.yaml b/example/v1beta2/redis_monitoring/standalone.yaml index 1753c2558..9c772fbe2 100644 --- a/example/v1beta2/redis_monitoring/standalone.yaml +++ b/example/v1beta2/redis_monitoring/standalone.yaml @@ -7,7 +7,7 @@ metadata: # redis.opstreelabs.in/skip-reconcile: "true" spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/sidecar_features/sidecar.yaml b/example/v1beta2/sidecar_features/sidecar.yaml index eb69bd8fc..ac6c58347 100644 --- a/example/v1beta2/sidecar_features/sidecar.yaml +++ b/example/v1beta2/sidecar_features/sidecar.yaml @@ -7,7 +7,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tls_enabled/redis-cluster.yaml b/example/v1beta2/tls_enabled/redis-cluster.yaml index 9da46d137..7c2f1f138 100644 --- a/example/v1beta2/tls_enabled/redis-cluster.yaml +++ b/example/v1beta2/tls_enabled/redis-cluster.yaml @@ -18,7 +18,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tls_enabled/redis-replication.yaml b/example/v1beta2/tls_enabled/redis-replication.yaml index 2496a896f..563709da2 100644 --- a/example/v1beta2/tls_enabled/redis-replication.yaml +++ b/example/v1beta2/tls_enabled/redis-replication.yaml @@ -16,7 +16,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tls_enabled/redis-standalone.yaml b/example/v1beta2/tls_enabled/redis-standalone.yaml index 800cda7f9..6176765a8 100644 --- a/example/v1beta2/tls_enabled/redis-standalone.yaml +++ b/example/v1beta2/tls_enabled/redis-standalone.yaml @@ -15,7 +15,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tolerations/clusterd.yaml b/example/v1beta2/tolerations/clusterd.yaml index a4de514a8..02d076bfc 100644 --- a/example/v1beta2/tolerations/clusterd.yaml +++ b/example/v1beta2/tolerations/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/tolerations/replication.yaml b/example/v1beta2/tolerations/replication.yaml index 62789ae90..d99fc289a 100644 --- a/example/v1beta2/tolerations/replication.yaml +++ b/example/v1beta2/tolerations/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/tolerations/standalone.yaml b/example/v1beta2/tolerations/standalone.yaml index 2fe7eff94..36c2fbf19 100644 --- a/example/v1beta2/tolerations/standalone.yaml +++ b/example/v1beta2/tolerations/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/upgrade-strategy/clusterd.yaml b/example/v1beta2/upgrade-strategy/clusterd.yaml index 81dd36d73..e6614dd16 100644 --- a/example/v1beta2/upgrade-strategy/clusterd.yaml +++ b/example/v1beta2/upgrade-strategy/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent updateStrategy: type: OnDelete diff --git a/example/v1beta2/upgrade-strategy/replication.yaml b/example/v1beta2/upgrade-strategy/replication.yaml index 5b8537785..2a9ad31e7 100644 --- a/example/v1beta2/upgrade-strategy/replication.yaml +++ b/example/v1beta2/upgrade-strategy/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent type: OnDelete # type: RollingUpdate diff --git a/example/v1beta2/upgrade-strategy/standalone.yaml b/example/v1beta2/upgrade-strategy/standalone.yaml index ca413bb57..f01895b2f 100644 --- a/example/v1beta2/upgrade-strategy/standalone.yaml +++ b/example/v1beta2/upgrade-strategy/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent updateStrategy: type: OnDelete diff --git a/example/v1beta2/volume_mount/redis-cluster.yaml b/example/v1beta2/volume_mount/redis-cluster.yaml index 50c8af66e..d4d8d8d2b 100644 --- a/example/v1beta2/volume_mount/redis-cluster.yaml +++ b/example/v1beta2/volume_mount/redis-cluster.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/volume_mount/redis-replication.yaml b/example/v1beta2/volume_mount/redis-replication.yaml index 8adf9e300..c107a0f94 100644 --- a/example/v1beta2/volume_mount/redis-replication.yaml +++ b/example/v1beta2/volume_mount/redis-replication.yaml @@ -7,7 +7,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/volume_mount/redis-standalone.yaml b/example/v1beta2/volume_mount/redis-standalone.yaml index e3257876d..421dab3d7 100644 --- a/example/v1beta2/volume_mount/redis-standalone.yaml +++ b/example/v1beta2/volume_mount/redis-standalone.yaml @@ -6,7 +6,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.5 + image: quay.io/opstree/redis:v7.0.11 imagePullPolicy: IfNotPresent resources: requests: From 4395ff63118d2f6ec6d1d21df914bef9c3afc9f8 Mon Sep 17 00:00:00 2001 From: jiuker <2818723467@qq.com> Date: Sat, 16 Sep 2023 21:45:30 +0800 Subject: [PATCH 010/203] fix:resize cluster's pvc with wrong label (#562) Signed-off-by: guozhi.li Co-authored-by: guozhi.li --- k8sutils/statefulset.go | 1 - 1 file changed, 1 deletion(-) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 373791e33..9593b5369 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -153,7 +153,6 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St map[string]string{ "app": storedStateful.Name, "app.kubernetes.io/component": "redis", - "app.kubernetes.io/name": storedStateful.Name, }, ), } From 97eec58762c68043483d366e55935ca0e0255416 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 16 Sep 2023 21:06:31 +0530 Subject: [PATCH 011/203] remove unwanted code from workflow (#634) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 83 ++------------------------- 1 file changed, 4 insertions(+), 79 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 8cdfab6ba..1cee0d163 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -9,7 +9,7 @@ on: env: ApplicationName: redis-operator QuayImageName: quay.io/opstree/redis-operator - AppVersion: "v0.15.0" + AppVersion: "v0.15.1" DOCKERFILE_PATH: '**/Dockerfile' jobs: @@ -30,69 +30,11 @@ jobs: username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.ACCESS_TOKEN }} - build_arm64: - needs: setup - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - name: Check existing AppVersion - id: check_version_arm64 - run: | - EXISTS=$(curl -s https://quay.io/api/v1/repository/${{ env.QuayImageName }}/tag/?specificTag=${{ env.AppVersion }}-arm64 | jq '.tags | length') - echo "::set-output name=exists::$EXISTS" - - - name: Build and push arm64 image - if: steps.check_version_arm64.outputs.exists == '0' - uses: docker/build-push-action@v2 - with: - context: . - file: ${{ env.DOCKERFILE_PATH }} - platforms: linux/arm64 - push: true - tags: ${{ env.QuayImageName }}:${{ env.AppVersion }}-arm64 - - build_amd64: - needs: setup - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - name: Check existing AppVersion - id: check_version_amd64 - run: | - EXISTS=$(curl -s https://quay.io/api/v1/repository/${{ env.QuayImageName }}/tag/?specificTag=${{ env.AppVersion }}-amd64 | jq '.tags | length') - echo "::set-output name=exists::$EXISTS" - - - name: Build and push amd64 image - if: steps.check_version_amd64.outputs.exists == '0' - uses: docker/build-push-action@v2 - with: - context: . - file: ${{ env.DOCKERFILE_PATH }} - platforms: linux/amd64 - push: true - tags: ${{ env.QuayImageName }}:${{ env.AppVersion }}-amd64 - build_multi_arch: needs: setup if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - - name: Check existing AppVersion - id: check_version_multi_arch - run: | - EXISTS=$(curl -s https://quay.io/api/v1/repository/${{ env.QuayImageName }}/tag/?specificTag=${{ env.AppVersion }} | jq '.tags | length') - echo "::set-output name=exists::$EXISTS" - - - name: Build and push multi-arch image - if: steps.check_version_multi_arch.outputs.exists == '0' - uses: docker/build-push-action@v2 - with: - context: . - file: ${{ env.DOCKERFILE_PATH }} - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.QuayImageName }}:${{ env.AppVersion }} - - name: Build and push multi-arch latest image uses: docker/build-push-action@v2 with: @@ -100,34 +42,17 @@ jobs: file: ${{ env.DOCKERFILE_PATH }} platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.QuayImageName }}:latest + tags: ${{ env.QuayImageName }}:{{ env.AppVersion }}, ${{ env.QuayImageName }}:latest trivy_scan: - needs: [build_arm64, build_amd64, build_multi_arch] + needs: [build_multi_arch] runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Run Trivy vulnerability scanner for arm64 image uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.QuayImageName }}:${{ env.AppVersion }}-arm64 - format: 'template' - template: '@/contrib/sarif.tpl' - output: 'trivy-results-arm64.sarif' - exit-code: '1' - ignore-unfixed: true - severity: 'CRITICAL,HIGH' - - name: Run Trivy vulnerability scanner for amd64 image - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.QuayImageName }}:${{ env.AppVersion }}-amd64 - format: 'template' - template: '@/contrib/sarif.tpl' - output: 'trivy-results-amd64.sarif' - exit-code: '1' - ignore-unfixed: true - severity: 'CRITICAL,HIGH' + - name: Run Trivy vulnerability scanner for multi-arch image uses: aquasecurity/trivy-action@master with: From 871c730321209e0607220a48e0c3fce3138e5a69 Mon Sep 17 00:00:00 2001 From: Akshay Kumar <114390890+Akshaykumar05@users.noreply.github.com> Date: Mon, 18 Sep 2023 11:17:59 +0530 Subject: [PATCH 012/203] Update changelog (#604) * Update operator-ci.yaml * Update operator-ci.yaml Signed-off-by: Akshay kumar * remove space * Update CHANGELOG.md * Update CHANGELOG.md Signed-off-by: Akshay kumar * Delete .github/workflows/operator-ci.yaml * Updated changelog file Signed-off-by: Akshay kumar * fix conflict Signed-off-by: Shubham Gupta --------- Signed-off-by: Akshay kumar Signed-off-by: Shubham Gupta Co-authored-by: Shubham Gupta Co-authored-by: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 3 +- CHANGELOG.md | 53 ++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 01613f2d5..ead3a89f3 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -34,7 +34,6 @@ jobs: else echo "All files are formated using gofmt" fi - govet: runs-on: ubuntu-latest steps: @@ -95,7 +94,6 @@ jobs: run: | mkdir -p ${{ github.workspace }}/compiled/${{ matrix.arch }} zip ${{ github.workspace }}/compiled/${{ matrix.arch }}/${{ env.APPLICATION_NAME }}-${{ matrix.arch }}.zip ${{ github.workspace }}/${{ env.APPLICATION_NAME }} - build_scan_container_image: needs: [container_quality_dockerfile_lint] runs-on: ubuntu-latest @@ -125,5 +123,6 @@ jobs: uses: securego/gosec@master with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GOSEC_OUTPUT: "junit-xml:/github/workspace/gosec-results.xml" diff --git a/CHANGELOG.md b/CHANGELOG.md index fdf2139d0..0f82ddec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,56 @@ +### v0.15.0 +##### July 17, 2023 Latest + +#### :beetle: Bug Fixes + +- Fix Linter Issue #479 +- Fix exporter ports enabled even when exporters disabled #484 +- Corrected scenario "go-get-tool" in makefile #499 +- Operator Crash when persistence is false/Disabled #519 -- Breaking Change +- call of func checkAttachedSlave for 1 Master Replication #523 +- Only created /node-conf VolumeMount for clusters #532 +- Redis Sentinel Exporter ports in Env Vars #533 +- Init Container tried to mount invalid volume name #538 +- Cluster leader failover loop if there is only a single leader #542 + +#### :tada: Features + +- Add RedisExporter for sentinel #440 +- Add InitContainer Field #458 +- ACL redis via secret #486 +- Adding Custom TerminationGracePeriodSeconds and additional fields for Sidecar #487 +- Enable Support for Backup and Restore via script #489 +- Support Scaling for Redis Cluster #531 -- Breaking Change + +#### :tada: Refactors + +- Fixed StatefulSet(sentinel) Label for Service(Selector) #442 +- Declare Module Correctly On sentinel #478 +- Manage (Pod and Container) security Context explicitly #518 +- Add watchnamespace function as per operator hub #520 +- Remove sentinel default validation not effect #535 +- Remove sentinel cluster size validation no effect #536 + +### v0.14.0 +##### Feburary 13, 2023 + +#### :beetle: Bug Fixes + +- Added check for persistent volume nil condition +- Fix crash with go panic +- Fix memory address bug and nil pointer +- CR annotations fixes w.r.t. to stateful set +- Fix issues with ARM64 support + +#### :tada: Features + +- Added serviceType functionality for redis standalone and cluster +- Added feature for additional volume mounts +- Added nodeSelectory and tolerations for redis cluster +- Added recreation logic for redis stateful sets +- Added replication mode support for the redis cluster +- Added sentinel support for replication failover + ### v0.13.0 ##### November 10, 2022 From 87fa654789c6899221723d8b582c0b862742547b Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 23 Sep 2023 21:53:18 +0530 Subject: [PATCH 013/203] bump image version (#643) Signed-off-by: Shubham Gupta --- docs/content/en/docs/Getting Started/Sentinel/_index.md | 2 +- example/v1beta1/redis-sentinel.yaml | 2 +- example/v1beta1/redis_sentinel/sentinel.yaml | 2 +- example/v1beta2/acl_config/replication.yaml | 2 +- example/v1beta2/additional_config/clusterd.yaml | 2 +- example/v1beta2/additional_config/replication.yaml | 2 +- example/v1beta2/additional_config/standalone.yaml | 2 +- example/v1beta2/advance_config/clusterd.yaml | 2 +- example/v1beta2/advance_config/standalone.yaml | 2 +- example/v1beta2/affinity/clusterd.yaml | 2 +- example/v1beta2/affinity/replication.yaml | 2 +- example/v1beta2/affinity/standalone.yaml | 2 +- example/v1beta2/backup_restore/restore/redis-cluster.yaml | 2 +- example/v1beta2/disruption_budget/clusterd.yaml | 2 +- example/v1beta2/env_vars/redis-cluster.yaml | 2 +- example/v1beta2/env_vars/redis-replication.yaml | 2 +- example/v1beta2/env_vars/redis-sentinel.yaml | 2 +- example/v1beta2/env_vars/redis-standalone.yaml | 2 +- example/v1beta2/external_service/clusterd.yaml | 2 +- example/v1beta2/external_service/replication.yaml | 2 +- example/v1beta2/external_service/standalone.yaml | 2 +- example/v1beta2/node-selector/clusterd.yaml | 2 +- example/v1beta2/node-selector/replication.yaml | 2 +- example/v1beta2/node-selector/standalone.yaml | 2 +- example/v1beta2/password_protected/clusterd.yaml | 2 +- example/v1beta2/password_protected/replication.yaml | 2 +- example/v1beta2/password_protected/standalone.yaml | 2 +- example/v1beta2/private_registry/clusterd.yaml | 2 +- example/v1beta2/private_registry/replication.yaml | 2 +- example/v1beta2/private_registry/standalone.yaml | 2 +- example/v1beta2/probes/clusterd.yaml | 2 +- example/v1beta2/probes/replication.yaml | 2 +- example/v1beta2/probes/standalone.yaml | 2 +- example/v1beta2/recreate-statefulset/clusterd.yaml | 2 +- example/v1beta2/recreate-statefulset/replication.yaml | 2 +- example/v1beta2/recreate-statefulset/standalone.yaml | 2 +- example/v1beta2/redis-cluster.yaml | 2 +- example/v1beta2/redis-replication.yaml | 2 +- example/v1beta2/redis-sentinel.yaml | 2 +- example/v1beta2/redis-standalone.yaml | 2 +- example/v1beta2/redis_monitoring/clusterd.yaml | 2 +- example/v1beta2/redis_monitoring/replication.yaml | 2 +- example/v1beta2/redis_monitoring/standalone.yaml | 2 +- example/v1beta2/redis_sentinel/sentinel.yaml | 2 +- example/v1beta2/sidecar_features/sidecar.yaml | 2 +- example/v1beta2/tls_enabled/redis-cluster.yaml | 2 +- example/v1beta2/tls_enabled/redis-replication.yaml | 2 +- example/v1beta2/tls_enabled/redis-standalone.yaml | 2 +- example/v1beta2/tolerations/clusterd.yaml | 2 +- example/v1beta2/tolerations/replication.yaml | 2 +- example/v1beta2/tolerations/standalone.yaml | 2 +- example/v1beta2/upgrade-strategy/clusterd.yaml | 2 +- example/v1beta2/upgrade-strategy/replication.yaml | 2 +- example/v1beta2/upgrade-strategy/standalone.yaml | 2 +- example/v1beta2/volume_mount/redis-cluster.yaml | 2 +- example/v1beta2/volume_mount/redis-replication.yaml | 2 +- example/v1beta2/volume_mount/redis-standalone.yaml | 2 +- tests/e2e/v1beta1/setup/cluster.yaml | 2 +- tests/e2e/v1beta2/setup/cluster.yaml | 2 +- 59 files changed, 59 insertions(+), 59 deletions(-) diff --git a/docs/content/en/docs/Getting Started/Sentinel/_index.md b/docs/content/en/docs/Getting Started/Sentinel/_index.md index 58feaeb08..f84ac0b86 100644 --- a/docs/content/en/docs/Getting Started/Sentinel/_index.md +++ b/docs/content/en/docs/Getting Started/Sentinel/_index.md @@ -77,7 +77,7 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.7 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta1/redis-sentinel.yaml b/example/v1beta1/redis-sentinel.yaml index 4eec84b51..430916b6c 100644 --- a/example/v1beta1/redis-sentinel.yaml +++ b/example/v1beta1/redis-sentinel.yaml @@ -11,7 +11,7 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.7 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta1/redis_sentinel/sentinel.yaml b/example/v1beta1/redis_sentinel/sentinel.yaml index 4eec84b51..430916b6c 100644 --- a/example/v1beta1/redis_sentinel/sentinel.yaml +++ b/example/v1beta1/redis_sentinel/sentinel.yaml @@ -11,7 +11,7 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.7 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/acl_config/replication.yaml b/example/v1beta2/acl_config/replication.yaml index 6d754c26d..8b53a5ae6 100644 --- a/example/v1beta2/acl_config/replication.yaml +++ b/example/v1beta2/acl_config/replication.yaml @@ -11,7 +11,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/additional_config/clusterd.yaml b/example/v1beta2/additional_config/clusterd.yaml index bb8d825ad..e2ce50ee2 100644 --- a/example/v1beta2/additional_config/clusterd.yaml +++ b/example/v1beta2/additional_config/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/additional_config/replication.yaml b/example/v1beta2/additional_config/replication.yaml index 001882dbb..b3393f9ef 100644 --- a/example/v1beta2/additional_config/replication.yaml +++ b/example/v1beta2/additional_config/replication.yaml @@ -8,7 +8,7 @@ spec: redisConfig: additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/additional_config/standalone.yaml b/example/v1beta2/additional_config/standalone.yaml index 6458e3631..53a841934 100644 --- a/example/v1beta2/additional_config/standalone.yaml +++ b/example/v1beta2/additional_config/standalone.yaml @@ -7,7 +7,7 @@ spec: redisConfig: additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/advance_config/clusterd.yaml b/example/v1beta2/advance_config/clusterd.yaml index 9d652ddae..57d7ff97f 100644 --- a/example/v1beta2/advance_config/clusterd.yaml +++ b/example/v1beta2/advance_config/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 resources: requests: cpu: 101m diff --git a/example/v1beta2/advance_config/standalone.yaml b/example/v1beta2/advance_config/standalone.yaml index 3505c18e2..f74862b5a 100644 --- a/example/v1beta2/advance_config/standalone.yaml +++ b/example/v1beta2/advance_config/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/affinity/clusterd.yaml b/example/v1beta2/affinity/clusterd.yaml index db3845403..84623e61d 100644 --- a/example/v1beta2/affinity/clusterd.yaml +++ b/example/v1beta2/affinity/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/affinity/replication.yaml b/example/v1beta2/affinity/replication.yaml index f7a102190..2901dc37c 100644 --- a/example/v1beta2/affinity/replication.yaml +++ b/example/v1beta2/affinity/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/affinity/standalone.yaml b/example/v1beta2/affinity/standalone.yaml index 910bc95d8..479568c3b 100644 --- a/example/v1beta2/affinity/standalone.yaml +++ b/example/v1beta2/affinity/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/backup_restore/restore/redis-cluster.yaml b/example/v1beta2/backup_restore/restore/redis-cluster.yaml index e8f857fa6..50fdaea5e 100644 --- a/example/v1beta2/backup_restore/restore/redis-cluster.yaml +++ b/example/v1beta2/backup_restore/restore/redis-cluster.yaml @@ -11,7 +11,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/disruption_budget/clusterd.yaml b/example/v1beta2/disruption_budget/clusterd.yaml index 97720f790..f017b4ed4 100644 --- a/example/v1beta2/disruption_budget/clusterd.yaml +++ b/example/v1beta2/disruption_budget/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/env_vars/redis-cluster.yaml b/example/v1beta2/env_vars/redis-cluster.yaml index 44a420efb..082c1ae81 100644 --- a/example/v1beta2/env_vars/redis-cluster.yaml +++ b/example/v1beta2/env_vars/redis-cluster.yaml @@ -11,7 +11,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/env_vars/redis-replication.yaml b/example/v1beta2/env_vars/redis-replication.yaml index 10fd3a13b..99214c8bc 100644 --- a/example/v1beta2/env_vars/redis-replication.yaml +++ b/example/v1beta2/env_vars/redis-replication.yaml @@ -11,7 +11,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/env_vars/redis-sentinel.yaml b/example/v1beta2/env_vars/redis-sentinel.yaml index 48bea21cc..6dd84edeb 100644 --- a/example/v1beta2/env_vars/redis-sentinel.yaml +++ b/example/v1beta2/env_vars/redis-sentinel.yaml @@ -14,7 +14,7 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.7 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/env_vars/redis-standalone.yaml b/example/v1beta2/env_vars/redis-standalone.yaml index cbe0fbdf2..e0dd08947 100644 --- a/example/v1beta2/env_vars/redis-standalone.yaml +++ b/example/v1beta2/env_vars/redis-standalone.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/external_service/clusterd.yaml b/example/v1beta2/external_service/clusterd.yaml index c8036c974..21f75b106 100644 --- a/example/v1beta2/external_service/clusterd.yaml +++ b/example/v1beta2/external_service/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/external_service/replication.yaml b/example/v1beta2/external_service/replication.yaml index 1ca1f9d71..481653988 100644 --- a/example/v1beta2/external_service/replication.yaml +++ b/example/v1beta2/external_service/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/external_service/standalone.yaml b/example/v1beta2/external_service/standalone.yaml index d51fdf6e0..c1e24459e 100644 --- a/example/v1beta2/external_service/standalone.yaml +++ b/example/v1beta2/external_service/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/node-selector/clusterd.yaml b/example/v1beta2/node-selector/clusterd.yaml index e4f0b9b89..6620875a7 100644 --- a/example/v1beta2/node-selector/clusterd.yaml +++ b/example/v1beta2/node-selector/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/node-selector/replication.yaml b/example/v1beta2/node-selector/replication.yaml index 1e387396a..58243fe0e 100644 --- a/example/v1beta2/node-selector/replication.yaml +++ b/example/v1beta2/node-selector/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/node-selector/standalone.yaml b/example/v1beta2/node-selector/standalone.yaml index 1213e99f6..daa3fb1e2 100644 --- a/example/v1beta2/node-selector/standalone.yaml +++ b/example/v1beta2/node-selector/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/password_protected/clusterd.yaml b/example/v1beta2/password_protected/clusterd.yaml index 4d1068508..9b531cf96 100644 --- a/example/v1beta2/password_protected/clusterd.yaml +++ b/example/v1beta2/password_protected/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisSecret: name: redis-secret diff --git a/example/v1beta2/password_protected/replication.yaml b/example/v1beta2/password_protected/replication.yaml index 6491b0f75..6bec17c31 100644 --- a/example/v1beta2/password_protected/replication.yaml +++ b/example/v1beta2/password_protected/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisSecret: name: redis-secret diff --git a/example/v1beta2/password_protected/standalone.yaml b/example/v1beta2/password_protected/standalone.yaml index 9796a3a5d..5d93e25ee 100644 --- a/example/v1beta2/password_protected/standalone.yaml +++ b/example/v1beta2/password_protected/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisSecret: name: redis-secret diff --git a/example/v1beta2/private_registry/clusterd.yaml b/example/v1beta2/private_registry/clusterd.yaml index 27cdec186..dfba74e36 100644 --- a/example/v1beta2/private_registry/clusterd.yaml +++ b/example/v1beta2/private_registry/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent imagePullSecrets: - name: regcred diff --git a/example/v1beta2/private_registry/replication.yaml b/example/v1beta2/private_registry/replication.yaml index 9b9876d29..bc7c17270 100644 --- a/example/v1beta2/private_registry/replication.yaml +++ b/example/v1beta2/private_registry/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent imagePullSecrets: - name: regcred diff --git a/example/v1beta2/private_registry/standalone.yaml b/example/v1beta2/private_registry/standalone.yaml index 956dc1944..3758cfe09 100644 --- a/example/v1beta2/private_registry/standalone.yaml +++ b/example/v1beta2/private_registry/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent imagePullSecrets: - name: regcred diff --git a/example/v1beta2/probes/clusterd.yaml b/example/v1beta2/probes/clusterd.yaml index 0699a7ade..55a27e49e 100644 --- a/example/v1beta2/probes/clusterd.yaml +++ b/example/v1beta2/probes/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta2/probes/replication.yaml b/example/v1beta2/probes/replication.yaml index 7ea3826e9..243267b09 100644 --- a/example/v1beta2/probes/replication.yaml +++ b/example/v1beta2/probes/replication.yaml @@ -9,7 +9,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/probes/standalone.yaml b/example/v1beta2/probes/standalone.yaml index a03d1e4cd..369a8edf3 100644 --- a/example/v1beta2/probes/standalone.yaml +++ b/example/v1beta2/probes/standalone.yaml @@ -8,7 +8,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/recreate-statefulset/clusterd.yaml b/example/v1beta2/recreate-statefulset/clusterd.yaml index 6f361694f..4c3571d16 100644 --- a/example/v1beta2/recreate-statefulset/clusterd.yaml +++ b/example/v1beta2/recreate-statefulset/clusterd.yaml @@ -13,7 +13,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/recreate-statefulset/replication.yaml b/example/v1beta2/recreate-statefulset/replication.yaml index 20c2bcfea..d33eeb194 100644 --- a/example/v1beta2/recreate-statefulset/replication.yaml +++ b/example/v1beta2/recreate-statefulset/replication.yaml @@ -8,7 +8,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/recreate-statefulset/standalone.yaml b/example/v1beta2/recreate-statefulset/standalone.yaml index bacd0b19c..d3bcc2e90 100644 --- a/example/v1beta2/recreate-statefulset/standalone.yaml +++ b/example/v1beta2/recreate-statefulset/standalone.yaml @@ -7,7 +7,7 @@ metadata: redis.opstreelabs.in/recreate-statefulset: "true" spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/redis-cluster.yaml b/example/v1beta2/redis-cluster.yaml index 8c232efee..5690c20f0 100644 --- a/example/v1beta2/redis-cluster.yaml +++ b/example/v1beta2/redis-cluster.yaml @@ -11,7 +11,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis-replication.yaml b/example/v1beta2/redis-replication.yaml index 73a69b9e2..e7a11022e 100644 --- a/example/v1beta2/redis-replication.yaml +++ b/example/v1beta2/redis-replication.yaml @@ -11,7 +11,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis-sentinel.yaml b/example/v1beta2/redis-sentinel.yaml index cd9a3a4ec..e53105d6e 100644 --- a/example/v1beta2/redis-sentinel.yaml +++ b/example/v1beta2/redis-sentinel.yaml @@ -14,7 +14,7 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.7 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis-standalone.yaml b/example/v1beta2/redis-standalone.yaml index 567e7f919..27e2b5e7f 100644 --- a/example/v1beta2/redis-standalone.yaml +++ b/example/v1beta2/redis-standalone.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis_monitoring/clusterd.yaml b/example/v1beta2/redis_monitoring/clusterd.yaml index bfb6b3894..8ba5e9ea5 100644 --- a/example/v1beta2/redis_monitoring/clusterd.yaml +++ b/example/v1beta2/redis_monitoring/clusterd.yaml @@ -13,7 +13,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: Always redisExporter: enabled: true diff --git a/example/v1beta2/redis_monitoring/replication.yaml b/example/v1beta2/redis_monitoring/replication.yaml index 17c09b8ce..517cfa5ab 100644 --- a/example/v1beta2/redis_monitoring/replication.yaml +++ b/example/v1beta2/redis_monitoring/replication.yaml @@ -8,7 +8,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/redis_monitoring/standalone.yaml b/example/v1beta2/redis_monitoring/standalone.yaml index 9c772fbe2..ba666e196 100644 --- a/example/v1beta2/redis_monitoring/standalone.yaml +++ b/example/v1beta2/redis_monitoring/standalone.yaml @@ -7,7 +7,7 @@ metadata: # redis.opstreelabs.in/skip-reconcile: "true" spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/redis_sentinel/sentinel.yaml b/example/v1beta2/redis_sentinel/sentinel.yaml index c2840cd53..78f838906 100644 --- a/example/v1beta2/redis_sentinel/sentinel.yaml +++ b/example/v1beta2/redis_sentinel/sentinel.yaml @@ -11,7 +11,7 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.7 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/sidecar_features/sidecar.yaml b/example/v1beta2/sidecar_features/sidecar.yaml index ac6c58347..7b3b1f4f7 100644 --- a/example/v1beta2/sidecar_features/sidecar.yaml +++ b/example/v1beta2/sidecar_features/sidecar.yaml @@ -7,7 +7,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tls_enabled/redis-cluster.yaml b/example/v1beta2/tls_enabled/redis-cluster.yaml index 7c2f1f138..7147edd43 100644 --- a/example/v1beta2/tls_enabled/redis-cluster.yaml +++ b/example/v1beta2/tls_enabled/redis-cluster.yaml @@ -18,7 +18,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tls_enabled/redis-replication.yaml b/example/v1beta2/tls_enabled/redis-replication.yaml index 563709da2..743e6d7fb 100644 --- a/example/v1beta2/tls_enabled/redis-replication.yaml +++ b/example/v1beta2/tls_enabled/redis-replication.yaml @@ -16,7 +16,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tls_enabled/redis-standalone.yaml b/example/v1beta2/tls_enabled/redis-standalone.yaml index 6176765a8..ca30a243c 100644 --- a/example/v1beta2/tls_enabled/redis-standalone.yaml +++ b/example/v1beta2/tls_enabled/redis-standalone.yaml @@ -15,7 +15,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/tolerations/clusterd.yaml b/example/v1beta2/tolerations/clusterd.yaml index 02d076bfc..8227fdac1 100644 --- a/example/v1beta2/tolerations/clusterd.yaml +++ b/example/v1beta2/tolerations/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent redisExporter: enabled: false diff --git a/example/v1beta2/tolerations/replication.yaml b/example/v1beta2/tolerations/replication.yaml index d99fc289a..1de158cf1 100644 --- a/example/v1beta2/tolerations/replication.yaml +++ b/example/v1beta2/tolerations/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent storage: volumeClaimTemplate: diff --git a/example/v1beta2/tolerations/standalone.yaml b/example/v1beta2/tolerations/standalone.yaml index 36c2fbf19..ac94e9d68 100644 --- a/example/v1beta2/tolerations/standalone.yaml +++ b/example/v1beta2/tolerations/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/upgrade-strategy/clusterd.yaml b/example/v1beta2/upgrade-strategy/clusterd.yaml index e6614dd16..1a8450896 100644 --- a/example/v1beta2/upgrade-strategy/clusterd.yaml +++ b/example/v1beta2/upgrade-strategy/clusterd.yaml @@ -11,7 +11,7 @@ spec: fsGroup: 1000 persistenceEnabled: true kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent updateStrategy: type: OnDelete diff --git a/example/v1beta2/upgrade-strategy/replication.yaml b/example/v1beta2/upgrade-strategy/replication.yaml index 2a9ad31e7..834b2e186 100644 --- a/example/v1beta2/upgrade-strategy/replication.yaml +++ b/example/v1beta2/upgrade-strategy/replication.yaml @@ -6,7 +6,7 @@ metadata: spec: clusterSize: 3 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent type: OnDelete # type: RollingUpdate diff --git a/example/v1beta2/upgrade-strategy/standalone.yaml b/example/v1beta2/upgrade-strategy/standalone.yaml index f01895b2f..e8e1aacbe 100644 --- a/example/v1beta2/upgrade-strategy/standalone.yaml +++ b/example/v1beta2/upgrade-strategy/standalone.yaml @@ -5,7 +5,7 @@ metadata: name: redis-standalone spec: kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent updateStrategy: type: OnDelete diff --git a/example/v1beta2/volume_mount/redis-cluster.yaml b/example/v1beta2/volume_mount/redis-cluster.yaml index d4d8d8d2b..a7f069d63 100644 --- a/example/v1beta2/volume_mount/redis-cluster.yaml +++ b/example/v1beta2/volume_mount/redis-cluster.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/volume_mount/redis-replication.yaml b/example/v1beta2/volume_mount/redis-replication.yaml index c107a0f94..4c081689c 100644 --- a/example/v1beta2/volume_mount/redis-replication.yaml +++ b/example/v1beta2/volume_mount/redis-replication.yaml @@ -7,7 +7,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/volume_mount/redis-standalone.yaml b/example/v1beta2/volume_mount/redis-standalone.yaml index 421dab3d7..cbb1a96da 100644 --- a/example/v1beta2/volume_mount/redis-standalone.yaml +++ b/example/v1beta2/volume_mount/redis-standalone.yaml @@ -6,7 +6,7 @@ spec: # redisConfig: # additionalRedisConfig: redis-external-config kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/tests/e2e/v1beta1/setup/cluster.yaml b/tests/e2e/v1beta1/setup/cluster.yaml index 73afc2b4a..6315fc563 100644 --- a/tests/e2e/v1beta1/setup/cluster.yaml +++ b/tests/e2e/v1beta1/setup/cluster.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.7 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/tests/e2e/v1beta2/setup/cluster.yaml b/tests/e2e/v1beta2/setup/cluster.yaml index 09b11b18b..64814772c 100644 --- a/tests/e2e/v1beta2/setup/cluster.yaml +++ b/tests/e2e/v1beta2/setup/cluster.yaml @@ -10,7 +10,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.11 + image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: From 26f9c0be576c6fbcd263f322ac7bd38478aa8e5e Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 24 Sep 2023 13:33:06 +0530 Subject: [PATCH 014/203] Fix nil ptr for the redis-sentinel. (#642) Signed-off-by: Shubham Gupta --- api/v1beta1/redissentinel_conversion.go | 2 +- example/v1beta2/redis-cluster.yaml | 5 ----- k8sutils/redis-sentinel.go | 6 +++++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/api/v1beta1/redissentinel_conversion.go b/api/v1beta1/redissentinel_conversion.go index 479f76cad..a069e1677 100644 --- a/api/v1beta1/redissentinel_conversion.go +++ b/api/v1beta1/redissentinel_conversion.go @@ -5,7 +5,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/conversion" ) -// ConvertTo converts this RedisSentinel to the Hub version (vbeta2). +// ConvertTo converts this RedisSentinel to the Hub version (v1beta2). func (src *RedisSentinel) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*redisv1beta2.RedisSentinel) diff --git a/example/v1beta2/redis-cluster.yaml b/example/v1beta2/redis-cluster.yaml index 5690c20f0..87b308e3a 100644 --- a/example/v1beta2/redis-cluster.yaml +++ b/example/v1beta2/redis-cluster.yaml @@ -20,11 +20,6 @@ spec: limits: cpu: 101m memory: 128Mi - env: - - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" - - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" # redisSecret: # name: redis-secret # key: password diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index f05aea39c..d1636400a 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -41,7 +41,7 @@ func CreateRedisSentinel(cr *redisv1beta2.RedisSentinel) error { TerminationGracePeriodSeconds: cr.Spec.TerminationGracePeriodSeconds, } - if cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig != nil { + if cr.Spec.RedisSentinelConfig != nil && cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig != nil { prop.ExternalConfig = cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig } @@ -242,6 +242,10 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { + if cr.Spec.RedisSentinelConfig == nil { + return &[]corev1.EnvVar{} + } + envVar := &[]corev1.EnvVar{ { Name: "MASTER_GROUP_NAME", From eb25ef7d8435a45fa3c4f4fa881c0a53ba3c2f3c Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 29 Sep 2023 16:16:32 +0530 Subject: [PATCH 015/203] update env (#649) Signed-off-by: Shubham Gupta --- .../redis.redis.opstreelabs.in_redis.yaml | 104 ++++++++++++++++++ ...is.redis.opstreelabs.in_redisclusters.yaml | 104 ++++++++++++++++++ ...edis.opstreelabs.in_redisreplications.yaml | 104 ++++++++++++++++++ ...s.redis.opstreelabs.in_redissentinels.yaml | 104 ++++++++++++++++++ 4 files changed, 416 insertions(+) diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index 4032fa9cf..fdeb29155 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -4563,6 +4563,110 @@ spec: type: array type: object type: object + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array initContainer: description: InitContainer for each Redis pods properties: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 2c6967d6d..6fc75fa00 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -4919,6 +4919,110 @@ spec: clusterVersion: default: v7 type: string + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array initContainer: description: InitContainer for each Redis pods properties: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index 11f780c4f..29c728ace 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -4568,6 +4568,110 @@ spec: clusterSize: format: int32 type: integer + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array initContainer: description: InitContainer for each Redis pods properties: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 7a273ffa4..908075903 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -2452,6 +2452,110 @@ spec: format: int32 minimum: 1 type: integer + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array initContainer: description: InitContainer for each Redis pods properties: From 673f117352daf1ee92bb73cc079966f9a6919adf Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 30 Sep 2023 16:56:42 +0530 Subject: [PATCH 016/203] [Refactor] : Add Test Case (#650) * unit-test Signed-off-by: Shubham Gupta * comment Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 12 + controllers/suite_test.go | 14 +- go.mod | 15 +- go.sum | 40 ++-- k8sutils/labels_test.go | 353 +++++++++++++++++++++++++++++ 5 files changed, 405 insertions(+), 29 deletions(-) create mode 100644 k8sutils/labels_test.go diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index ead3a89f3..52e5a6ad8 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -45,6 +45,18 @@ jobs: - name: Run Go Vet run: go vet ./... + gotest: + name: Go Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GolangVersion }} + - name: Run Go Tests + run: go test ./... + code_quality_golang_ci_lint: needs: [gofmt, govet] runs-on: ubuntu-latest diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 1b7d57a7b..88aea5083 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -18,7 +18,6 @@ package controllers import ( "path/filepath" - "testing" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" . "github.com/onsi/ginkgo" @@ -28,7 +27,6 @@ import ( // "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" - "sigs.k8s.io/controller-runtime/pkg/envtest/printer" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" // +kubebuilder:scaffold:imports @@ -41,13 +39,13 @@ import ( var k8sClient client.Client var testEnv *envtest.Environment -func TestAPIs(t *testing.T) { - RegisterFailHandler(Fail) +// func TestAPIs(t *testing.T) { +// RegisterFailHandler(Fail) - RunSpecsWithDefaultAndCustomReporters(t, - "Controller Suite", - []Reporter{printer.NewlineReporter{}}) -} +// RunSpecsWithDefaultAndCustomReporters(t, +// "Controller Suite", +// []Reporter{printer.NewlineReporter{}}) +// } var _ = BeforeSuite(func() { logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) diff --git a/go.mod b/go.mod index 6257c84de..705b08c46 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( k8s.io/api v0.23.0 k8s.io/apimachinery v0.23.0 k8s.io/client-go v0.23.0 + k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b sigs.k8s.io/controller-runtime v0.11.0 ) @@ -50,15 +51,16 @@ require ( github.com/prometheus/common v0.28.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.8.4 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.19.1 // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/net v0.7.0 // indirect + golang.org/x/crypto v0.13.0 // indirect + golang.org/x/net v0.15.0 // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/term v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect @@ -66,12 +68,11 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.23.0 // indirect k8s.io/component-base v0.23.0 // indirect k8s.io/klog/v2 v2.30.0 // indirect k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect - k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/go.sum b/go.sum index 096a9b4c1..e3b8f89b6 100644 --- a/go.sum +++ b/go.sum @@ -464,13 +464,18 @@ github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -536,8 +541,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -574,6 +579,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -622,9 +628,10 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -652,6 +659,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -720,15 +728,17 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -738,9 +748,10 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -808,6 +819,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -956,8 +968,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go new file mode 100644 index 000000000..c326929f6 --- /dev/null +++ b/k8sutils/labels_test.go @@ -0,0 +1,353 @@ +package k8sutils + +import ( + "reflect" + "testing" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" +) + +func Test_generateMetaInformation(t *testing.T) { + type args struct { + resourceKind string + apiVersion string + } + tests := []struct { + name string + args args + want metav1.TypeMeta + }{ + {"pod-generateMetaInformation", args{resourceKind: "Pod", apiVersion: "v1"}, metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := generateMetaInformation(tt.args.resourceKind, tt.args.apiVersion); !reflect.DeepEqual(got, tt.want) { + t.Errorf("generateMetaInformation() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_generateObjectMetaInformation(t *testing.T) { + type args struct { + name string + namespace string + labels map[string]string + annotations map[string]string + } + tests := []struct { + name string + args args + want metav1.ObjectMeta + }{ + { + name: "generateObjectMetaInformation", + args: args{ + name: "test", + namespace: "default", + labels: map[string]string{"test": "test"}, + annotations: map[string]string{"test": "test"}}, + want: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + Labels: map[string]string{"test": "test"}, + Annotations: map[string]string{"test": "test"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := generateObjectMetaInformation(tt.args.name, tt.args.namespace, tt.args.labels, tt.args.annotations); !reflect.DeepEqual(got, tt.want) { + t.Errorf("generateObjectMetaInformation() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAddOwnerRefToObject(t *testing.T) { + type args struct { + obj metav1.Object + ownerRef metav1.OwnerReference + } + tests := []struct { + name string + args args + }{ + { + name: "AddOwnerRefToObject", + args: args{ + obj: &metav1.ObjectMeta{ + Name: "pod", + Namespace: "default", + }, + ownerRef: metav1.OwnerReference{ + APIVersion: "apps/v1", + Kind: "Deployment", + Name: "deployment", + UID: "1234567890", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + AddOwnerRefToObject(tt.args.obj, tt.args.ownerRef) + }) + } +} + +func Test_generateStatefulSetsAnots(t *testing.T) { + type args struct { + stsMeta metav1.ObjectMeta + } + tests := []struct { + name string + args args + want map[string]string + }{ + { + name: "generateStatefulSetsAnots", + args: args{ + stsMeta: metav1.ObjectMeta{ + Name: "sts", + Namespace: "default", + Annotations: map[string]string{ + "app.kubernetes.io/name": "redis", + "operator.redis.com/redis": "redis", + "operator.redis.com/redis-uid": "1234567890", + }, + }, + }, + want: map[string]string{ + "app.kubernetes.io/name": "redis", + "operator.redis.com/redis": "redis", + "operator.redis.com/redis-uid": "1234567890", + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "sts", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := generateStatefulSetsAnots(tt.args.stsMeta); !reflect.DeepEqual(got, tt.want) { + t.Errorf("generateStatefulSetsAnots() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_filterAnnotations(t *testing.T) { + type args struct { + anots map[string]string + } + tests := []struct { + name string + args args + want map[string]string + }{ + { + name: "filterAnnotations", + args: args{ + anots: map[string]string{ + "app.kubernetes.io/name": "redis", + "operator.redis.com/redis": "redis", + "kubectl.kubernetes.io/last-applied-configuration": "eyJhcGlWZXJzaW9uIjoiYXBwcy92", + "banzaicloud.com/last-applied": "eyJhcGlWZXJzaW9uIjoiYXBwcy92", + }, + }, + want: map[string]string{ + "app.kubernetes.io/name": "redis", + "operator.redis.com/redis": "redis", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := filterAnnotations(tt.args.anots); !reflect.DeepEqual(got, tt.want) { + t.Errorf("filterAnnotations() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGenerateServiceAnots(t *testing.T) { + stsMeta := metav1.ObjectMeta{ + Name: "test-sts", + Annotations: map[string]string{"custom-annotation": "custom-value"}, + } + + additionalSvcAnnotations := map[string]string{ + "additional-annotation": "additional-value", + } + + expectedAnnotations := map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + "prometheus.io/scrape": "true", + "prometheus.io/port": "9121", + "custom-annotation": "custom-value", + "additional-annotation": "additional-value", + } + + resultAnnotations := generateServiceAnots(stsMeta, additionalSvcAnnotations) + + if !reflect.DeepEqual(resultAnnotations, expectedAnnotations) { + t.Errorf("Expected annotations to be %v but got %v", expectedAnnotations, resultAnnotations) + } +} + +func TestGetRedisLabels(t *testing.T) { + tests := []struct { + name string + setupType string + role string + input map[string]string + expected map[string]string + }{ + { + name: "test-redis", + setupType: "cluster", + role: "master", + input: map[string]string{"custom-label": "custom-value"}, + expected: map[string]string{ + "app": "test-redis", + "redis_setup_type": "cluster", + "role": "master", + "custom-label": "custom-value", + }, + }, + { + name: "test-redis", + setupType: "standalone", + role: "master", + input: map[string]string{}, + expected: map[string]string{ + "app": "test-redis", + "redis_setup_type": "standalone", + "role": "master", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := getRedisLabels(tt.name, tt.setupType, tt.role, tt.input) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("For name=%s, setupType=%s, and role=%s; expected %v but got %v", tt.name, tt.setupType, tt.role, tt.expected, result) + } + }) + } +} + +func TestRedisAsOwner(t *testing.T) { + redisObj := &redisv1beta2.Redis{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "Redis", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis", + UID: "12345", + }, + } + + expectedOwnerReference := metav1.OwnerReference{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "Redis", + Name: "test-redis", + UID: "12345", + Controller: func() *bool { + b := true + return &b + }(), + } + + result := redisAsOwner(redisObj) + + if !reflect.DeepEqual(result, expectedOwnerReference) { + t.Errorf("Expected %v but got %v", expectedOwnerReference, result) + } +} + +func TestRedisClusterAsOwner(t *testing.T) { + clusterObj := &redisv1beta2.RedisCluster{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "RedisCluster", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-cluster", + UID: "abcdef", + }, + } + + expectedOwnerReference := metav1.OwnerReference{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "RedisCluster", + Name: "test-redis-cluster", + UID: "abcdef", + Controller: pointer.BoolPtr(true), + } + + result := redisClusterAsOwner(clusterObj) + + if !reflect.DeepEqual(result, expectedOwnerReference) { + t.Errorf("Expected %v but got %v", expectedOwnerReference, result) + } +} + +func TestRedisReplicationAsOwner(t *testing.T) { + replicationObj := &redisv1beta2.RedisReplication{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "RedisReplication", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-replication", + UID: "ghijkl", + }, + } + + expectedOwnerReference := metav1.OwnerReference{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "RedisReplication", + Name: "test-redis-replication", + UID: "ghijkl", + Controller: pointer.BoolPtr(true), + } + + result := redisReplicationAsOwner(replicationObj) + + if !reflect.DeepEqual(result, expectedOwnerReference) { + t.Errorf("Expected %v but got %v", expectedOwnerReference, result) + } +} + +func TestRedisSentinelAsOwner(t *testing.T) { + sentinelObj := &redisv1beta2.RedisSentinel{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "RedisSentinel", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-sentinel", + UID: "mnopqr", + }, + } + + expectedOwnerReference := metav1.OwnerReference{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "RedisSentinel", + Name: "test-redis-sentinel", + UID: "mnopqr", + Controller: pointer.BoolPtr(true), + } + + result := redisSentinelAsOwner(sentinelObj) + + if !reflect.DeepEqual(result, expectedOwnerReference) { + t.Errorf("Expected %v but got %v", expectedOwnerReference, result) + } +} From b5d1184db88cf16c96aac17b896d74096ddc827f Mon Sep 17 00:00:00 2001 From: Aswath S Date: Tue, 3 Oct 2023 20:16:52 +0530 Subject: [PATCH 017/203] Refactor. redis setup type in labels to contant (#652) * Refactor. redis setup type in labels to contant Signed-off-by: titanventura * Refactor. make setuptype and constants private Signed-off-by: titanventura --------- Signed-off-by: titanventura --- k8sutils/labels.go | 13 +++++++++++-- k8sutils/labels_test.go | 10 +++++----- k8sutils/poddisruption.go | 4 ++-- k8sutils/redis-cluster.go | 4 ++-- k8sutils/redis-replication.go | 4 ++-- k8sutils/redis-sentinel.go | 4 ++-- k8sutils/redis-standalone.go | 4 ++-- 7 files changed, 26 insertions(+), 17 deletions(-) diff --git a/k8sutils/labels.go b/k8sutils/labels.go index 6ed97ba63..8e90dfcea 100644 --- a/k8sutils/labels.go +++ b/k8sutils/labels.go @@ -5,6 +5,15 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +type setupType string + +const ( + standalone setupType = "standalone" + replication setupType = "replication" + cluster setupType = "cluster" + sentinel setupType = "sentinel" +) + // generateMetaInformation generates the meta information func generateMetaInformation(resourceKind string, apiVersion string) metav1.TypeMeta { return metav1.TypeMeta{ @@ -119,10 +128,10 @@ func LabelSelectors(labels map[string]string) *metav1.LabelSelector { return &metav1.LabelSelector{MatchLabels: labels} } -func getRedisLabels(name, setupType, role string, labels map[string]string) map[string]string { +func getRedisLabels(name string, st setupType, role string, labels map[string]string) map[string]string { lbls := map[string]string{ "app": name, - "redis_setup_type": setupType, + "redis_setup_type": string(st), "role": role, } for k, v := range labels { diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go index c326929f6..c04d8ca56 100644 --- a/k8sutils/labels_test.go +++ b/k8sutils/labels_test.go @@ -201,31 +201,31 @@ func TestGenerateServiceAnots(t *testing.T) { func TestGetRedisLabels(t *testing.T) { tests := []struct { name string - setupType string + setupType setupType role string input map[string]string expected map[string]string }{ { name: "test-redis", - setupType: "cluster", + setupType: cluster, role: "master", input: map[string]string{"custom-label": "custom-value"}, expected: map[string]string{ "app": "test-redis", - "redis_setup_type": "cluster", + "redis_setup_type": string(cluster), "role": "master", "custom-label": "custom-value", }, }, { name: "test-redis", - setupType: "standalone", + setupType: standalone, role: "master", input: map[string]string{}, expected: map[string]string{ "app": "test-redis", - "redis_setup_type": "standalone", + "redis_setup_type": string(standalone), "role": "master", }, }, diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index ca398efb3..7d0160d1e 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -19,7 +19,7 @@ func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role strin pdbName := cr.ObjectMeta.Name + "-" + role logger := pdbLogger(cr.Namespace, pdbName) if pdbParams != nil && pdbParams.Enabled { - labels := getRedisLabels(cr.ObjectMeta.Name, "cluster", role, cr.ObjectMeta.GetLabels()) + labels := getRedisLabels(cr.ObjectMeta.Name, cluster, role, cr.ObjectMeta.GetLabels()) annotations := generateStatefulSetsAnots(cr.ObjectMeta) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) pdbDef := generatePodDisruptionBudgetDef(cr, role, pdbMeta, cr.Spec.RedisLeader.PodDisruptionBudget) @@ -42,7 +42,7 @@ func ReconcileSentinelPodDisruptionBudget(cr *redisv1beta2.RedisSentinel, pdbPar pdbName := cr.ObjectMeta.Name + "-sentinel" logger := pdbLogger(cr.Namespace, pdbName) if pdbParams != nil && pdbParams.Enabled { - labels := getRedisLabels(cr.ObjectMeta.Name, "sentinel", "sentinel", cr.ObjectMeta.GetLabels()) + labels := getRedisLabels(cr.ObjectMeta.Name, sentinel, "sentinel", cr.ObjectMeta.GetLabels()) annotations := generateStatefulSetsAnots(cr.ObjectMeta) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) pdbDef := generateSentinelPodDisruptionBudgetDef(cr, "sentinel", pdbMeta, pdbParams) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index f9c44e96e..a367cd55f 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -209,7 +209,7 @@ func (service RedisClusterSTS) getReplicaCount(cr *redisv1beta2.RedisCluster) in func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisCluster) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) - labels := getRedisLabels(stateFulName, "cluster", service.RedisStateFulType, cr.ObjectMeta.Labels) + labels := getRedisLabels(stateFulName, cluster, service.RedisStateFulType, cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( @@ -232,7 +232,7 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.RedisCluster) error { serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) - labels := getRedisLabels(serviceName, "cluster", service.RedisServiceRole, cr.ObjectMeta.Labels) + labels := getRedisLabels(serviceName, cluster, service.RedisServiceRole, cr.ObjectMeta.Labels) annotations := generateServiceAnots(cr.ObjectMeta, nil) if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { enableMetrics = true diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 100f63cb0..070f03032 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -5,7 +5,7 @@ import redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" // CreateReplicationService method will create replication service for Redis func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) - labels := getRedisLabels(cr.ObjectMeta.Name, "replication", "replication", cr.ObjectMeta.Labels) + labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) annotations := generateServiceAnots(cr.ObjectMeta, nil) if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { enableMetrics = true @@ -45,7 +45,7 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { func CreateReplicationRedis(cr *redisv1beta2.RedisReplication) error { stateFulName := cr.ObjectMeta.Name logger := statefulSetLogger(cr.Namespace, cr.ObjectMeta.Name) - labels := getRedisLabels(cr.ObjectMeta.Name, "replication", "replication", cr.ObjectMeta.Labels) + labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul(cr.Namespace, diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index d1636400a..781d4f371 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -63,7 +63,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(cr *redisv1beta2.RedisS stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) - labels := getRedisLabels(stateFulName, "cluster", service.RedisStateFulType, cr.ObjectMeta.Labels) + labels := getRedisLabels(stateFulName, cluster, service.RedisStateFulType, cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( @@ -198,7 +198,7 @@ func (service RedisSentinelSTS) getSentinelCount(cr *redisv1beta2.RedisSentinel) func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) - labels := getRedisLabels(serviceName, "cluster", service.RedisServiceRole, cr.ObjectMeta.Labels) + labels := getRedisLabels(serviceName, cluster, service.RedisServiceRole, cr.ObjectMeta.Labels) annotations := generateServiceAnots(cr.ObjectMeta, nil) if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index f044fb432..3276847aa 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -9,7 +9,7 @@ var ( // CreateStandaloneService method will create standalone service for Redis func CreateStandaloneService(cr *redisv1beta2.Redis) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) - labels := getRedisLabels(cr.ObjectMeta.Name, "standalone", "standalone", cr.ObjectMeta.Labels) + labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) annotations := generateServiceAnots(cr.ObjectMeta, nil) if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { enableMetrics = true @@ -48,7 +48,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { // CreateStandaloneRedis will create a standalone redis setup func CreateStandaloneRedis(cr *redisv1beta2.Redis) error { logger := statefulSetLogger(cr.Namespace, cr.ObjectMeta.Name) - labels := getRedisLabels(cr.ObjectMeta.Name, "standalone", "standalone", cr.ObjectMeta.Labels) + labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta) objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul(cr.Namespace, From 67acb29f549c26cf9f5da96257d7745ba812e240 Mon Sep 17 00:00:00 2001 From: Aswath S Date: Wed, 4 Oct 2023 09:43:12 +0530 Subject: [PATCH 018/203] Golang ci lint action (#653) * Refactor. Change to golangci-lint action Signed-off-by: titanventura * Refactor. add './...' arg to golangci-lint command - gh-actions Signed-off-by: titanventura * Remove branch 'golang-ci-lint-action' from list of branches - gh-actions Signed-off-by: titanventura * Refactor. upgrade go and golangci-lint version - gh-actions Signed-off-by: titanventura * Refactor. remove 'golang-ci-lint-action' branch from list of branches and solve lint issues reported by golangci-lint v1.54.0 Signed-off-by: titanventura * Refactor. run go fmt Signed-off-by: titanventura --------- Signed-off-by: titanventura --- .github/workflows/operator-ci.yaml | 10 +++++----- api/v1beta2/redis_webhook.go | 4 ---- api/v1beta2/rediscluster_webhook.go | 4 ---- api/v1beta2/redisreplication_webhook.go | 4 ---- api/v1beta2/redissentinel_webhook.go | 4 ---- controllers/redis_controller.go | 4 ++-- controllers/rediscluster_controller.go | 4 ++-- controllers/redisreplication_controller.go | 4 ++-- controllers/redissentinel_controller.go | 4 ++-- k8sutils/poddisruption.go | 2 +- k8sutils/redis.go | 2 +- k8sutils/services.go | 2 +- k8sutils/statefulset.go | 4 ++-- 13 files changed, 18 insertions(+), 34 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 52e5a6ad8..0ab72a51d 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -63,14 +63,14 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: ${{ env.GolangVersion }} - - name: Install GolangCI-Lint - run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.40.0 - name: Run GolangCI-Lint - run: ./bin/golangci-lint run --timeout 5m0s ./... + uses: golangci/golangci-lint-action@v3 + with: + version: v1.54.0 + args: --timeout=5m0s ./... container_quality_dockerfile_lint: needs: [gofmt, govet] diff --git a/api/v1beta2/redis_webhook.go b/api/v1beta2/redis_webhook.go index a6b69ae3d..c00eae821 100644 --- a/api/v1beta2/redis_webhook.go +++ b/api/v1beta2/redis_webhook.go @@ -18,12 +18,8 @@ package v1beta2 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var redislog = logf.Log.WithName("redis-resource") - func (r *Redis) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/api/v1beta2/rediscluster_webhook.go b/api/v1beta2/rediscluster_webhook.go index 4e7640540..4b69b0b5a 100644 --- a/api/v1beta2/rediscluster_webhook.go +++ b/api/v1beta2/rediscluster_webhook.go @@ -18,12 +18,8 @@ package v1beta2 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var redisclusterlog = logf.Log.WithName("rediscluster-resource") - func (r *RedisCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/api/v1beta2/redisreplication_webhook.go b/api/v1beta2/redisreplication_webhook.go index fa49a9b03..3474d59cd 100644 --- a/api/v1beta2/redisreplication_webhook.go +++ b/api/v1beta2/redisreplication_webhook.go @@ -18,12 +18,8 @@ package v1beta2 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var redisreplicationlog = logf.Log.WithName("redisreplication-resource") - func (r *RedisReplication) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/api/v1beta2/redissentinel_webhook.go b/api/v1beta2/redissentinel_webhook.go index e0987ac96..356f2a0d4 100644 --- a/api/v1beta2/redissentinel_webhook.go +++ b/api/v1beta2/redissentinel_webhook.go @@ -18,12 +18,8 @@ package v1beta2 import ( ctrl "sigs.k8s.io/controller-runtime" - logf "sigs.k8s.io/controller-runtime/pkg/log" ) -// log is for logging in this package. -var redissentinellog = logf.Log.WithName("redissentinel-resource") - func (r *RedisSentinel) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). For(r). diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index a1d8be2b7..9b07469f8 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -53,11 +53,11 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl reqLogger.Info("Found annotations redis.opstreelabs.in/skip-reconcile, so skipping reconcile") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } - if err := k8sutils.HandleRedisFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisFinalizer(instance, r.Client); err != nil { return ctrl.Result{}, err } - if err := k8sutils.AddRedisFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddRedisFinalizer(instance, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 02b577055..d1d9b18a8 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -61,11 +61,11 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request followerReplicas := instance.Spec.GetReplicaCounts("follower") totalReplicas := leaderReplicas + followerReplicas - if err := k8sutils.HandleRedisClusterFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisClusterFinalizer(instance, r.Client); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } - if err := k8sutils.AddRedisClusterFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddRedisClusterFinalizer(instance, r.Client); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index d0e4f30e8..086f5658a 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -44,11 +44,11 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req followerReplicas := instance.Spec.GetReplicationCounts("replication") - leaderReplicas totalReplicas := leaderReplicas + followerReplicas - if err := k8sutils.HandleRedisReplicationFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisReplicationFinalizer(instance, r.Client); err != nil { return ctrl.Result{}, err } - if err := k8sutils.AddRedisReplicationFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddRedisReplicationFinalizer(instance, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index b4b0b02bf..71e8583eb 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -42,11 +42,11 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques // Get total Sentinel Replicas // sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel") - if err := k8sutils.HandleRedisSentinelFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisSentinelFinalizer(instance, r.Client); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } - if err := k8sutils.AddRedisSentinelFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddRedisSentinelFinalizer(instance, r.Client); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 7d0160d1e..3029afea9 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -120,7 +120,7 @@ func CreateOrUpdatePodDisruptionBudget(pdbDef *policyv1.PodDisruptionBudget) err logger := pdbLogger(pdbDef.Namespace, pdbDef.Name) storedPDB, err := GetPodDisruptionBudget(pdbDef.Namespace, pdbDef.Name) if err != nil { - if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(pdbDef); err != nil { + if err = patch.DefaultAnnotator.SetLastAppliedAnnotation(pdbDef); err != nil { logger.Error(err, "Unable to patch redis PodDisruptionBudget with comparison object") return err } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index d9a77abfa..a3004bf1e 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -255,7 +255,7 @@ func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { if err != nil { logger.Error(err, "Redis command failed with this error") flushcommand := redis.NewStringCmd("flushall") - err := client.Process(flushcommand) + err = client.Process(flushcommand) if err != nil { logger.Error(err, "Redis flush command failed with this error") return err diff --git a/k8sutils/services.go b/k8sutils/services.go index d7ba204fb..9db0f340b 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -137,7 +137,7 @@ func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, owne storedService, err := getService(namespace, serviceMeta.Name) if err != nil { if errors.IsNotFound(err) { - if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil { + if err = patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil { logger.Error(err, "Unable to patch redis service with compare annotations") } return createService(namespace, serviceDef) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 9593b5369..cf219bdac 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -93,7 +93,7 @@ func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params storedStateful, err := GetStatefulSet(namespace, stsMeta.Name) statefulSetDef := generateStatefulSetsDef(stsMeta, params, ownerDef, initcontainerParams, containerParams, getSidecars(sidecars)) if err != nil { - if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil { + if err = patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil { logger.Error(err, "Unable to patch redis statefulset with comparison object") return err } @@ -661,7 +661,7 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS } logger.V(1).Info("recreating StatefulSet because the update operation wasn't possible", "reason", strings.Join(failMsg, ", ")) propagationPolicy := metav1.DeletePropagationForeground - if err := generateK8sClient().AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { + if err = generateK8sClient().AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { return errors.Wrap(err, "failed to delete StatefulSet to avoid forbidden action") } } From 97751a2b5bc4ec07f7db179d5ee356e1e1e5935b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:33:39 +0530 Subject: [PATCH 019/203] Bump postcss from 8.2.9 to 8.4.31 in /docs (#654) Bumps [postcss](https://github.com/postcss/postcss) from 8.2.9 to 8.4.31. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.2.9...8.4.31) --- updated-dependencies: - dependency-name: postcss dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package.json b/docs/package.json index fa425acca..1c55babf8 100644 --- a/docs/package.json +++ b/docs/package.json @@ -1,7 +1,7 @@ { "dependencies": { "postcss-cli": "8.3.1", - "postcss": "8.2.9", + "postcss": "8.4.31", "autoprefixer": "10.2.5" } } From 6bbc0b13bb25d52a909b6ae3c70f1af1e966143d Mon Sep 17 00:00:00 2001 From: Azanul Haque <42029519+Azanul@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:58:51 +0530 Subject: [PATCH 020/203] Dependencies upgrade (#651) * Dependencies upgrade Signed-off-by: Azanul * controller runtime options upgrade Signed-off-by: Azanul * CI go version upgrade Signed-off-by: Azanul * Dockerfile go version upgrade Signed-off-by: Azanul * fix lint bool pointer Signed-off-by: Shubham Gupta * fix pointer.BoolPtr Signed-off-by: Shubham Gupta * fix lint exec.Stream Signed-off-by: Shubham Gupta --------- Signed-off-by: Azanul Signed-off-by: Shubham Gupta Co-authored-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 2 +- .golangci.yml | 2 +- Dockerfile | 2 +- go.mod | 87 ++- go.sum | 865 ++++------------------------- k8sutils/labels_test.go | 6 +- k8sutils/redis.go | 2 +- main.go | 17 +- 8 files changed, 170 insertions(+), 813 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 0ab72a51d..bae7dc7b2 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -8,7 +8,7 @@ on: - master env: - GolangVersion: 1.17 + GolangVersion: 1.21 ApplicationName: redis-operator DockerImagName: docker.io/opstree/redis-operator BuildDocs: true diff --git a/.golangci.yml b/.golangci.yml index 4895afc04..603eccad5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,7 +22,7 @@ issues: - gosec run: timeout: 5m - go-version: "1.17" + go-version: "1.21" test: false # Exclude third-party packages and go.mod from the lint checks exclude: | diff --git a/Dockerfile b/Dockerfile index c643513b6..2bf6f87f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.17 as builder +FROM golang:1.21 as builder ARG BUILDOS ARG BUILDPLATFORM ARG BUILDARCH diff --git a/go.mod b/go.mod index 705b08c46..32084681a 100644 --- a/go.mod +++ b/go.mod @@ -1,79 +1,78 @@ module github.com/OT-CONTAINER-KIT/redis-operator -go 1.17 +go 1.21 require ( github.com/banzaicloud/k8s-objectmatcher v1.7.0 - github.com/go-logr/logr v1.2.2 + github.com/go-logr/logr v1.2.4 github.com/go-redis/redis v6.15.9+incompatible github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.17.0 + github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 - k8s.io/api v0.23.0 - k8s.io/apimachinery v0.23.0 - k8s.io/client-go v0.23.0 - k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b - sigs.k8s.io/controller-runtime v0.11.0 + k8s.io/api v0.28.2 + k8s.io/apimachinery v0.28.2 + k8s.io/client-go v0.28.2 + k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 + sigs.k8s.io/controller-runtime v0.16.2 ) require ( - cloud.google.com/go v0.81.0 // indirect emperror.dev/errors v0.8.0 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.18 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect - github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/go-logr/zapr v1.2.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/go-cmp v0.5.5 // indirect - github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/googleapis/gnostic v0.5.5 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.12 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect - github.com/prometheus/client_golang v1.11.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.28.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.4 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.19.1 // indirect - golang.org/x/crypto v0.13.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.25.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/net v0.15.0 // indirect - golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect + golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/sys v0.12.0 // indirect golang.org/x/term v0.12.0 // indirect golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + golang.org/x/time v0.3.0 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.27.1 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.23.0 // indirect - k8s.io/component-base v0.23.0 // indirect - k8s.io/klog/v2 v2.30.0 // indirect - k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect - sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect + k8s.io/apiextensions-apiserver v0.28.0 // indirect + k8s.io/component-base v0.28.1 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index e3b8f89b6..e4c74033a 100644 --- a/go.sum +++ b/go.sum @@ -1,217 +1,79 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= emperror.dev/errors v0.8.0 h1:4lycVEx0sdJkwDUfQ9pdu6SR0x7rgympt5f4+ok8jDk= emperror.dev/errors v0.8.0/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/banzaicloud/k8s-objectmatcher v1.7.0 h1:6ufo47TaPC0jXJPg8d8/oooCy1ma3vEfM0J8ZbomKaw= github.com/banzaicloud/k8s-objectmatcher v1.7.0/go.mod h1:DSctpi6o9FqTfX7RluuEBeRLUahoDC7JavCeuu6Y+sg= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -219,144 +81,60 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.9.0/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -365,565 +143,166 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.28.0 h1:vGVfV9KrDTvWt5boZO0I19g2E3CsWfpPPKZM9dt3mEw= -github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= +go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -933,90 +312,60 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.23.0 h1:WrL1gb73VSC8obi8cuYETJGXEoFNEh3LU0Pt+Sokgro= -k8s.io/api v0.23.0/go.mod h1:8wmDdLBHBNxtOIytwLstXt5E9PddnZb0GaMcqsvDBpg= -k8s.io/apiextensions-apiserver v0.23.0 h1:uii8BYmHYiT2ZTAJxmvc3X8UhNYMxl2A0z0Xq3Pm+WY= -k8s.io/apiextensions-apiserver v0.23.0/go.mod h1:xIFAEEDlAZgpVBl/1VSjGDmLoXAWRG40+GsWhKhAxY4= +k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= +k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.23.0 h1:mIfWRMjBuMdolAWJ3Fd+aPTMv3X9z+waiARMpvvb0HQ= -k8s.io/apimachinery v0.23.0/go.mod h1:fFCTTBKvKcwTPFzjlcxp91uPFZr+JA0FubU4fLzzFYc= -k8s.io/apiserver v0.23.0/go.mod h1:Cec35u/9zAepDPPFyT+UMrgqOCjgJ5qtfVJDxjZYmt4= -k8s.io/client-go v0.23.0 h1:vcsOqyPq7XV3QmQRCBH/t9BICJM9Q1M18qahjv+rebY= -k8s.io/client-go v0.23.0/go.mod h1:hrDnpnK1mSr65lHHcUuIZIXDgEbzc7/683c6hyG4jTA= -k8s.io/code-generator v0.23.0/go.mod h1:vQvOhDXhuzqiVfM/YHp+dmg10WDZCchJVObc9MvowsE= -k8s.io/component-base v0.23.0 h1:UAnyzjvVZ2ZR1lF35YwtNY6VMN94WtOnArcXBu34es8= -k8s.io/component-base v0.23.0/go.mod h1:DHH5uiFvLC1edCpvcTDV++NKULdYYU6pR9Tt3HIKMKI= +k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= +k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= +k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= +k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= +k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= +k8s.io/component-base v0.28.1/go.mod h1:jI11OyhbX21Qtbav7JkhehyBsIRfnO8oEgoAR12ArIU= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.25/go.mod h1:Mlj9PNLmG9bZ6BHFwFKDo5afkpWyUISkb9Me0GnK66I= -sigs.k8s.io/controller-runtime v0.11.0 h1:DqO+c8mywcZLFJWILq4iktoECTyn30Bkj0CwgqMpZWQ= -sigs.k8s.io/controller-runtime v0.11.0/go.mod h1:KKwLiTooNGu+JmLZGn9Sl3Gjmfj66eMbCQznLP5zcqA= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= +k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= +k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.0 h1:kDvPBbnPk+qYmkHmSo8vKGp438IASWofnbbUKDE/bv0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.0/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go index c04d8ca56..ba638fc27 100644 --- a/k8sutils/labels_test.go +++ b/k8sutils/labels_test.go @@ -288,7 +288,7 @@ func TestRedisClusterAsOwner(t *testing.T) { Kind: "RedisCluster", Name: "test-redis-cluster", UID: "abcdef", - Controller: pointer.BoolPtr(true), + Controller: pointer.Bool(true), } result := redisClusterAsOwner(clusterObj) @@ -315,7 +315,7 @@ func TestRedisReplicationAsOwner(t *testing.T) { Kind: "RedisReplication", Name: "test-redis-replication", UID: "ghijkl", - Controller: pointer.BoolPtr(true), + Controller: pointer.Bool(true), } result := redisReplicationAsOwner(replicationObj) @@ -342,7 +342,7 @@ func TestRedisSentinelAsOwner(t *testing.T) { Kind: "RedisSentinel", Name: "test-redis-sentinel", UID: "mnopqr", - Controller: pointer.BoolPtr(true), + Controller: pointer.Bool(true), } result := redisSentinelAsOwner(sentinelObj) diff --git a/k8sutils/redis.go b/k8sutils/redis.go index a3004bf1e..f7bbcb576 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -382,7 +382,7 @@ func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) return } - err = exec.Stream(remotecommand.StreamOptions{ + err = exec.StreamWithContext(context.Background(), remotecommand.StreamOptions{ Stdout: &execOut, Stderr: &execErr, Tty: false, diff --git a/main.go b/main.go index d6b1cb761..70d82f333 100644 --- a/main.go +++ b/main.go @@ -28,8 +28,11 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/controllers" @@ -73,16 +76,22 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) options := ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, + Scheme: scheme, + Metrics: server.Options{ + BindAddress: metricsAddr, + }, + WebhookServer: &webhook.DefaultServer{ + Options: webhook.Options{ + Port: 9443, + }, + }, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "6cab913b.redis.opstreelabs.in", } if ns := os.Getenv("WATCH_NAMESPACE"); ns != "" { - options.Namespace = ns + options.Cache.DefaultNamespaces = map[string]cache.Config{ns: {}} } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) From 57883c067cc3a02563437f54123db04f3292e9df Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 4 Oct 2023 22:03:55 +0530 Subject: [PATCH 021/203] redis_test - unit test (#655) Signed-off-by: Shubham Gupta --- go.mod | 3 +- k8sutils/services_test.go | 230 ++++++++++++++++++++ k8sutils/statefulset_test.go | 392 +++++++++++++++++++++++++++++++++++ 3 files changed, 624 insertions(+), 1 deletion(-) create mode 100644 k8sutils/services_test.go create mode 100644 k8sutils/statefulset_test.go diff --git a/go.mod b/go.mod index 32084681a..161af7150 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 + github.com/stretchr/testify v1.8.4 k8s.io/api v0.28.2 k8s.io/apimachinery v0.28.2 k8s.io/client-go v0.28.2 @@ -46,12 +47,12 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect diff --git a/k8sutils/services_test.go b/k8sutils/services_test.go new file mode 100644 index 000000000..035583779 --- /dev/null +++ b/k8sutils/services_test.go @@ -0,0 +1,230 @@ +package k8sutils + +import ( + "testing" + + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func TestGenerateServiceDef(t *testing.T) { + tests := []struct { + name string + serviceMeta metav1.ObjectMeta + enableMetrics bool + headless bool + serviceType string + expected *corev1.Service + }{ + { + name: "Test sentinel with ClusterIP service type", + serviceMeta: metav1.ObjectMeta{ + Name: "test-service", + Labels: map[string]string{ + "role": "sentinel", + }, + }, + enableMetrics: false, + headless: false, + serviceType: "ClusterIP", + expected: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + Kind: "Service", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Labels: map[string]string{ + "role": "sentinel", + }, + OwnerReferences: []metav1.OwnerReference{ + {}, + }, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "sentinel-client", + Port: sentinelPort, + TargetPort: intstr.FromInt(int(sentinelPort)), + Protocol: corev1.ProtocolTCP, + }, + }, + Selector: map[string]string{"role": "sentinel"}, + ClusterIP: "", + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + name: "Test sentinel with headless service", + serviceMeta: metav1.ObjectMeta{ + Name: "test-service", + Labels: map[string]string{ + "role": "sentinel", + }, + }, + enableMetrics: false, + headless: true, + serviceType: "ClusterIP", + expected: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + Kind: "Service", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Labels: map[string]string{ + "role": "sentinel", + }, + OwnerReferences: []metav1.OwnerReference{ + {}, + }, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "sentinel-client", + Port: sentinelPort, + TargetPort: intstr.FromInt(int(sentinelPort)), + Protocol: corev1.ProtocolTCP, + }, + }, + Selector: map[string]string{"role": "sentinel"}, + ClusterIP: "None", + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + name: "Test redis with ClusterIP service type", + serviceMeta: metav1.ObjectMeta{ + Name: "test-redis-service", + Labels: map[string]string{ + "role": "redis", + }, + }, + enableMetrics: false, + headless: false, + serviceType: "ClusterIP", + expected: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + Kind: "Service", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-service", + Labels: map[string]string{ + "role": "redis", + }, + OwnerReferences: []metav1.OwnerReference{ + {}, + }, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "redis-client", + Port: redisPort, + TargetPort: intstr.FromInt(int(redisPort)), + Protocol: corev1.ProtocolTCP, + }, + }, + Selector: map[string]string{"role": "redis"}, + ClusterIP: "", + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + name: "Test redis with headless service", + serviceMeta: metav1.ObjectMeta{ + Name: "test-redis-headless-service", + Labels: map[string]string{ + "role": "redis", + }, + }, + enableMetrics: false, + headless: true, + serviceType: "ClusterIP", + expected: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + Kind: "Service", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-headless-service", + Labels: map[string]string{ + "role": "redis", + }, + OwnerReferences: []metav1.OwnerReference{ + {}, + }, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "redis-client", + Port: redisPort, + TargetPort: intstr.FromInt(int(redisPort)), + Protocol: corev1.ProtocolTCP, + }, + }, + Selector: map[string]string{"role": "redis"}, + ClusterIP: "None", + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + name: "Test redis with ClusterIP service type and metrics enabled", + serviceMeta: metav1.ObjectMeta{ + Name: "test-redis-metrics-service", + Labels: map[string]string{ + "role": "redis", + }, + }, + enableMetrics: true, + headless: false, + serviceType: "ClusterIP", + expected: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + Kind: "Service", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-metrics-service", + Labels: map[string]string{ + "role": "redis", + }, + OwnerReferences: []metav1.OwnerReference{ + {}, + }, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "redis-client", + Port: redisPort, + TargetPort: intstr.FromInt(int(redisPort)), + Protocol: corev1.ProtocolTCP, + }, + *enableMetricsPort(), + }, + Selector: map[string]string{"role": "redis"}, + ClusterIP: "", + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := generateServiceDef(tt.serviceMeta, tt.enableMetrics, metav1.OwnerReference{}, tt.headless, tt.serviceType) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go new file mode 100644 index 000000000..1bb954166 --- /dev/null +++ b/k8sutils/statefulset_test.go @@ -0,0 +1,392 @@ +package k8sutils + +import ( + "path" + "testing" + + common "github.com/OT-CONTAINER-KIT/redis-operator/api" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" +) + +func TestGetVolumeMount(t *testing.T) { + tests := []struct { + name string + persistenceEnabled *bool + clusterMode bool + nodeConfVolume bool + externalConfig *string + mountpath []corev1.VolumeMount + tlsConfig *redisv1beta2.TLSConfig + aclConfig *redisv1beta2.ACLConfig + expectedMounts []corev1.VolumeMount + }{ + { + name: "1. All false or nil", + persistenceEnabled: nil, + clusterMode: false, + nodeConfVolume: false, + externalConfig: nil, + mountpath: []corev1.VolumeMount{}, + tlsConfig: nil, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{}, + }, + { + name: "2. Persistence enabled with cluster mode and node conf", + persistenceEnabled: pointer.Bool(true), + clusterMode: true, + nodeConfVolume: true, + externalConfig: nil, + mountpath: []corev1.VolumeMount{}, + tlsConfig: nil, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{ + { + Name: "persistent-volume", + MountPath: "/data", + }, + { + Name: "node-conf", + MountPath: "/node-conf", + }, + }, + }, + { + name: "3. Persistence enabled with cluster mode and external config", + persistenceEnabled: pointer.Bool(true), + clusterMode: true, + nodeConfVolume: false, + externalConfig: pointer.String("some-config"), + mountpath: []corev1.VolumeMount{}, + tlsConfig: nil, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{ + { + Name: "persistent-volume", + MountPath: "/data", + }, + { + Name: "external-config", + MountPath: "/etc/redis/external.conf.d", + }, + }, + }, + { + name: "4. Persistence enabled, cluster mode false, node conf true, no tls/acl, with mountpath", + persistenceEnabled: pointer.Bool(true), + clusterMode: false, + nodeConfVolume: true, + externalConfig: nil, + mountpath: []corev1.VolumeMount{ + { + Name: "additional-mount", + MountPath: "/additional", + }, + }, + tlsConfig: nil, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{{Name: "persistent-volume", MountPath: "/data"}, {Name: "additional-mount", MountPath: "/additional"}}, + }, + { + name: "5. Only tls enabled", + persistenceEnabled: nil, + clusterMode: false, + nodeConfVolume: false, + externalConfig: nil, + mountpath: []corev1.VolumeMount{}, + tlsConfig: &redisv1beta2.TLSConfig{}, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{{Name: "tls-certs", MountPath: "/tls", ReadOnly: true}}, + }, + { + name: "6. Only acl enabled", + persistenceEnabled: nil, + clusterMode: false, + nodeConfVolume: false, + externalConfig: nil, + mountpath: []corev1.VolumeMount{}, + tlsConfig: nil, + aclConfig: &redisv1beta2.ACLConfig{}, + expectedMounts: []corev1.VolumeMount{{Name: "acl-secret", MountPath: "/etc/redis/user.acl", SubPath: "user.acl"}}, + }, + { + name: "7. Everything enabled except externalConfig", + persistenceEnabled: pointer.Bool(true), + clusterMode: true, + nodeConfVolume: true, + externalConfig: nil, + mountpath: []corev1.VolumeMount{ + { + Name: "additional-mount", + MountPath: "/additional", + }, + }, + tlsConfig: &redisv1beta2.TLSConfig{}, + aclConfig: &redisv1beta2.ACLConfig{}, + expectedMounts: []corev1.VolumeMount{ + {Name: "persistent-volume", MountPath: "/data"}, + {Name: "node-conf", MountPath: "/node-conf"}, + {Name: "tls-certs", MountPath: "/tls", ReadOnly: true}, + {Name: "acl-secret", MountPath: "/etc/redis/user.acl", SubPath: "user.acl"}, + {Name: "additional-mount", MountPath: "/additional"}, + }, + }, + { + name: "8. Only externalConfig enabled", + persistenceEnabled: nil, + clusterMode: false, + nodeConfVolume: false, + externalConfig: pointer.String("some-config"), + mountpath: []corev1.VolumeMount{}, + tlsConfig: nil, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{{Name: "external-config", MountPath: "/etc/redis/external.conf.d"}}, + }, + { + name: "9. Persistence enabled, cluster mode true, node conf true, only acl enabled", + persistenceEnabled: pointer.Bool(true), + clusterMode: true, + nodeConfVolume: true, + externalConfig: nil, + mountpath: []corev1.VolumeMount{}, + tlsConfig: nil, + aclConfig: &redisv1beta2.ACLConfig{}, + expectedMounts: []corev1.VolumeMount{ + {Name: "persistent-volume", MountPath: "/data"}, + {Name: "node-conf", MountPath: "/node-conf"}, + {Name: "acl-secret", MountPath: "/etc/redis/user.acl", SubPath: "user.acl"}, + }, + }, + { + name: "10. Persistence enabled, cluster mode false, node conf false, only tls enabled with mountpath", + persistenceEnabled: pointer.Bool(true), + clusterMode: false, + nodeConfVolume: false, + externalConfig: nil, + mountpath: []corev1.VolumeMount{ + { + Name: "additional-mount", + MountPath: "/additional", + }, + }, + tlsConfig: &redisv1beta2.TLSConfig{}, + aclConfig: nil, + expectedMounts: []corev1.VolumeMount{{Name: "persistent-volume", MountPath: "/data"}, {Name: "tls-certs", MountPath: "/tls", ReadOnly: true}, {Name: "additional-mount", MountPath: "/additional"}}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getVolumeMount("persistent-volume", tt.persistenceEnabled, tt.clusterMode, tt.nodeConfVolume, tt.externalConfig, tt.mountpath, tt.tlsConfig, tt.aclConfig) + assert.ElementsMatch(t, tt.expectedMounts, got) + }) + } +} + +func TestGenerateTLSEnvironmentVariables(t *testing.T) { + tlsConfig := &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "test_ca.crt", + CertKeyFile: "test_tls.crt", + KeyFile: "test_tls.key", + }, + } + + envVars := GenerateTLSEnvironmentVariables(tlsConfig) + + expectedEnvVars := []corev1.EnvVar{ + { + Name: "TLS_MODE", + Value: "true", + }, + { + Name: "REDIS_TLS_CA_KEY", + Value: path.Join("/tls/", "test_ca.crt"), + }, + { + Name: "REDIS_TLS_CERT", + Value: path.Join("/tls/", "test_tls.crt"), + }, + { + Name: "REDIS_TLS_CERT_KEY", + Value: path.Join("/tls/", "test_tls.key"), + }, + } + assert.ElementsMatch(t, envVars, expectedEnvVars, "EnvVars generated for TLS config are not as expected") +} + +func TestGetEnvironmentVariables(t *testing.T) { + tests := []struct { + name string + role string + enabledMetric bool + enabledPassword *bool + secretName *string + secretKey *string + persistenceEnabled *bool + exporterEnvVar *[]corev1.EnvVar + tlsConfig *redisv1beta2.TLSConfig + aclConfig *redisv1beta2.ACLConfig + envVar *[]corev1.EnvVar + expectedEnvironment []corev1.EnvVar + }{ + { + name: "Test with role sentinel, metrics true, password true, persistence true, exporter env, tls enabled, acl enabled and env var", + role: "sentinel", + enabledMetric: true, + enabledPassword: pointer.Bool(true), + secretName: pointer.String("test-secret"), + secretKey: pointer.String("test-key"), + persistenceEnabled: pointer.Bool(true), + exporterEnvVar: &[]corev1.EnvVar{ + {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, + }, + tlsConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "test_ca.crt", + CertKeyFile: "test_tls.crt", + KeyFile: "test_tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "tls-secret", + }, + }, + }, + aclConfig: &redisv1beta2.ACLConfig{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "acl-secret", + }, + }, + envVar: &[]corev1.EnvVar{ + {Name: "TEST_ENV", Value: "test-value"}, + }, + expectedEnvironment: []corev1.EnvVar{ + {Name: "ACL_MODE", Value: "true"}, + {Name: "PERSISTENCE_ENABLED", Value: "true"}, + {Name: "REDIS_ADDR", Value: "redis://localhost:26379"}, + {Name: "REDIS_EXPORTER_SKIP_TLS_VERIFICATION", Value: "true"}, + {Name: "REDIS_EXPORTER_TLS_CA_CERT_FILE", Value: "/tls/ca.crt"}, + {Name: "REDIS_EXPORTER_TLS_CLIENT_CERT_FILE", Value: "/tls/tls.crt"}, + {Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", Value: "/tls/tls.key"}, + {Name: "TLS_MODE", Value: "true"}, + {Name: "REDIS_TLS_CA_KEY", Value: path.Join("/tls/", "test_ca.crt")}, + {Name: "REDIS_TLS_CERT", Value: path.Join("/tls/", "test_tls.crt")}, + {Name: "REDIS_TLS_CERT_KEY", Value: path.Join("/tls/", "test_tls.key")}, + {Name: "REDIS_PASSWORD", ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "test-secret", + }, + Key: "test-key", + }, + }}, + {Name: "SERVER_MODE", Value: "sentinel"}, + {Name: "SETUP_MODE", Value: "sentinel"}, + {Name: "TEST_ENV", Value: "test-value"}, + {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, + }, + }, + { + name: "Test with role redis, metrics false, password nil, persistence nil, exporter nil, tls nil, acl nil and nil env var", + role: "redis", + enabledMetric: false, + enabledPassword: nil, + secretName: nil, + secretKey: nil, + persistenceEnabled: nil, + exporterEnvVar: nil, + tlsConfig: nil, + aclConfig: nil, + envVar: nil, + expectedEnvironment: []corev1.EnvVar{ + {Name: "REDIS_ADDR", Value: "redis://localhost:6379"}, + {Name: "SERVER_MODE", Value: "redis"}, + {Name: "SETUP_MODE", Value: "redis"}, + }, + }, + { + name: "Test with role redis, metrics false, password nil, persistence false, exporter nil, tls nil, acl nil and nil env var", + role: "sentinel", + enabledMetric: false, + enabledPassword: nil, + secretName: nil, + secretKey: nil, + persistenceEnabled: pointer.Bool(false), + exporterEnvVar: nil, + tlsConfig: nil, + aclConfig: nil, + envVar: nil, + expectedEnvironment: []corev1.EnvVar{ + {Name: "REDIS_ADDR", Value: "redis://localhost:26379"}, + {Name: "SERVER_MODE", Value: "sentinel"}, + {Name: "SETUP_MODE", Value: "sentinel"}, + }, + }, + { + name: "Test with role cluster, metrics true, password true, persistence true, exporter env, tls nil, acl enabled and env var", + role: "cluster", + enabledMetric: true, + enabledPassword: pointer.Bool(true), + secretName: pointer.String("test-secret"), + secretKey: pointer.String("test-key"), + persistenceEnabled: pointer.Bool(true), + exporterEnvVar: &[]corev1.EnvVar{ + {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, + }, + tlsConfig: nil, + aclConfig: &redisv1beta2.ACLConfig{}, + envVar: &[]corev1.EnvVar{ + {Name: "TEST_ENV", Value: "test-value"}, + }, + expectedEnvironment: []corev1.EnvVar{ + {Name: "ACL_MODE", Value: "true"}, + {Name: "PERSISTENCE_ENABLED", Value: "true"}, + {Name: "REDIS_ADDR", Value: "redis://localhost:6379"}, + {Name: "REDIS_PASSWORD", ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "test-secret", + }, + Key: "test-key", + }, + }}, + {Name: "SERVER_MODE", Value: "cluster"}, + {Name: "SETUP_MODE", Value: "cluster"}, + {Name: "TEST_ENV", Value: "test-value"}, + {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, + }, + }, + { + name: "Test with cluster role and only metrics enabled", + role: "cluster", + enabledMetric: true, + enabledPassword: nil, + secretName: nil, + secretKey: nil, + persistenceEnabled: nil, + exporterEnvVar: &[]corev1.EnvVar{ + {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, + }, + tlsConfig: nil, + aclConfig: nil, + envVar: nil, + expectedEnvironment: []corev1.EnvVar{ + {Name: "REDIS_ADDR", Value: "redis://localhost:6379"}, + {Name: "SERVER_MODE", Value: "cluster"}, + {Name: "SETUP_MODE", Value: "cluster"}, + {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actualEnvironment := getEnvironmentVariables(tt.role, tt.enabledMetric, tt.enabledPassword, tt.secretName, + tt.secretKey, tt.persistenceEnabled, tt.exporterEnvVar, tt.tlsConfig, tt.aclConfig, tt.envVar) + + assert.ElementsMatch(t, tt.expectedEnvironment, actualEnvironment) + }) + } +} From ab69ce511ae6f000d6e3d8a7d315a675666d0976 Mon Sep 17 00:00:00 2001 From: Azanul Haque <42029519+Azanul@users.noreply.github.com> Date: Fri, 6 Oct 2023 01:37:48 +0530 Subject: [PATCH 022/203] Redis SDK version update (#657) Signed-off-by: Azanul --- .golangci.yml | 2 +- controllers/rediscluster_controller.go | 26 ++++----- controllers/redisreplication_controller.go | 8 +-- controllers/redissentinel_controller.go | 2 +- go.mod | 3 +- go.sum | 10 +++- k8sutils/cluster-scaling.go | 66 +++++++++++----------- k8sutils/redis-sentinel.go | 22 ++++---- k8sutils/redis.go | 62 ++++++++++---------- 9 files changed, 105 insertions(+), 96 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 603eccad5..2a38a4fa8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -34,7 +34,7 @@ run: - k8s.io/client-go - github.com/banzaicloud/k8s-objectmatcher - github.com/go-logr/logr - - github.com/go-redis/redis + - github.com/redis/go-redis - github.com/onsi/ginkgo - github.com/onsi/gomega - github.com/pkg/errors diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index d1d9b18a8..98530728d 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -76,19 +76,19 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // check whether the redis is leader or not ? // if not true then make it leader pod - if !(k8sutils.VerifyLeaderPod(instance)) { + if !(k8sutils.VerifyLeaderPod(ctx, instance)) { // lastLeaderPod is slaving right now Make it the master Pod // We have to bring a manual failover here to make it a leaderPod // clusterFailover should also include the clusterReplicate since we have to map the followers to new leader - k8sutils.ClusterFailover(instance) + k8sutils.ClusterFailover(ctx, instance) } // Step 1 Rehard the Cluster k8sutils.ReshardRedisCluster(instance) // Step 2 Remove the Follower Node - k8sutils.RemoveRedisFollowerNodesFromCluster(instance) + k8sutils.RemoveRedisFollowerNodesFromCluster(ctx, instance) // Step 3 Remove the Leader Node - k8sutils.RemoveRedisNodeFromCluster(instance) + k8sutils.RemoveRedisNodeFromCluster(ctx, instance) // Step 4 Rebalance the cluster k8sutils.RebalanceRedisCluster(instance) return ctrl.Result{RequeueAfter: time.Second * 100}, nil @@ -175,17 +175,17 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) - if k8sutils.CheckRedisNodeCount(instance, "") != totalReplicas { - leaderCount := k8sutils.CheckRedisNodeCount(instance, "leader") + if k8sutils.CheckRedisNodeCount(ctx, instance, "") != totalReplicas { + leaderCount := k8sutils.CheckRedisNodeCount(ctx, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) if leaderCount <= 2 { - k8sutils.ExecuteRedisClusterCommand(instance) + k8sutils.ExecuteRedisClusterCommand(ctx, instance) } else { if leaderCount < leaderReplicas { // Scale up the cluster // Step 2 : Add Redis Node - k8sutils.AddRedisNodeToCluster(instance) + k8sutils.AddRedisNodeToCluster(ctx, instance) // Step 3 Rebalance the cluster using the empty masters k8sutils.RebalanceRedisClusterEmptyMasters(instance) } @@ -193,16 +193,16 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } else { if followerReplicas > 0 && redisFollowerInfo.Status.ReadyReplicas == followerReplicas { reqLogger.Info("All leader are part of the cluster, adding follower/replicas", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas, "Follower.Replicas", followerReplicas) - k8sutils.ExecuteRedisReplicationCommand(instance) + k8sutils.ExecuteRedisReplicationCommand(ctx, instance) } else { reqLogger.Info("no follower/replicas configured, skipping replication configuration", "Leaders.Count", leaderCount, "Leader.Size", leaderReplicas, "Follower.Replicas", followerReplicas) } } } else { reqLogger.Info("Redis leader count is desired") - if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(instance) >= int(totalReplicas)-1 { + if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(ctx, instance) >= int(totalReplicas)-1 { reqLogger.Info("Redis leader is not desired, executing failover operation") - err = k8sutils.ExecuteFailoverOperation(instance) + err = k8sutils.ExecuteFailoverOperation(ctx, instance) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 10}, err } @@ -211,8 +211,8 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Check If there is No Empty Master Node - if k8sutils.CheckRedisNodeCount(instance, "") == totalReplicas { - k8sutils.CheckIfEmptyMasters(instance) + if k8sutils.CheckRedisNodeCount(ctx, instance, "") == totalReplicas { + k8sutils.CheckIfEmptyMasters(ctx, instance) } reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 086f5658a..ab7efb08e 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -76,11 +76,11 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) - if len(k8sutils.GetRedisNodesByRole(instance, "master")) > int(leaderReplicas) { + if len(k8sutils.GetRedisNodesByRole(ctx, instance, "master")) > int(leaderReplicas) { - masterNodes := k8sutils.GetRedisNodesByRole(instance, "master") - slaveNodes := k8sutils.GetRedisNodesByRole(instance, "slave") - err := k8sutils.CreateMasterSlaveReplication(instance, masterNodes, slaveNodes) + masterNodes := k8sutils.GetRedisNodesByRole(ctx, instance, "master") + slaveNodes := k8sutils.GetRedisNodesByRole(ctx, instance, "slave") + err := k8sutils.CreateMasterSlaveReplication(ctx, instance, masterNodes, slaveNodes) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 71e8583eb..33170cff1 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -51,7 +51,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Create Redis Sentinel - err = k8sutils.CreateRedisSentinel(instance) + err = k8sutils.CreateRedisSentinel(ctx, instance) if err != nil { return ctrl.Result{}, err } diff --git a/go.mod b/go.mod index 161af7150..ed287b58b 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,10 @@ go 1.21 require ( github.com/banzaicloud/k8s-objectmatcher v1.7.0 github.com/go-logr/logr v1.2.4 - github.com/go-redis/redis v6.15.9+incompatible github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 + github.com/redis/go-redis/v9 v9.2.1 github.com/stretchr/testify v1.8.4 k8s.io/api v0.28.2 k8s.io/apimachinery v0.28.2 @@ -22,6 +22,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect diff --git a/go.sum b/go.sum index e4c74033a..8eedf22f0 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,10 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -22,6 +26,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -57,8 +63,6 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= -github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= @@ -177,6 +181,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index f15867ac0..f58279834 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -1,18 +1,20 @@ package k8sutils import ( + "context" "strconv" "strings" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - "github.com/go-redis/redis" + redis "github.com/redis/go-redis/v9" ) // Reshard the redis Cluster func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { + ctx := context.TODO() logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") // Transfer Pod details transferPOD := RedisDetails{ @@ -46,17 +48,17 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { //--cluster-from --cluster-to --cluster-slots --cluster-yes // Remove Node - removeNodeID := getRedisNodeID(cr, removePOD) + removeNodeID := getRedisNodeID(ctx, cr, removePOD) cmd = append(cmd, "--cluster-from") cmd = append(cmd, removeNodeID) // Transfer Node - transferNodeID := getRedisNodeID(cr, transferPOD) + transferNodeID := getRedisNodeID(ctx, cr, transferPOD) cmd = append(cmd, "--cluster-to") cmd = append(cmd, transferNodeID) // Cluster Slots - slot := getRedisClusterSlots(cr, removeNodeID) + slot := getRedisClusterSlots(ctx, cr, removeNodeID) cmd = append(cmd, "--cluster-slots") cmd = append(cmd, slot) @@ -71,13 +73,13 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") } -func getRedisClusterSlots(cr *redisv1beta2.RedisCluster, nodeID string) string { +func getRedisClusterSlots(ctx context.Context, cr *redisv1beta2.RedisCluster, nodeID string) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) totalSlots := 0 redisClient := configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() - redisClusterInfo, err := redisClient.ClusterNodes().Result() + redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() if err != nil { logger.Error(err, "Failed to Get Cluster Info") return "" @@ -112,20 +114,20 @@ func getRedisClusterSlots(cr *redisv1beta2.RedisCluster, nodeID string) string { } // getRedisNodeID would return nodeID of a redis node by passing pod -func getRedisNodeID(cr *redisv1beta2.RedisCluster, pod RedisDetails) string { +func getRedisNodeID(ctx context.Context, cr *redisv1beta2.RedisCluster, pod RedisDetails) string { var client *redis.Client logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) client = configureRedisClient(cr, pod.PodName) defer client.Close() - pong, err := client.Ping().Result() + pong, err := client.Ping(ctx).Result() if err != nil || pong != "PONG" { logger.Error(err, "Failed to ping Redis server") return "" } - cmd := redis.NewStringCmd("cluster", "myid") - err = client.Process(cmd) + cmd := redis.NewStringCmd(ctx, "cluster", "myid") + err = client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") return "" @@ -174,17 +176,17 @@ func RebalanceRedisClusterEmptyMasters(cr *redisv1beta2.RedisCluster) { executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") } -func CheckIfEmptyMasters(cr *redisv1beta2.RedisCluster) { +func CheckIfEmptyMasters(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - totalRedisLeaderNodes := CheckRedisNodeCount(cr, "leader") + totalRedisLeaderNodes := CheckRedisNodeCount(ctx, cr, "leader") for i := 0; i < int(totalRedisLeaderNodes); i++ { pod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i), Namespace: cr.Namespace, } - podNodeID := getRedisNodeID(cr, pod) - podSlots := getRedisClusterSlots(cr, podNodeID) + podNodeID := getRedisNodeID(ctx, cr, pod) + podSlots := getRedisClusterSlots(ctx, cr, podNodeID) if podSlots == "0" || podSlots == "" { logger.V(1).Info("Found Empty Redis Leader Node", "pod", pod) @@ -227,10 +229,10 @@ func RebalanceRedisCluster(cr *redisv1beta2.RedisCluster) { } // Add redis cluster node would add a node to the existing redis cluster using redis-cli -func AddRedisNodeToCluster(cr *redisv1beta2.RedisCluster) { +func AddRedisNodeToCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - activeRedisNode := CheckRedisNodeCount(cr, "leader") + activeRedisNode := CheckRedisNodeCount(ctx, cr, "leader") newPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(activeRedisNode)), @@ -267,12 +269,12 @@ func AddRedisNodeToCluster(cr *redisv1beta2.RedisCluster) { } // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader -func getAttachedFollowerNodeIDs(cr *redisv1beta2.RedisCluster, masterNodeID string) []string { +func getAttachedFollowerNodeIDs(ctx context.Context, cr *redisv1beta2.RedisCluster, masterNodeID string) []string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) redisClient := configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() - redisClusterInfo, err := redisClient.ClusterNodes().Result() + redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() if err != nil { logger.Error(err, "Failed to Get Cluster Info") return nil @@ -297,10 +299,10 @@ func getAttachedFollowerNodeIDs(cr *redisv1beta2.RedisCluster, masterNodeID stri } // Remove redis follower node would remove all follower nodes of last leader node using redis-cli -func RemoveRedisFollowerNodesFromCluster(cr *redisv1beta2.RedisCluster) { +func RemoveRedisFollowerNodesFromCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -323,8 +325,8 @@ func RemoveRedisFollowerNodesFromCluster(cr *redisv1beta2.RedisCluster) { } cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) - lastLeaderPodNodeID := getRedisNodeID(cr, lastLeaderPod) - followerNodeIDs := getAttachedFollowerNodeIDs(cr, lastLeaderPodNodeID) + lastLeaderPodNodeID := getRedisNodeID(ctx, cr, lastLeaderPod) + followerNodeIDs := getAttachedFollowerNodeIDs(ctx, cr, lastLeaderPodNodeID) cmd = append(cmd, "--cluster", "del-node") if *cr.Spec.ClusterVersion == "v7" { @@ -343,10 +345,10 @@ func RemoveRedisFollowerNodesFromCluster(cr *redisv1beta2.RedisCluster) { } // Remove redis cluster node would remove last node to the existing redis cluster using redis-cli -func RemoveRedisNodeFromCluster(cr *redisv1beta2.RedisCluster) { +func RemoveRedisNodeFromCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -365,7 +367,7 @@ func RemoveRedisNodeFromCluster(cr *redisv1beta2.RedisCluster) { cmd = append(cmd, getRedisServerIP(existingPod)+":6379") } - removePodNodeID := getRedisNodeID(cr, removePod) + removePodNodeID := getRedisNodeID(ctx, cr, removePod) cmd = append(cmd, removePodNodeID) if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -380,20 +382,20 @@ func RemoveRedisNodeFromCluster(cr *redisv1beta2.RedisCluster) { cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster leader remove command is", "Command", cmd) - if getRedisClusterSlots(cr, removePodNodeID) != "0" { + if getRedisClusterSlots(ctx, cr, removePodNodeID) != "0" { logger.V(1).Info("Skipping execution remove leader not empty", "cmd", cmd) } executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // verifyLeaderPod return true if the pod is leader/master -func VerifyLeaderPod(cr *redisv1beta2.RedisCluster) bool { +func VerifyLeaderPod(ctx context.Context, cr *redisv1beta2.RedisCluster) bool { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - podName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(cr, "leader"))-1) + podName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, cr, "leader"))-1) redisClient := configureRedisClient(cr, podName) defer redisClient.Close() - info, err := redisClient.Info("replication").Result() + info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the role Info of the", "redis pod", podName) return false @@ -410,9 +412,9 @@ func VerifyLeaderPod(cr *redisv1beta2.RedisCluster) bool { return false } -func ClusterFailover(cr *redisv1beta2.RedisCluster) { +func ClusterFailover(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - slavePodName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(cr, "leader"))-1) + slavePodName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, cr, "leader"))-1) // cmd = redis-cli cluster failover -a var cmd []string diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 781d4f371..fe11fd24c 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -32,7 +32,7 @@ type RedisReplicationObject struct { } // Redis Sentinel Create the Redis Sentinel Setup -func CreateRedisSentinel(cr *redisv1beta2.RedisSentinel) error { +func CreateRedisSentinel(ctx context.Context, cr *redisv1beta2.RedisSentinel) error { prop := RedisSentinelSTS{ RedisStateFulType: "sentinel", Affinity: cr.Spec.Affinity, @@ -45,7 +45,7 @@ func CreateRedisSentinel(cr *redisv1beta2.RedisSentinel) error { prop.ExternalConfig = cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig } - return prop.CreateRedisSentinelSetup(cr) + return prop.CreateRedisSentinelSetup(ctx, cr) } @@ -59,7 +59,7 @@ func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { } // Create Redis Sentinel Cluster Setup -func (service RedisSentinelSTS) CreateRedisSentinelSetup(cr *redisv1beta2.RedisSentinel) error { +func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr *redisv1beta2.RedisSentinel) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) @@ -72,7 +72,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(cr *redisv1beta2.RedisS generateRedisSentinelParams(cr, service.getSentinelCount(cr), service.ExternalConfig, service.Affinity), redisSentinelAsOwner(cr), generateRedisSentinelInitContainerParams(cr), - generateRedisSentinelContainerParams(cr, service.ReadinessProbe, service.LivenessProbe), + generateRedisSentinelContainerParams(ctx, cr, service.ReadinessProbe, service.LivenessProbe), cr.Spec.Sidecars, ) @@ -141,7 +141,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in } // Create Redis Sentinel Statefulset Container Params -func generateRedisSentinelContainerParams(cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { +func generateRedisSentinelContainerParams(ctx context.Context, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { trueProperty := true falseProperty := false @@ -151,7 +151,7 @@ func generateRedisSentinelContainerParams(cr *redisv1beta2.RedisSentinel, readin ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - AdditionalEnvVariable: getSentinelEnvVariable(cr), + AdditionalEnvVariable: getSentinelEnvVariable(ctx, cr), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars @@ -240,7 +240,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. } -func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { +func getSentinelEnvVariable(ctx context.Context, cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { if cr.Spec.RedisSentinelConfig == nil { return &[]corev1.EnvVar{} @@ -253,7 +253,7 @@ func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { }, { Name: "IP", - Value: getRedisReplicationMasterIP(cr), + Value: getRedisReplicationMasterIP(ctx, cr), }, { Name: "PORT", @@ -281,7 +281,7 @@ func getSentinelEnvVariable(cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { } -func getRedisReplicationMasterIP(cr *redisv1beta2.RedisSentinel) string { +func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSentinel) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) replicationName := cr.Spec.RedisSentinelConfig.RedisReplicationName @@ -317,7 +317,7 @@ func getRedisReplicationMasterIP(cr *redisv1beta2.RedisSentinel) string { return "" } - masterPods := GetRedisNodesByRole(&replicationInstance, "master") + masterPods := GetRedisNodesByRole(ctx, &replicationInstance, "master") if len(masterPods) == 0 { realMasterPod = "" @@ -326,7 +326,7 @@ func getRedisReplicationMasterIP(cr *redisv1beta2.RedisSentinel) string { } else if len(masterPods) == 1 { realMasterPod = masterPods[0] } else { - realMasterPod = checkAttachedSlave(&replicationInstance, masterPods) + realMasterPod = checkAttachedSlave(ctx, &replicationInstance, masterPods) } realMasterInfo := RedisDetails{ diff --git a/k8sutils/redis.go b/k8sutils/redis.go index f7bbcb576..6973363f0 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -11,7 +11,7 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" - "github.com/go-redis/redis" + redis "github.com/redis/go-redis/v9" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/scheme" @@ -87,13 +87,13 @@ func CreateMultipleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { } // ExecuteRedisClusterCommand will execute redis cluster creation command -func ExecuteRedisClusterCommand(cr *redisv1beta2.RedisCluster) { +func ExecuteRedisClusterCommand(ctx context.Context, cr *redisv1beta2.RedisCluster) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string replicas := cr.Spec.GetReplicaCounts("leader") switch int(replicas) { case 1: - err := executeFailoverCommand(cr, "leader") + err := executeFailoverCommand(ctx, cr, "leader") if err != nil { logger.Error(err, "error executing failover command") } @@ -154,14 +154,14 @@ func createRedisReplicationCommand(cr *redisv1beta2.RedisCluster, leaderPod Redi } // ExecuteRedisReplicationCommand will execute the replication command -func ExecuteRedisReplicationCommand(cr *redisv1beta2.RedisCluster) { +func ExecuteRedisReplicationCommand(ctx context.Context, cr *redisv1beta2.RedisCluster) { var podIP string logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) followerCounts := cr.Spec.GetReplicaCounts("follower") leaderCounts := cr.Spec.GetReplicaCounts("leader") followerPerLeader := followerCounts / leaderCounts - nodes := checkRedisCluster(cr) + nodes := checkRedisCluster(ctx, cr) for followerIdx := 0; followerIdx <= int(followerCounts)-1; { for i := 0; i < int(followerPerLeader) && followerIdx <= int(followerCounts)-1; i++ { followerPod := RedisDetails{ @@ -177,7 +177,7 @@ func ExecuteRedisReplicationCommand(cr *redisv1beta2.RedisCluster) { logger.V(1).Info("Adding node to cluster.", "Node.IP", podIP, "Follower.Pod", followerPod) cmd := createRedisReplicationCommand(cr, leaderPod, followerPod) redisClient := configureRedisClient(cr, followerPod.PodName) - pong, err := redisClient.Ping().Result() + pong, err := redisClient.Ping(ctx).Result() redisClient.Close() if err != nil { logger.Error(err, "Failed to ping Redis server", "Follower.Pod", followerPod) @@ -198,13 +198,13 @@ func ExecuteRedisReplicationCommand(cr *redisv1beta2.RedisCluster) { } // checkRedisCluster will check the redis cluster have sufficient nodes or not -func checkRedisCluster(cr *redisv1beta2.RedisCluster) [][]string { +func checkRedisCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) [][]string { var client *redis.Client logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) client = configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") defer client.Close() - cmd := redis.NewStringCmd("cluster", "nodes") - err := client.Process(cmd) + cmd := redis.NewStringCmd(ctx, "cluster", "nodes") + err := client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") } @@ -226,14 +226,14 @@ func checkRedisCluster(cr *redisv1beta2.RedisCluster) [][]string { } // ExecuteFailoverOperation will execute redis failover operations -func ExecuteFailoverOperation(cr *redisv1beta2.RedisCluster) error { +func ExecuteFailoverOperation(ctx context.Context, cr *redisv1beta2.RedisCluster) error { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - err := executeFailoverCommand(cr, "leader") + err := executeFailoverCommand(ctx, cr, "leader") if err != nil { logger.Error(err, "Redis command failed for leader nodes") return err } - err = executeFailoverCommand(cr, "follower") + err = executeFailoverCommand(ctx, cr, "follower") if err != nil { logger.Error(err, "Redis command failed for follower nodes") return err @@ -242,7 +242,7 @@ func ExecuteFailoverOperation(cr *redisv1beta2.RedisCluster) error { } // executeFailoverCommand will execute failover command -func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { +func executeFailoverCommand(ctx context.Context, cr *redisv1beta2.RedisCluster, role string) error { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) replicas := cr.Spec.GetReplicaCounts(role) podName := fmt.Sprintf("%s-%s-", cr.ObjectMeta.Name, role) @@ -250,18 +250,18 @@ func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { logger.V(1).Info("Executing redis failover operations", "Redis Node", podName+strconv.Itoa(podCount)) client := configureRedisClient(cr, podName+strconv.Itoa(podCount)) defer client.Close() - cmd := redis.NewStringCmd("cluster", "reset") - err := client.Process(cmd) + cmd := redis.NewStringCmd(ctx, "cluster", "reset") + err := client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") - flushcommand := redis.NewStringCmd("flushall") - err = client.Process(flushcommand) + flushcommand := redis.NewStringCmd(ctx, "flushall") + err = client.Process(ctx, flushcommand) if err != nil { logger.Error(err, "Redis flush command failed with this error") return err } } - err = client.Process(cmd) + err = client.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") return err @@ -277,10 +277,10 @@ func executeFailoverCommand(cr *redisv1beta2.RedisCluster, role string) error { } // CheckRedisNodeCount will check the count of redis nodes -func CheckRedisNodeCount(cr *redisv1beta2.RedisCluster, nodeType string) int32 { +func CheckRedisNodeCount(ctx context.Context, cr *redisv1beta2.RedisCluster, nodeType string) int32 { var redisNodeType string logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - clusterNodes := checkRedisCluster(cr) + clusterNodes := checkRedisCluster(ctx, cr) count := len(clusterNodes) switch nodeType { @@ -306,9 +306,9 @@ func CheckRedisNodeCount(cr *redisv1beta2.RedisCluster, nodeType string) int32 { } // CheckRedisClusterState will check the redis cluster state -func CheckRedisClusterState(cr *redisv1beta2.RedisCluster) int { +func CheckRedisClusterState(ctx context.Context, cr *redisv1beta2.RedisCluster) int { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - clusterNodes := checkRedisCluster(cr) + clusterNodes := checkRedisCluster(ctx, cr) count := 0 for _, node := range clusterNodes { @@ -464,7 +464,7 @@ func configureRedisReplicationClient(cr *redisv1beta2.RedisReplication, podName } // Get Redis nodes by it's role i.e. master, slave and sentinel -func GetRedisNodesByRole(cr *redisv1beta2.RedisReplication, redisRole string) []string { +func GetRedisNodesByRole(ctx context.Context, cr *redisv1beta2.RedisReplication, redisRole string) []string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) statefulset, err := GetStatefulSet(cr.Namespace, cr.Name) if err != nil { @@ -477,7 +477,7 @@ func GetRedisNodesByRole(cr *redisv1beta2.RedisReplication, redisRole string) [] for i := 0; i < int(replicas); i++ { podName := statefulset.Name + "-" + strconv.Itoa(i) - podRole := checkRedisServerRole(cr, podName) + podRole := checkRedisServerRole(ctx, cr, podName) if podRole == redisRole { pods = append(pods, podName) } @@ -487,12 +487,12 @@ func GetRedisNodesByRole(cr *redisv1beta2.RedisReplication, redisRole string) [] } // Check the Redis Server Role i.e. master, slave and sentinel -func checkRedisServerRole(cr *redisv1beta2.RedisReplication, podName string) string { +func checkRedisServerRole(ctx context.Context, cr *redisv1beta2.RedisReplication, podName string) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) redisClient := configureRedisReplicationClient(cr, podName) defer redisClient.Close() - info, err := redisClient.Info("replication").Result() + info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the role Info of the", "redis pod", podName) } @@ -510,7 +510,7 @@ func checkRedisServerRole(cr *redisv1beta2.RedisReplication, podName string) str } // checkAttachedSlave would return redis pod name which has slave -func checkAttachedSlave(cr *redisv1beta2.RedisReplication, masterPods []string) string { +func checkAttachedSlave(ctx context.Context, cr *redisv1beta2.RedisReplication, masterPods []string) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) for _, podName := range masterPods { @@ -518,7 +518,7 @@ func checkAttachedSlave(cr *redisv1beta2.RedisReplication, masterPods []string) connected_slaves := "" redisClient := configureRedisReplicationClient(cr, podName) defer redisClient.Close() - info, err := redisClient.Info("replication").Result() + info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the connected slaves Info of the", "redis pod", podName) } @@ -543,11 +543,11 @@ func checkAttachedSlave(cr *redisv1beta2.RedisReplication, masterPods []string) } -func CreateMasterSlaveReplication(cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { +func CreateMasterSlaveReplication(ctx context.Context, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var realMasterPod string - realMasterPod = checkAttachedSlave(cr, masterPods) + realMasterPod = checkAttachedSlave(ctx, cr, masterPods) if len(slavePods) < 1 { realMasterPod = masterPods[0] @@ -568,7 +568,7 @@ func CreateMasterSlaveReplication(cr *redisv1beta2.RedisReplication, masterPods redisClient := configureRedisReplicationClient(cr, masterPods[i]) defer redisClient.Close() logger.V(1).Info("Setting the", "pod", masterPods[i], "to slave of", realMasterPod) - err := redisClient.SlaveOf(realMasterPodIP, "6379").Err() + err := redisClient.SlaveOf(ctx, realMasterPodIP, "6379").Err() if err != nil { logger.Error(err, "Failed to set", "pod", masterPods[i], "to slave of", realMasterPod) return err From 667ceae327e57d543a0aeb27dafa255556d363e6 Mon Sep 17 00:00:00 2001 From: yangw Date: Fri, 6 Oct 2023 13:33:21 +0800 Subject: [PATCH 023/203] Fix e2e test (#658) * fix kuttl timeout unit to second Signed-off-by: drivebyer * fix assert rediscluster version Signed-off-by: drivebyer * Update readme.md --------- Signed-off-by: drivebyer Co-authored-by: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> --- tests/e2e/v1beta2/setup/ready-cluster.yaml | 2 +- tests/readme.md | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/e2e/v1beta2/setup/ready-cluster.yaml b/tests/e2e/v1beta2/setup/ready-cluster.yaml index 57d53c708..54077ef06 100644 --- a/tests/e2e/v1beta2/setup/ready-cluster.yaml +++ b/tests/e2e/v1beta2/setup/ready-cluster.yaml @@ -1,4 +1,4 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta1 +apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster-v1beta2 diff --git a/tests/readme.md b/tests/readme.md index 155b89fb3..5538aa670 100644 --- a/tests/readme.md +++ b/tests/readme.md @@ -13,8 +13,6 @@ Ensure you have the following tools installed: ## **Steps** -### **1. Set Up a 3-node Kind Cluster** - ## Steps to Follow ### 1. Set Up a 3-node Kind Cluster @@ -22,7 +20,7 @@ Ensure you have the following tools installed: Create a 3-node kind cluster using the provided configuration: ```bash -kind create cluster --config /redis-operator/tests/_config/kind-example-config.yaml +kind create cluster --config /redis-operator/tests/_config/kind-config.yaml ``` ### 2. Install the Redis Operator @@ -38,5 +36,5 @@ Please refer to the repository's README for detailed instructions on installing Execute the kuttl test using the following command: ```bash -kubectl kuttl test redis-operator/tests/e2e/v1beta2 --config /redis-operator/tests/_config/kuttl-test.yaml --timeout 10m +kubectl kuttl test redis-operator/tests/e2e/v1beta2 --config /redis-operator/tests/_config/kuttl-test.yaml --timeout 600 ``` From 5b14d94771021aaa108db4033789ca0192f79e3c Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:36:41 +0530 Subject: [PATCH 024/203] Test (#659) Signed-off-by: Shubham Gupta --- .gitignore | 3 +- tests/_config/kuttl-test.yaml | 2 + .../setup/{ => redis-cluster}/00-install.yaml | 3 +- .../setup/{ => redis-cluster}/cluster.yaml | 0 .../ready-cluster-sts.yaml | 0 .../{ => redis-cluster}/ready-cluster.yaml | 2 +- .../setup/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++++ tests/readme.md | 12 +- 8 files changed, 198 insertions(+), 5 deletions(-) rename tests/e2e/v1beta2/setup/{ => redis-cluster}/00-install.yaml (69%) rename tests/e2e/v1beta2/setup/{ => redis-cluster}/cluster.yaml (100%) rename tests/e2e/v1beta2/setup/{ => redis-cluster}/ready-cluster-sts.yaml (100%) rename tests/e2e/v1beta2/setup/{ => redis-cluster}/ready-cluster.yaml (82%) create mode 100644 tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml diff --git a/.gitignore b/.gitignore index 3f4669bdb..d360ec637 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,5 @@ testbin/* *~ .vscode -docs/build \ No newline at end of file +docs/build +kubeconfig \ No newline at end of file diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml index ab9b63777..66a9a882e 100644 --- a/tests/_config/kuttl-test.yaml +++ b/tests/_config/kuttl-test.yaml @@ -4,5 +4,7 @@ startKIND: false kindConfig: "./kind-config.yaml" parallel: 1 timeout: 300 +testDirs: +- tests/e2e/v1beta2/setup suppress : - events \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/00-install.yaml b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml similarity index 69% rename from tests/e2e/v1beta2/setup/00-install.yaml rename to tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml index 94b166978..1aef14859 100644 --- a/tests/e2e/v1beta2/setup/00-install.yaml +++ b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml @@ -4,4 +4,5 @@ apply : - cluster.yaml assert : - ready-cluster.yaml - - ready-cluster-sts.yaml \ No newline at end of file + - ready-cluster-sts.yaml + - ready-pvc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/cluster.yaml b/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/cluster.yaml rename to tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml diff --git a/tests/e2e/v1beta2/setup/ready-cluster-sts.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/ready-cluster-sts.yaml rename to tests/e2e/v1beta2/setup/redis-cluster/ready-cluster-sts.yaml diff --git a/tests/e2e/v1beta2/setup/ready-cluster.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml similarity index 82% rename from tests/e2e/v1beta2/setup/ready-cluster.yaml rename to tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml index 54077ef06..49e754e81 100644 --- a/tests/e2e/v1beta2/setup/ready-cluster.yaml +++ b/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml @@ -3,5 +3,5 @@ kind: RedisCluster metadata: name: redis-cluster-v1beta2 status: - # readyFollowerReplicas: 3 + readyFollowerReplicas: 3 readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/readme.md b/tests/readme.md index 5538aa670..f4057b698 100644 --- a/tests/readme.md +++ b/tests/readme.md @@ -20,7 +20,7 @@ Ensure you have the following tools installed: Create a 3-node kind cluster using the provided configuration: ```bash -kind create cluster --config /redis-operator/tests/_config/kind-config.yaml +kind create cluster --config tests/_config/kind-config.yaml ``` ### 2. Install the Redis Operator @@ -35,6 +35,14 @@ Please refer to the repository's README for detailed instructions on installing Execute the kuttl test using the following command: +To run all default tests ( _config/kuttl-test.yaml is the default config file ) + +```bash +kubectl kuttl test --config tests/_config/kuttl-test.yaml +``` + +To run a test at specified path + ```bash -kubectl kuttl test redis-operator/tests/e2e/v1beta2 --config /redis-operator/tests/_config/kuttl-test.yaml --timeout 600 +kubectl kuttl test tests/e2e/v1beta2 --config tests/_config/kuttl-test.yaml --timeout 600 ``` From 108c07aa39cc333e3f4ac22647dddf803be313e1 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:01:34 +0530 Subject: [PATCH 025/203] add setup for redis standalone (#660) Signed-off-by: Shubham Gupta --- .../setup/redis-standalone/00-install.yaml | 8 ++++++ .../setup/redis-standalone/ready-pvc.yaml | 14 ++++++++++ .../setup/redis-standalone/ready-sts.yaml | 11 ++++++++ .../setup/redis-standalone/standalone.yaml | 26 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-standalone/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml diff --git a/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml new file mode 100644 index 000000000..3155e0cca --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml @@ -0,0 +1,8 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - standalone.yaml +assert : + # - ready-standalone.yaml + - ready-sts.yaml + - ready-pvc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml b/tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml new file mode 100644 index 000000000..777fa3656 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-standalone-v1beta2-redis-standalone-v1beta2-0 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/setup/redis-standalone/ready-sts.yaml b/tests/e2e/v1beta2/setup/redis-standalone/ready-sts.yaml new file mode 100644 index 000000000..5402de920 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-standalone/ready-sts.yaml @@ -0,0 +1,11 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + replicas: 1 + readyReplicas: 1 diff --git a/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml b/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml new file mode 100644 index 000000000..327c9a946 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml @@ -0,0 +1,26 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone-v1beta2 +spec: + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi From aecb51c3cb610bc707c5b277ddd057f1dfcc63dd Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 7 Oct 2023 14:20:30 +0800 Subject: [PATCH 026/203] [Fix] - make deploy target not works well (#662) * execute make manifests Signed-off-by: drivebyer * fix indent Signed-off-by: drivebyer * match operator's name && namespace Signed-off-by: drivebyer * disable webhook related resources Signed-off-by: drivebyer * fix no-group name for core api resources Signed-off-by: drivebyer * disable manager auth by default Signed-off-by: drivebyer * fix ClusterRoleBinding Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- Makefile | 2 +- api/rbac.go | 2 +- config/certmanager/certificate.yaml | 4 +- .../redis.redis.opstreelabs.in_redis.yaml | 2962 +++++++++------ ...is.redis.opstreelabs.in_redisclusters.yaml | 3320 ++++++++++------- ...edis.opstreelabs.in_redisreplications.yaml | 2962 +++++++++------ ...s.redis.opstreelabs.in_redissentinels.yaml | 430 ++- config/crd/patches/webhook_in_redis.yaml | 2 +- .../crd/patches/webhook_in_redisclusters.yaml | 2 +- .../patches/webhook_in_redisreplications.yaml | 2 +- .../patches/webhook_in_redissentinels.yaml | 2 +- config/default/kustomization.yaml | 66 +- config/default/manager_auth_proxy_patch.yaml | 4 +- config/default/manager_config_patch.yaml | 4 +- config/default/manager_webhook_patch.yaml | 4 +- config/prometheus/monitor.yaml | 8 +- config/rbac/role.yaml | 4 +- config/rbac/role_binding.yaml | 2 +- config/webhook/service.yaml | 4 +- 19 files changed, 5832 insertions(+), 3954 deletions(-) diff --git a/Makefile b/Makefile index 46741633b..2c39a1d2b 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ uninstall: manifests kustomize # Deploy controller in the configured Kubernetes cluster in ~/.kube/config deploy: manifests kustomize cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | kubectl apply -f - + $(KUSTOMIZE) build config/default | kubectl apply --server-side=true -f - # UnDeploy controller from the configured Kubernetes cluster in ~/.kube/config undeploy: diff --git a/api/rbac.go b/api/rbac.go index 9510243ec..6cc700341 100644 --- a/api/rbac.go +++ b/api/rbac.go @@ -5,7 +5,7 @@ package api // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch // +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/finalizers;rediscluster/finalizers;redisclusters/finalizers;redissentinel/finalizers;redissentinels/finalizers;redisreplication/finalizers;redisreplications/finalizers,verbs=update // +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/status;rediscluster/status;redisclusters/status;redissentinel/status;redissentinels/status;redisreplication/status;redisreplications/status,verbs=get;patch;update -// +kubebuilder:rbac:groups=,resources=secrets;pods/exec;pods;services;configmaps;events;persistentvolumeclaims;namespaces,verbs=create;delete;get;list;patch;update;watch +// +kubebuilder:rbac:groups="",resources=secrets;pods/exec;pods;services;configmaps;events;persistentvolumeclaims;namespaces,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=create;delete;get;list;patch;update;watch // +kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=create;delete;get;list;patch;update;watch diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml index 52d866183..688894e90 100644 --- a/config/certmanager/certificate.yaml +++ b/config/certmanager/certificate.yaml @@ -5,7 +5,7 @@ apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-issuer - namespace: system + namespace: ot-operators spec: selfSigned: {} --- @@ -13,7 +13,7 @@ apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml - namespace: system + namespace: ot-operators spec: # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize dnsNames: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index fdeb29155..24a475aa1 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -49,37 +49,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -88,10 +89,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -99,12 +100,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -399,9 +400,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -456,7 +455,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -555,8 +554,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -607,7 +604,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -708,9 +705,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -765,7 +760,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -864,8 +859,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -916,7 +909,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -969,6 +962,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -989,7 +1004,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -1017,10 +1033,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -1239,6 +1274,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1259,7 +1316,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -1354,7 +1412,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -1368,9 +1427,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -1413,14 +1477,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -1562,6 +1623,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1582,8 +1665,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -1615,24 +1698,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -1651,27 +1737,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -1685,18 +1778,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1718,12 +1845,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -1768,8 +1896,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -1777,20 +1905,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -1798,19 +1971,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -1819,36 +2004,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -1862,14 +2048,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -1923,123 +2102,128 @@ spec: may be accessed by any container in the pod. properties: awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS + description: 'awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty).' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: - description: 'Specify "true" to force and set the - ReadOnly property in VolumeMounts to "true". If - omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: - description: 'Unique ID of the persistent disk resource - in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: - description: AzureDisk represents an Azure Data Disk + description: azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: - description: 'Host Caching mode: None, Read Only, - Read Write.' + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: - description: The Name of the data disk in the blob - storage + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: - description: The URI the data disk in the blob storage + description: diskURI is the URI of data disk in + the blob storage type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: - description: 'Expected values Shared: multiple blob - disks per storage account Dedicated: single blob - disk per storage account Managed: azure managed - data disk (only in managed availability set). - defaults to shared' + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: - description: AzureFile represents an Azure File Service + description: azureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretName: - description: the name of secret that contains Azure - Storage Account Name and Key + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: - description: Share Name + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: - description: CephFS represents a Ceph FS mount on the + description: cephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: - description: 'Required: Monitors is a collection - of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: - description: 'Optional: Used as the mounted root, - rather than the full Ceph tree, default is /' + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: - description: 'Optional: SecretFile is the path to - key ring for User, default is /etc/ceph/user.secret + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: - description: 'Optional: SecretRef is reference to - the authentication secret for User, default is - empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: @@ -2049,31 +2233,32 @@ spec: type: string type: object user: - description: 'Optional: User is the rados user name, - default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: - description: 'Cinder represents a cinder volume attached + description: 'cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Examples: "ext4", "xfs", "ntfs". Implicitly - inferred to be "ext4" if unspecified. More info: - https://examples.k8s.io/mysql-cinder-pd/README.md' + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: - description: 'Optional: Defaults to false (read/write). + description: 'readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: - description: 'Optional: points to a secret object - containing parameters used to connect to OpenStack.' + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' properties: name: description: 'Name of the referent. More info: @@ -2083,32 +2268,32 @@ spec: type: string type: object volumeID: - description: 'volume id used to identify the volume + description: 'volumeID used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: - description: ConfigMap represents a configMap that should + description: configMap represents a configMap that should populate this volume properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced ConfigMap + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified @@ -2123,26 +2308,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -2155,28 +2342,28 @@ spec: uid?' type: string optional: - description: Specify whether the ConfigMap or its - keys must be defined + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object csi: - description: CSI (Container Storage Interface) represents + description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external CSI drivers (Beta feature). properties: driver: - description: Driver is the name of the CSI driver + description: driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: - description: Filesystem type to mount. Ex. "ext4", - "xfs", "ntfs". If not provided, the empty value - is passed to the associated CSI driver which will - determine the default filesystem to apply. + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. type: string nodePublishSecretRef: - description: NodePublishSecretRef is a reference + description: nodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. @@ -2193,13 +2380,13 @@ spec: type: string type: object readOnly: - description: Specifies a read-only configuration + description: readOnly specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string - description: VolumeAttributes stores driver-specific + description: volumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. @@ -2208,7 +2395,7 @@ spec: - driver type: object downwardAPI: - description: DownwardAPI represents downward API about + description: downwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: @@ -2301,32 +2488,33 @@ spec: type: array type: object emptyDir: - description: 'EmptyDir represents a temporary directory + description: 'emptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: - description: 'What type of storage medium should - back this directory. The default is "" which means - to use the node''s default medium. Must be an - empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string - description: 'Total amount of local storage required - for this EmptyDir volume. The size limit is also - applicable for memory medium. The maximum usage - on memory medium EmptyDir would be the minimum - value between the SizeLimit specified here and - the sum of memory limits of all containers in - a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object ephemeral: - description: "Ephemeral represents a volume that is + description: "ephemeral represents a volume that is handled by a cluster storage driver. The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted @@ -2386,25 +2574,28 @@ spec: are also valid here. properties: accessModes: - description: 'AccessModes contains the desired + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to - specify either: * An existing VolumeSnapshot + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate - is enabled, this field will always have - the same contents as the DataSourceRef - field.' + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for @@ -2427,33 +2618,41 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from - which to populate the volume with data, - if a non-empty volume is desired. This - may be any local object from a non-empty + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the - functionality of the DataSource field + functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards - compatibility, both fields (DataSource - and DataSourceRef) will be set to the + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value automatically if one of them - is empty and the other is non-empty. There - are two important differences between - DataSource and DataSourceRef: * While - DataSource only allows two specific types - of objects, DataSourceRef allows any - non-core object, as well as PersistentVolumeClaim - objects. * While DataSource ignores disallowed - values (dropping them), DataSourceRef preserves + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves all values, and generates an error if - a disallowed value is specified. (Alpha) - Using this field requires the AnyVolumeDataSource + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' properties: apiGroup: @@ -2472,12 +2671,25 @@ spec: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are @@ -2486,6 +2698,32 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2510,12 +2748,13 @@ spec: a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes - to consider for binding. + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: description: matchExpressions is a list @@ -2569,8 +2808,9 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required - by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type @@ -2579,7 +2819,7 @@ spec: in claim spec. type: string volumeName: - description: VolumeName is the binding reference + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object @@ -2588,74 +2828,75 @@ spec: type: object type: object fc: - description: FC represents a Fibre Channel resource + description: fc represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: - description: 'Optional: FC target lun number' + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: - description: 'Optional: FC target worldwide names - (WWNs)' + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array wwids: - description: 'Optional: FC volume world wide identifiers - (wwids) Either wwids or combination of targetWWNs - and lun must be set, but not both simultaneously.' + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' items: type: string type: array type: object flexVolume: - description: FlexVolume represents a generic volume + description: flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: - description: Driver is the name of the driver to + description: driver is the name of the driver to use for this volume. type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". The default - filesystem depends on FlexVolume script. + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string - description: 'Optional: Extra command options if - any.' + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean secretRef: - description: 'Optional: SecretRef is reference to - the secret object containing sensitive information - to pass to the plugin scripts. This may be empty - if no secret object is specified. If the secret - object contains more than one secret, all secrets - are passed to the plugin scripts.' + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: @@ -2668,28 +2909,28 @@ spec: - driver type: object flocker: - description: Flocker represents a Flocker volume attached + description: flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: - description: Name of the dataset stored as metadata - -> name on the dataset for Flocker should be considered - as deprecated + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated type: string datasetUUID: - description: UUID of the dataset. This is unique - identifier of a Flocker dataset + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk + description: 'gcePersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk @@ -2697,21 +2938,22 @@ spec: from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: - description: 'Unique name of the PD resource in - GCE. Used to identify the disk in GCE. More info: - https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean @@ -2719,7 +2961,7 @@ spec: - pdName type: object gitRepo: - description: 'GitRepo represents a git repository at + description: 'gitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo @@ -2727,37 +2969,38 @@ spec: container.' properties: directory: - description: Target directory name. Must not contain - or start with '..'. If '.' is supplied, the volume - directory will be the git repository. Otherwise, - if specified, the volume will contain the git - repository in the subdirectory with the given - name. + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. type: string repository: - description: Repository URL + description: repository is the URL type: string revision: - description: Commit hash for the specified revision. + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: - description: 'Glusterfs represents a Glusterfs mount + description: 'glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: - description: 'EndpointsName is the endpoint name - that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: - description: 'Path is the Glusterfs volume path. + description: 'path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: - description: 'ReadOnly here will force the Glusterfs + description: 'readOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean @@ -2766,7 +3009,7 @@ spec: - path type: object hostPath: - description: 'HostPath represents a pre-existing file + description: 'hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are @@ -2777,71 +3020,73 @@ spec: directories as read/write.' properties: path: - description: 'Path of the directory on the host. + description: 'path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: - description: 'Type for HostPath Volume Defaults + description: 'type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: - description: 'ISCSI represents an ISCSI Disk resource + description: 'iscsi represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP - authentication + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: - description: whether support iSCSI Session CHAP - authentication + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName - is specified with iscsiInterface simultaneously, - new iSCSI interface : - will be created for the connection. + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: - description: Target iSCSI Qualified Name. + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI - transport. Defaults to 'default' (tcp). + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). type: string lun: - description: iSCSI Target Lun number. + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: - description: iSCSI Target Portal List. The portal - is either an IP or ip_addr:port if the port is - other than default (typically TCP ports 860 and - 3260). + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). items: type: string type: array readOnly: - description: ReadOnly here will force the ReadOnly + description: readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: - description: CHAP Secret for iSCSI target and initiator - authentication + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: description: 'Name of the referent. More info: @@ -2851,9 +3096,10 @@ spec: type: string type: object targetPortal: - description: iSCSI Target Portal. The Portal is - either an IP or ip_addr:port if the port is other - than default (typically TCP ports 860 and 3260). + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). type: string required: - iqn @@ -2861,24 +3107,24 @@ spec: - targetPortal type: object name: - description: 'Volume''s name. Must be a DNS_LABEL and - unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: - description: 'NFS represents an NFS mount on the host + description: 'nfs represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: - description: 'Path that is exported by the NFS server. + description: 'path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: - description: 'ReadOnly here will force the NFS export + description: 'readOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: - description: 'Server is the hostname or IP address + description: 'server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: @@ -2886,132 +3132,133 @@ spec: - server type: object persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents + description: 'persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim + description: 'claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: - description: Will force the ReadOnly setting in - VolumeMounts. Default false. + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController + description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: - description: ID that identifies Photon Controller - persistent disk + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: - description: PortworxVolume represents a portworx volume + description: portworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: - description: FSType represents the filesystem type + description: fSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean volumeID: - description: VolumeID uniquely identifies a Portworx + description: volumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: - description: Items for all in one resources secrets, - configmaps, and downward API + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: - description: Mode bits used to set permissions on - created files by default. Must be an octal value - between 0000 and 0777 or a decimal value between - 0 and 511. YAML accepts both octal and decimal - values, JSON requires decimal values for mode - bits. Directories within the path are not affected - by this setting. This might be in conflict with - other options that affect the file mode, like - fsGroup, and the result can be other mode bits - set. + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. format: int32 type: integer sources: - description: list of volume projections + description: sources is the list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: - description: information about the configMap - data to project + description: configMap information about the + configMap data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - ConfigMap will be projected into the - volume as a file whose name is the key - and content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the ConfigMap, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -3026,13 +3273,13 @@ spec: kind, uid?' type: string optional: - description: Specify whether the ConfigMap - or its keys must be defined + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object downwardAPI: - description: information about the downwardAPI - data to project + description: downwardAPI information about + the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume @@ -3122,53 +3369,53 @@ spec: type: array type: object secret: - description: information about the secret - data to project + description: secret information about the + secret data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - Secret will be projected into the volume - as a file whose name is the key and - content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the Secret, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -3183,16 +3430,16 @@ spec: kind, uid?' type: string optional: - description: Specify whether the Secret - or its key must be defined + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object serviceAccountToken: - description: information about the serviceAccountToken - data to project + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: - description: Audience is the intended + description: audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience @@ -3201,7 +3448,7 @@ spec: the identifier of the apiserver. type: string expirationSeconds: - description: ExpirationSeconds is the + description: expirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume @@ -3215,7 +3462,7 @@ spec: format: int64 type: integer path: - description: Path is the path relative + description: path is the path relative to the mount point of the file to project the token into. type: string @@ -3226,36 +3473,36 @@ spec: type: array type: object quobyte: - description: Quobyte represents a Quobyte mount on the + description: quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: - description: Group to map volume access to Default + description: group to map volume access to Default is no group type: string readOnly: - description: ReadOnly here will force the Quobyte + description: readOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: - description: Registry represents a single or multiple + description: registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: - description: Tenant owning the given Quobyte volume + description: tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: - description: User to map volume access to Defaults + description: user to map volume access to Defaults to serivceaccount user type: string volume: - description: Volume is a string that references + description: volume is a string that references an already created Quobyte volume by name. type: string required: @@ -3263,44 +3510,46 @@ spec: - volume type: object rbd: - description: 'RBD represents a Rados Block Device mount + description: 'rbd represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: - description: 'Keyring is the path to key ring for + description: 'keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: - description: 'A collection of Ceph monitors. More - info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: - description: 'The rados pool name. Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: - description: 'SecretRef is name of the authentication + description: 'secretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: @@ -3312,37 +3561,38 @@ spec: type: string type: object user: - description: 'The rados user name. Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: - description: ScaleIO represents a ScaleIO persistent + description: scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Default is - "xfs". + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". type: string gateway: - description: The host address of the ScaleIO API - Gateway. + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: - description: The name of the ScaleIO Protection - Domain for the configured storage. + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef references to the secret + description: secretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. @@ -3355,26 +3605,26 @@ spec: type: string type: object sslEnabled: - description: Flag to enable/disable SSL communication - with Gateway, default false + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: - description: Indicates whether the storage for a - volume should be ThickProvisioned or ThinProvisioned. + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: - description: The ScaleIO Storage Pool associated - with the protection domain. + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: - description: The name of the storage system as configured - in ScaleIO. + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: - description: The name of a volume already created - in the ScaleIO system that is associated with - this volume source. + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. type: string required: - gateway @@ -3382,27 +3632,27 @@ spec: - system type: object secret: - description: 'Secret represents a secret that should + description: 'secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced Secret will - be projected into the volume as a file whose name - is the key and content is the value. If specified, + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in @@ -3415,26 +3665,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -3442,30 +3694,31 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys - must be defined + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace - to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: - description: StorageOS represents a StorageOS volume + description: storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef specifies the secret to use + description: secretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: @@ -3477,12 +3730,12 @@ spec: type: string type: object volumeName: - description: VolumeName is the human-readable name + description: volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: - description: VolumeNamespace specifies the scope + description: volumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping @@ -3494,26 +3747,27 @@ spec: type: string type: object vsphereVolume: - description: VsphereVolume represents a vSphere volume + description: vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: - description: Storage Policy Based Management (SPBM) - profile ID associated with the StoragePolicyName. + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: - description: Storage Policy Based Management (SPBM) - profile name. + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: - description: Path that identifies vSphere volume - vmdk + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -3609,37 +3863,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -3648,10 +3903,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -3659,12 +3914,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -3679,37 +3934,38 @@ spec: Secret volumes support ownership management and SELinux relabeling." properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -3718,10 +3974,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -3729,12 +3985,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object type: object @@ -4027,9 +4283,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -4084,7 +4338,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -4183,8 +4437,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -4235,7 +4487,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -4336,9 +4588,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -4393,7 +4643,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -4492,8 +4742,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -4544,7 +4792,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -4799,6 +5047,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -4819,7 +5089,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -4859,6 +5130,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -4879,7 +5172,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -4907,10 +5201,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -5050,7 +5363,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -5064,9 +5378,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -5109,14 +5428,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -5295,6 +5611,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5315,7 +5653,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -5434,7 +5773,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -5465,14 +5805,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -5692,6 +6029,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5712,8 +6071,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -5745,24 +6104,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -5781,27 +6143,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -5815,18 +6184,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5848,12 +6251,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -5898,8 +6302,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -5907,20 +6311,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -5928,19 +6377,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -5949,36 +6410,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -5992,14 +6454,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -6053,123 +6508,128 @@ spec: may be accessed by any container in the pod. properties: awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS + description: 'awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty).' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: - description: 'Specify "true" to force and set the - ReadOnly property in VolumeMounts to "true". If - omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: - description: 'Unique ID of the persistent disk resource - in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: - description: AzureDisk represents an Azure Data Disk + description: azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: - description: 'Host Caching mode: None, Read Only, - Read Write.' + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: - description: The Name of the data disk in the blob - storage + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: - description: The URI the data disk in the blob storage + description: diskURI is the URI of data disk in + the blob storage type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: - description: 'Expected values Shared: multiple blob - disks per storage account Dedicated: single blob - disk per storage account Managed: azure managed - data disk (only in managed availability set). - defaults to shared' + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: - description: AzureFile represents an Azure File Service + description: azureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretName: - description: the name of secret that contains Azure - Storage Account Name and Key + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: - description: Share Name + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: - description: CephFS represents a Ceph FS mount on the + description: cephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: - description: 'Required: Monitors is a collection - of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: - description: 'Optional: Used as the mounted root, - rather than the full Ceph tree, default is /' + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: - description: 'Optional: SecretFile is the path to - key ring for User, default is /etc/ceph/user.secret + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: - description: 'Optional: SecretRef is reference to - the authentication secret for User, default is - empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: @@ -6179,31 +6639,32 @@ spec: type: string type: object user: - description: 'Optional: User is the rados user name, - default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: - description: 'Cinder represents a cinder volume attached + description: 'cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Examples: "ext4", "xfs", "ntfs". Implicitly - inferred to be "ext4" if unspecified. More info: - https://examples.k8s.io/mysql-cinder-pd/README.md' + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: - description: 'Optional: Defaults to false (read/write). + description: 'readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: - description: 'Optional: points to a secret object - containing parameters used to connect to OpenStack.' + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' properties: name: description: 'Name of the referent. More info: @@ -6213,32 +6674,32 @@ spec: type: string type: object volumeID: - description: 'volume id used to identify the volume + description: 'volumeID used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: - description: ConfigMap represents a configMap that should + description: configMap represents a configMap that should populate this volume properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced ConfigMap + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified @@ -6253,26 +6714,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -6285,28 +6748,28 @@ spec: uid?' type: string optional: - description: Specify whether the ConfigMap or its - keys must be defined + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object csi: - description: CSI (Container Storage Interface) represents + description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external CSI drivers (Beta feature). properties: driver: - description: Driver is the name of the CSI driver + description: driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: - description: Filesystem type to mount. Ex. "ext4", - "xfs", "ntfs". If not provided, the empty value - is passed to the associated CSI driver which will - determine the default filesystem to apply. + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. type: string nodePublishSecretRef: - description: NodePublishSecretRef is a reference + description: nodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. @@ -6323,13 +6786,13 @@ spec: type: string type: object readOnly: - description: Specifies a read-only configuration + description: readOnly specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string - description: VolumeAttributes stores driver-specific + description: volumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. @@ -6338,7 +6801,7 @@ spec: - driver type: object downwardAPI: - description: DownwardAPI represents downward API about + description: downwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: @@ -6431,32 +6894,33 @@ spec: type: array type: object emptyDir: - description: 'EmptyDir represents a temporary directory + description: 'emptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: - description: 'What type of storage medium should - back this directory. The default is "" which means - to use the node''s default medium. Must be an - empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string - description: 'Total amount of local storage required - for this EmptyDir volume. The size limit is also - applicable for memory medium. The maximum usage - on memory medium EmptyDir would be the minimum - value between the SizeLimit specified here and - the sum of memory limits of all containers in - a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object ephemeral: - description: "Ephemeral represents a volume that is + description: "ephemeral represents a volume that is handled by a cluster storage driver. The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted @@ -6516,25 +6980,28 @@ spec: are also valid here. properties: accessModes: - description: 'AccessModes contains the desired + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to - specify either: * An existing VolumeSnapshot + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate - is enabled, this field will always have - the same contents as the DataSourceRef - field.' + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for @@ -6557,33 +7024,41 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from - which to populate the volume with data, - if a non-empty volume is desired. This - may be any local object from a non-empty + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the - functionality of the DataSource field + functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards - compatibility, both fields (DataSource - and DataSourceRef) will be set to the + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value automatically if one of them - is empty and the other is non-empty. There - are two important differences between - DataSource and DataSourceRef: * While - DataSource only allows two specific types - of objects, DataSourceRef allows any - non-core object, as well as PersistentVolumeClaim - objects. * While DataSource ignores disallowed - values (dropping them), DataSourceRef preserves + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves all values, and generates an error if - a disallowed value is specified. (Alpha) - Using this field requires the AnyVolumeDataSource + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' properties: apiGroup: @@ -6602,12 +7077,25 @@ spec: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are @@ -6616,6 +7104,32 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6640,12 +7154,13 @@ spec: a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes - to consider for binding. + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: description: matchExpressions is a list @@ -6699,8 +7214,9 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required - by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type @@ -6709,7 +7225,7 @@ spec: in claim spec. type: string volumeName: - description: VolumeName is the binding reference + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object @@ -6718,74 +7234,75 @@ spec: type: object type: object fc: - description: FC represents a Fibre Channel resource + description: fc represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: - description: 'Optional: FC target lun number' + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: - description: 'Optional: FC target worldwide names - (WWNs)' + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array wwids: - description: 'Optional: FC volume world wide identifiers - (wwids) Either wwids or combination of targetWWNs - and lun must be set, but not both simultaneously.' + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' items: type: string type: array type: object flexVolume: - description: FlexVolume represents a generic volume + description: flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: - description: Driver is the name of the driver to + description: driver is the name of the driver to use for this volume. type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". The default - filesystem depends on FlexVolume script. + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string - description: 'Optional: Extra command options if - any.' + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean secretRef: - description: 'Optional: SecretRef is reference to - the secret object containing sensitive information - to pass to the plugin scripts. This may be empty - if no secret object is specified. If the secret - object contains more than one secret, all secrets - are passed to the plugin scripts.' + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: @@ -6798,28 +7315,28 @@ spec: - driver type: object flocker: - description: Flocker represents a Flocker volume attached + description: flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: - description: Name of the dataset stored as metadata - -> name on the dataset for Flocker should be considered - as deprecated + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated type: string datasetUUID: - description: UUID of the dataset. This is unique - identifier of a Flocker dataset + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk + description: 'gcePersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk @@ -6827,21 +7344,22 @@ spec: from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: - description: 'Unique name of the PD resource in - GCE. Used to identify the disk in GCE. More info: - https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean @@ -6849,7 +7367,7 @@ spec: - pdName type: object gitRepo: - description: 'GitRepo represents a git repository at + description: 'gitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo @@ -6857,37 +7375,38 @@ spec: container.' properties: directory: - description: Target directory name. Must not contain - or start with '..'. If '.' is supplied, the volume - directory will be the git repository. Otherwise, - if specified, the volume will contain the git - repository in the subdirectory with the given - name. + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. type: string repository: - description: Repository URL + description: repository is the URL type: string revision: - description: Commit hash for the specified revision. + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: - description: 'Glusterfs represents a Glusterfs mount + description: 'glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: - description: 'EndpointsName is the endpoint name - that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: - description: 'Path is the Glusterfs volume path. + description: 'path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: - description: 'ReadOnly here will force the Glusterfs + description: 'readOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean @@ -6896,7 +7415,7 @@ spec: - path type: object hostPath: - description: 'HostPath represents a pre-existing file + description: 'hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are @@ -6907,71 +7426,73 @@ spec: directories as read/write.' properties: path: - description: 'Path of the directory on the host. + description: 'path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: - description: 'Type for HostPath Volume Defaults + description: 'type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: - description: 'ISCSI represents an ISCSI Disk resource + description: 'iscsi represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP - authentication + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: - description: whether support iSCSI Session CHAP - authentication + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName - is specified with iscsiInterface simultaneously, - new iSCSI interface : - will be created for the connection. + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: - description: Target iSCSI Qualified Name. + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI - transport. Defaults to 'default' (tcp). + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). type: string lun: - description: iSCSI Target Lun number. + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: - description: iSCSI Target Portal List. The portal - is either an IP or ip_addr:port if the port is - other than default (typically TCP ports 860 and - 3260). + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). items: type: string type: array readOnly: - description: ReadOnly here will force the ReadOnly + description: readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: - description: CHAP Secret for iSCSI target and initiator - authentication + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: description: 'Name of the referent. More info: @@ -6981,9 +7502,10 @@ spec: type: string type: object targetPortal: - description: iSCSI Target Portal. The Portal is - either an IP or ip_addr:port if the port is other - than default (typically TCP ports 860 and 3260). + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). type: string required: - iqn @@ -6991,24 +7513,24 @@ spec: - targetPortal type: object name: - description: 'Volume''s name. Must be a DNS_LABEL and - unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: - description: 'NFS represents an NFS mount on the host + description: 'nfs represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: - description: 'Path that is exported by the NFS server. + description: 'path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: - description: 'ReadOnly here will force the NFS export + description: 'readOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: - description: 'Server is the hostname or IP address + description: 'server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: @@ -7016,132 +7538,133 @@ spec: - server type: object persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents + description: 'persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim + description: 'claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: - description: Will force the ReadOnly setting in - VolumeMounts. Default false. + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController + description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: - description: ID that identifies Photon Controller - persistent disk + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: - description: PortworxVolume represents a portworx volume + description: portworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: - description: FSType represents the filesystem type + description: fSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean volumeID: - description: VolumeID uniquely identifies a Portworx + description: volumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: - description: Items for all in one resources secrets, - configmaps, and downward API + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: - description: Mode bits used to set permissions on - created files by default. Must be an octal value - between 0000 and 0777 or a decimal value between - 0 and 511. YAML accepts both octal and decimal - values, JSON requires decimal values for mode - bits. Directories within the path are not affected - by this setting. This might be in conflict with - other options that affect the file mode, like - fsGroup, and the result can be other mode bits - set. + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. format: int32 type: integer sources: - description: list of volume projections + description: sources is the list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: - description: information about the configMap - data to project + description: configMap information about the + configMap data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - ConfigMap will be projected into the - volume as a file whose name is the key - and content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the ConfigMap, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -7156,13 +7679,13 @@ spec: kind, uid?' type: string optional: - description: Specify whether the ConfigMap - or its keys must be defined + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object downwardAPI: - description: information about the downwardAPI - data to project + description: downwardAPI information about + the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume @@ -7252,53 +7775,53 @@ spec: type: array type: object secret: - description: information about the secret - data to project + description: secret information about the + secret data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - Secret will be projected into the volume - as a file whose name is the key and - content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the Secret, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -7313,16 +7836,16 @@ spec: kind, uid?' type: string optional: - description: Specify whether the Secret - or its key must be defined + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object serviceAccountToken: - description: information about the serviceAccountToken - data to project + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: - description: Audience is the intended + description: audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience @@ -7331,7 +7854,7 @@ spec: the identifier of the apiserver. type: string expirationSeconds: - description: ExpirationSeconds is the + description: expirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume @@ -7345,7 +7868,7 @@ spec: format: int64 type: integer path: - description: Path is the path relative + description: path is the path relative to the mount point of the file to project the token into. type: string @@ -7356,36 +7879,36 @@ spec: type: array type: object quobyte: - description: Quobyte represents a Quobyte mount on the + description: quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: - description: Group to map volume access to Default + description: group to map volume access to Default is no group type: string readOnly: - description: ReadOnly here will force the Quobyte + description: readOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: - description: Registry represents a single or multiple + description: registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: - description: Tenant owning the given Quobyte volume + description: tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: - description: User to map volume access to Defaults + description: user to map volume access to Defaults to serivceaccount user type: string volume: - description: Volume is a string that references + description: volume is a string that references an already created Quobyte volume by name. type: string required: @@ -7393,44 +7916,46 @@ spec: - volume type: object rbd: - description: 'RBD represents a Rados Block Device mount + description: 'rbd represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: - description: 'Keyring is the path to key ring for + description: 'keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: - description: 'A collection of Ceph monitors. More - info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: - description: 'The rados pool name. Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: - description: 'SecretRef is name of the authentication + description: 'secretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: @@ -7442,37 +7967,38 @@ spec: type: string type: object user: - description: 'The rados user name. Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: - description: ScaleIO represents a ScaleIO persistent + description: scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Default is - "xfs". + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". type: string gateway: - description: The host address of the ScaleIO API - Gateway. + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: - description: The name of the ScaleIO Protection - Domain for the configured storage. + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef references to the secret + description: secretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. @@ -7485,26 +8011,26 @@ spec: type: string type: object sslEnabled: - description: Flag to enable/disable SSL communication - with Gateway, default false + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: - description: Indicates whether the storage for a - volume should be ThickProvisioned or ThinProvisioned. + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: - description: The ScaleIO Storage Pool associated - with the protection domain. + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: - description: The name of the storage system as configured - in ScaleIO. + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: - description: The name of a volume already created - in the ScaleIO system that is associated with - this volume source. + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. type: string required: - gateway @@ -7512,27 +8038,27 @@ spec: - system type: object secret: - description: 'Secret represents a secret that should + description: 'secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced Secret will - be projected into the volume as a file whose name - is the key and content is the value. If specified, + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in @@ -7545,26 +8071,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -7572,30 +8100,31 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys - must be defined + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace - to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: - description: StorageOS represents a StorageOS volume + description: storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef specifies the secret to use + description: secretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: @@ -7607,12 +8136,12 @@ spec: type: string type: object volumeName: - description: VolumeName is the human-readable name + description: volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: - description: VolumeNamespace specifies the scope + description: volumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping @@ -7624,26 +8153,27 @@ spec: type: string type: object vsphereVolume: - description: VsphereVolume represents a vSphere volume + description: vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: - description: Storage Policy Based Management (SPBM) - profile ID associated with the StoragePolicyName. + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: - description: Storage Policy Based Management (SPBM) - profile name. + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: - description: Path that identifies vSphere volume - vmdk + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 6fc75fa00..a7ad7a93e 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -66,37 +66,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -105,10 +106,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -116,12 +117,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -167,6 +168,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -187,7 +210,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -215,10 +239,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -359,6 +402,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -379,7 +444,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -704,9 +770,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -763,7 +827,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -867,9 +931,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -924,7 +986,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -1028,9 +1090,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -1087,7 +1147,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -1191,9 +1251,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -1248,7 +1306,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -1723,9 +1781,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -1782,7 +1838,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -1886,9 +1942,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -1943,7 +1997,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -2047,9 +2101,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -2106,7 +2158,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -2210,9 +2262,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -2267,7 +2317,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -2427,6 +2477,27 @@ spec: resources: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be set + for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2447,7 +2518,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object securityContext: @@ -2539,7 +2611,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -2553,9 +2626,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -2598,14 +2676,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -2747,6 +2822,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2767,8 +2864,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -2800,24 +2897,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -2836,27 +2936,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -2870,18 +2977,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2903,12 +3044,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -2953,8 +3095,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -2962,20 +3104,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -2983,19 +3170,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -3004,36 +3203,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -3047,14 +3247,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -3108,123 +3301,128 @@ spec: may be accessed by any container in the pod. properties: awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS + description: 'awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty).' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: - description: 'Specify "true" to force and set the - ReadOnly property in VolumeMounts to "true". If - omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: - description: 'Unique ID of the persistent disk resource - in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: - description: AzureDisk represents an Azure Data Disk + description: azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: - description: 'Host Caching mode: None, Read Only, - Read Write.' + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: - description: The Name of the data disk in the blob - storage + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: - description: The URI the data disk in the blob storage + description: diskURI is the URI of data disk in + the blob storage type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: - description: 'Expected values Shared: multiple blob - disks per storage account Dedicated: single blob - disk per storage account Managed: azure managed - data disk (only in managed availability set). - defaults to shared' + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: - description: AzureFile represents an Azure File Service + description: azureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretName: - description: the name of secret that contains Azure - Storage Account Name and Key + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: - description: Share Name + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: - description: CephFS represents a Ceph FS mount on the + description: cephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: - description: 'Required: Monitors is a collection - of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: - description: 'Optional: Used as the mounted root, - rather than the full Ceph tree, default is /' + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: - description: 'Optional: SecretFile is the path to - key ring for User, default is /etc/ceph/user.secret + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: - description: 'Optional: SecretRef is reference to - the authentication secret for User, default is - empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: @@ -3234,31 +3432,32 @@ spec: type: string type: object user: - description: 'Optional: User is the rados user name, - default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: - description: 'Cinder represents a cinder volume attached + description: 'cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Examples: "ext4", "xfs", "ntfs". Implicitly - inferred to be "ext4" if unspecified. More info: - https://examples.k8s.io/mysql-cinder-pd/README.md' + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: - description: 'Optional: Defaults to false (read/write). + description: 'readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: - description: 'Optional: points to a secret object - containing parameters used to connect to OpenStack.' + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' properties: name: description: 'Name of the referent. More info: @@ -3268,32 +3467,32 @@ spec: type: string type: object volumeID: - description: 'volume id used to identify the volume + description: 'volumeID used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: - description: ConfigMap represents a configMap that should + description: configMap represents a configMap that should populate this volume properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced ConfigMap + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified @@ -3308,26 +3507,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -3340,28 +3541,28 @@ spec: uid?' type: string optional: - description: Specify whether the ConfigMap or its - keys must be defined + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object csi: - description: CSI (Container Storage Interface) represents + description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external CSI drivers (Beta feature). properties: driver: - description: Driver is the name of the CSI driver + description: driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: - description: Filesystem type to mount. Ex. "ext4", - "xfs", "ntfs". If not provided, the empty value - is passed to the associated CSI driver which will - determine the default filesystem to apply. + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. type: string nodePublishSecretRef: - description: NodePublishSecretRef is a reference + description: nodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. @@ -3378,13 +3579,13 @@ spec: type: string type: object readOnly: - description: Specifies a read-only configuration + description: readOnly specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string - description: VolumeAttributes stores driver-specific + description: volumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. @@ -3393,7 +3594,7 @@ spec: - driver type: object downwardAPI: - description: DownwardAPI represents downward API about + description: downwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: @@ -3486,32 +3687,33 @@ spec: type: array type: object emptyDir: - description: 'EmptyDir represents a temporary directory + description: 'emptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: - description: 'What type of storage medium should - back this directory. The default is "" which means - to use the node''s default medium. Must be an - empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string - description: 'Total amount of local storage required - for this EmptyDir volume. The size limit is also - applicable for memory medium. The maximum usage - on memory medium EmptyDir would be the minimum - value between the SizeLimit specified here and - the sum of memory limits of all containers in - a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object ephemeral: - description: "Ephemeral represents a volume that is + description: "ephemeral represents a volume that is handled by a cluster storage driver. The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted @@ -3571,25 +3773,28 @@ spec: are also valid here. properties: accessModes: - description: 'AccessModes contains the desired + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to - specify either: * An existing VolumeSnapshot + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate - is enabled, this field will always have - the same contents as the DataSourceRef - field.' + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for @@ -3612,33 +3817,41 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from - which to populate the volume with data, - if a non-empty volume is desired. This - may be any local object from a non-empty + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the - functionality of the DataSource field + functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards - compatibility, both fields (DataSource - and DataSourceRef) will be set to the + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value automatically if one of them - is empty and the other is non-empty. There - are two important differences between - DataSource and DataSourceRef: * While - DataSource only allows two specific types - of objects, DataSourceRef allows any - non-core object, as well as PersistentVolumeClaim - objects. * While DataSource ignores disallowed - values (dropping them), DataSourceRef preserves + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves all values, and generates an error if - a disallowed value is specified. (Alpha) - Using this field requires the AnyVolumeDataSource + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' properties: apiGroup: @@ -3657,12 +3870,25 @@ spec: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are @@ -3671,6 +3897,32 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -3695,12 +3947,13 @@ spec: a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes - to consider for binding. + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: description: matchExpressions is a list @@ -3754,8 +4007,9 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required - by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type @@ -3764,7 +4018,7 @@ spec: in claim spec. type: string volumeName: - description: VolumeName is the binding reference + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object @@ -3773,74 +4027,75 @@ spec: type: object type: object fc: - description: FC represents a Fibre Channel resource + description: fc represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: - description: 'Optional: FC target lun number' + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: - description: 'Optional: FC target worldwide names - (WWNs)' + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array wwids: - description: 'Optional: FC volume world wide identifiers - (wwids) Either wwids or combination of targetWWNs - and lun must be set, but not both simultaneously.' + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' items: type: string type: array type: object flexVolume: - description: FlexVolume represents a generic volume + description: flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: - description: Driver is the name of the driver to + description: driver is the name of the driver to use for this volume. type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". The default - filesystem depends on FlexVolume script. + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string - description: 'Optional: Extra command options if - any.' + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean secretRef: - description: 'Optional: SecretRef is reference to - the secret object containing sensitive information - to pass to the plugin scripts. This may be empty - if no secret object is specified. If the secret - object contains more than one secret, all secrets - are passed to the plugin scripts.' + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: @@ -3853,28 +4108,28 @@ spec: - driver type: object flocker: - description: Flocker represents a Flocker volume attached + description: flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: - description: Name of the dataset stored as metadata - -> name on the dataset for Flocker should be considered - as deprecated + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated type: string datasetUUID: - description: UUID of the dataset. This is unique - identifier of a Flocker dataset + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk + description: 'gcePersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk @@ -3882,21 +4137,22 @@ spec: from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: - description: 'Unique name of the PD resource in - GCE. Used to identify the disk in GCE. More info: - https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean @@ -3904,7 +4160,7 @@ spec: - pdName type: object gitRepo: - description: 'GitRepo represents a git repository at + description: 'gitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo @@ -3912,37 +4168,38 @@ spec: container.' properties: directory: - description: Target directory name. Must not contain - or start with '..'. If '.' is supplied, the volume - directory will be the git repository. Otherwise, - if specified, the volume will contain the git - repository in the subdirectory with the given - name. + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. type: string repository: - description: Repository URL + description: repository is the URL type: string revision: - description: Commit hash for the specified revision. + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: - description: 'Glusterfs represents a Glusterfs mount + description: 'glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: - description: 'EndpointsName is the endpoint name - that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: - description: 'Path is the Glusterfs volume path. + description: 'path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: - description: 'ReadOnly here will force the Glusterfs + description: 'readOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean @@ -3951,7 +4208,7 @@ spec: - path type: object hostPath: - description: 'HostPath represents a pre-existing file + description: 'hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are @@ -3962,71 +4219,73 @@ spec: directories as read/write.' properties: path: - description: 'Path of the directory on the host. + description: 'path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: - description: 'Type for HostPath Volume Defaults + description: 'type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: - description: 'ISCSI represents an ISCSI Disk resource + description: 'iscsi represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP - authentication + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: - description: whether support iSCSI Session CHAP - authentication + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName - is specified with iscsiInterface simultaneously, - new iSCSI interface : - will be created for the connection. + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: - description: Target iSCSI Qualified Name. + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI - transport. Defaults to 'default' (tcp). + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). type: string lun: - description: iSCSI Target Lun number. + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: - description: iSCSI Target Portal List. The portal - is either an IP or ip_addr:port if the port is - other than default (typically TCP ports 860 and - 3260). + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). items: type: string type: array readOnly: - description: ReadOnly here will force the ReadOnly + description: readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: - description: CHAP Secret for iSCSI target and initiator - authentication + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: description: 'Name of the referent. More info: @@ -4036,9 +4295,10 @@ spec: type: string type: object targetPortal: - description: iSCSI Target Portal. The Portal is - either an IP or ip_addr:port if the port is other - than default (typically TCP ports 860 and 3260). + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). type: string required: - iqn @@ -4046,24 +4306,24 @@ spec: - targetPortal type: object name: - description: 'Volume''s name. Must be a DNS_LABEL and - unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: - description: 'NFS represents an NFS mount on the host + description: 'nfs represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: - description: 'Path that is exported by the NFS server. + description: 'path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: - description: 'ReadOnly here will force the NFS export + description: 'readOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: - description: 'Server is the hostname or IP address + description: 'server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: @@ -4071,132 +4331,133 @@ spec: - server type: object persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents + description: 'persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim + description: 'claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: - description: Will force the ReadOnly setting in - VolumeMounts. Default false. + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController + description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: - description: ID that identifies Photon Controller - persistent disk + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: - description: PortworxVolume represents a portworx volume + description: portworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: - description: FSType represents the filesystem type + description: fSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean volumeID: - description: VolumeID uniquely identifies a Portworx + description: volumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: - description: Items for all in one resources secrets, - configmaps, and downward API + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: - description: Mode bits used to set permissions on - created files by default. Must be an octal value - between 0000 and 0777 or a decimal value between - 0 and 511. YAML accepts both octal and decimal - values, JSON requires decimal values for mode - bits. Directories within the path are not affected - by this setting. This might be in conflict with - other options that affect the file mode, like - fsGroup, and the result can be other mode bits - set. + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. format: int32 type: integer sources: - description: list of volume projections + description: sources is the list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: - description: information about the configMap - data to project + description: configMap information about the + configMap data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - ConfigMap will be projected into the - volume as a file whose name is the key - and content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the ConfigMap, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -4211,13 +4472,13 @@ spec: kind, uid?' type: string optional: - description: Specify whether the ConfigMap - or its keys must be defined + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object downwardAPI: - description: information about the downwardAPI - data to project + description: downwardAPI information about + the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume @@ -4307,53 +4568,53 @@ spec: type: array type: object secret: - description: information about the secret - data to project + description: secret information about the + secret data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - Secret will be projected into the volume - as a file whose name is the key and - content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the Secret, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -4368,16 +4629,16 @@ spec: kind, uid?' type: string optional: - description: Specify whether the Secret - or its key must be defined + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object serviceAccountToken: - description: information about the serviceAccountToken - data to project + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: - description: Audience is the intended + description: audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience @@ -4386,7 +4647,7 @@ spec: the identifier of the apiserver. type: string expirationSeconds: - description: ExpirationSeconds is the + description: expirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume @@ -4400,7 +4661,7 @@ spec: format: int64 type: integer path: - description: Path is the path relative + description: path is the path relative to the mount point of the file to project the token into. type: string @@ -4411,36 +4672,36 @@ spec: type: array type: object quobyte: - description: Quobyte represents a Quobyte mount on the + description: quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: - description: Group to map volume access to Default + description: group to map volume access to Default is no group type: string readOnly: - description: ReadOnly here will force the Quobyte + description: readOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: - description: Registry represents a single or multiple + description: registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: - description: Tenant owning the given Quobyte volume + description: tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: - description: User to map volume access to Defaults + description: user to map volume access to Defaults to serivceaccount user type: string volume: - description: Volume is a string that references + description: volume is a string that references an already created Quobyte volume by name. type: string required: @@ -4448,44 +4709,46 @@ spec: - volume type: object rbd: - description: 'RBD represents a Rados Block Device mount + description: 'rbd represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: - description: 'Keyring is the path to key ring for + description: 'keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: - description: 'A collection of Ceph monitors. More - info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: - description: 'The rados pool name. Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: - description: 'SecretRef is name of the authentication + description: 'secretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: @@ -4497,37 +4760,38 @@ spec: type: string type: object user: - description: 'The rados user name. Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: - description: ScaleIO represents a ScaleIO persistent + description: scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Default is - "xfs". + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". type: string gateway: - description: The host address of the ScaleIO API - Gateway. + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: - description: The name of the ScaleIO Protection - Domain for the configured storage. + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef references to the secret + description: secretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. @@ -4540,26 +4804,26 @@ spec: type: string type: object sslEnabled: - description: Flag to enable/disable SSL communication - with Gateway, default false + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: - description: Indicates whether the storage for a - volume should be ThickProvisioned or ThinProvisioned. + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: - description: The ScaleIO Storage Pool associated - with the protection domain. + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: - description: The name of the storage system as configured - in ScaleIO. + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: - description: The name of a volume already created - in the ScaleIO system that is associated with - this volume source. + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. type: string required: - gateway @@ -4567,27 +4831,27 @@ spec: - system type: object secret: - description: 'Secret represents a secret that should + description: 'secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced Secret will - be projected into the volume as a file whose name - is the key and content is the value. If specified, + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in @@ -4600,26 +4864,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -4627,30 +4893,31 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys - must be defined + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace - to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: - description: StorageOS represents a StorageOS volume + description: storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef specifies the secret to use + description: secretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: @@ -4662,12 +4929,12 @@ spec: type: string type: object volumeName: - description: VolumeName is the human-readable name + description: volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: - description: VolumeNamespace specifies the scope + description: volumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping @@ -4679,26 +4946,27 @@ spec: type: string type: object vsphereVolume: - description: VsphereVolume represents a vSphere volume + description: vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: - description: Storage Policy Based Management (SPBM) - profile ID associated with the StoragePolicyName. + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: - description: Storage Policy Based Management (SPBM) - profile name. + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: - description: Path that identifies vSphere volume - vmdk + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -4784,37 +5052,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -4823,10 +5092,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -4834,12 +5103,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -4854,37 +5123,38 @@ spec: Secret volumes support ownership management and SELinux relabeling." properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -4893,10 +5163,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -4904,12 +5174,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object type: object @@ -5155,6 +5425,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5175,7 +5467,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -5215,6 +5508,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5235,7 +5550,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -5263,10 +5579,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -5369,7 +5704,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -5383,9 +5719,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -5428,14 +5769,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -5573,6 +5911,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5593,7 +5953,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -5918,9 +6279,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -5977,7 +6336,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -6081,9 +6440,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -6138,7 +6495,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -6242,9 +6599,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -6301,7 +6656,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -6405,9 +6760,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -6462,7 +6815,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -6697,7 +7050,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -6729,15 +7083,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -7111,9 +7462,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -7170,7 +7519,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -7274,9 +7623,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -7331,7 +7678,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -7435,9 +7782,7 @@ spec: this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty - selector ({}) matches all namespaces. This - field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. + selector ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list @@ -7494,7 +7839,7 @@ spec: listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this - pod's namespace" + pod's namespace". items: type: string type: array @@ -7598,9 +7943,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -7655,7 +7998,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -7890,7 +8233,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT + be set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -7922,15 +8266,12 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is - alpha-level and will only be honored by components that - enable the WindowsHostProcessContainers feature flag. - Setting this field without the feature flag will result - in errors when validating the Pod. All of a Pod's containers - must have the same effective HostProcess value (it is - not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -7989,6 +8330,27 @@ spec: resources: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be set + for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -8009,7 +8371,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object serviceAccountName: @@ -8221,6 +8584,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -8241,8 +8626,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -8276,24 +8661,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -8312,27 +8700,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -8346,18 +8741,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -8379,12 +8808,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -8429,8 +8859,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -8438,20 +8868,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -8459,19 +8934,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -8480,36 +8967,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -8523,14 +9011,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -8554,24 +9035,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -8590,27 +9074,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -8624,18 +9115,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -8657,12 +9182,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -8707,8 +9233,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -8716,20 +9242,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -8737,19 +9308,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -8758,36 +9341,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -8801,14 +9385,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -8862,123 +9439,128 @@ spec: may be accessed by any container in the pod. properties: awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS + description: 'awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty).' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: - description: 'Specify "true" to force and set the - ReadOnly property in VolumeMounts to "true". If - omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: - description: 'Unique ID of the persistent disk resource - in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: - description: AzureDisk represents an Azure Data Disk + description: azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: - description: 'Host Caching mode: None, Read Only, - Read Write.' + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: - description: The Name of the data disk in the blob - storage + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: - description: The URI the data disk in the blob storage + description: diskURI is the URI of data disk in + the blob storage type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: - description: 'Expected values Shared: multiple blob - disks per storage account Dedicated: single blob - disk per storage account Managed: azure managed - data disk (only in managed availability set). - defaults to shared' + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: - description: AzureFile represents an Azure File Service + description: azureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretName: - description: the name of secret that contains Azure - Storage Account Name and Key + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: - description: Share Name + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: - description: CephFS represents a Ceph FS mount on the + description: cephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: - description: 'Required: Monitors is a collection - of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: - description: 'Optional: Used as the mounted root, - rather than the full Ceph tree, default is /' + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: - description: 'Optional: SecretFile is the path to - key ring for User, default is /etc/ceph/user.secret + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: - description: 'Optional: SecretRef is reference to - the authentication secret for User, default is - empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: @@ -8988,31 +9570,32 @@ spec: type: string type: object user: - description: 'Optional: User is the rados user name, - default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: - description: 'Cinder represents a cinder volume attached + description: 'cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Examples: "ext4", "xfs", "ntfs". Implicitly - inferred to be "ext4" if unspecified. More info: - https://examples.k8s.io/mysql-cinder-pd/README.md' + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: - description: 'Optional: Defaults to false (read/write). + description: 'readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: - description: 'Optional: points to a secret object - containing parameters used to connect to OpenStack.' + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' properties: name: description: 'Name of the referent. More info: @@ -9022,32 +9605,32 @@ spec: type: string type: object volumeID: - description: 'volume id used to identify the volume + description: 'volumeID used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: - description: ConfigMap represents a configMap that should + description: configMap represents a configMap that should populate this volume properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced ConfigMap + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified @@ -9062,26 +9645,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -9094,28 +9679,28 @@ spec: uid?' type: string optional: - description: Specify whether the ConfigMap or its - keys must be defined + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object csi: - description: CSI (Container Storage Interface) represents + description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external CSI drivers (Beta feature). properties: driver: - description: Driver is the name of the CSI driver + description: driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: - description: Filesystem type to mount. Ex. "ext4", - "xfs", "ntfs". If not provided, the empty value - is passed to the associated CSI driver which will - determine the default filesystem to apply. + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. type: string nodePublishSecretRef: - description: NodePublishSecretRef is a reference + description: nodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. @@ -9132,13 +9717,13 @@ spec: type: string type: object readOnly: - description: Specifies a read-only configuration + description: readOnly specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string - description: VolumeAttributes stores driver-specific + description: volumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. @@ -9147,7 +9732,7 @@ spec: - driver type: object downwardAPI: - description: DownwardAPI represents downward API about + description: downwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: @@ -9240,32 +9825,33 @@ spec: type: array type: object emptyDir: - description: 'EmptyDir represents a temporary directory + description: 'emptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: - description: 'What type of storage medium should - back this directory. The default is "" which means - to use the node''s default medium. Must be an - empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string - description: 'Total amount of local storage required - for this EmptyDir volume. The size limit is also - applicable for memory medium. The maximum usage - on memory medium EmptyDir would be the minimum - value between the SizeLimit specified here and - the sum of memory limits of all containers in - a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object ephemeral: - description: "Ephemeral represents a volume that is + description: "ephemeral represents a volume that is handled by a cluster storage driver. The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted @@ -9325,25 +9911,28 @@ spec: are also valid here. properties: accessModes: - description: 'AccessModes contains the desired + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to - specify either: * An existing VolumeSnapshot + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate - is enabled, this field will always have - the same contents as the DataSourceRef - field.' + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for @@ -9366,33 +9955,41 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from - which to populate the volume with data, - if a non-empty volume is desired. This - may be any local object from a non-empty + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the - functionality of the DataSource field + functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards - compatibility, both fields (DataSource - and DataSourceRef) will be set to the + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value automatically if one of them - is empty and the other is non-empty. There - are two important differences between - DataSource and DataSourceRef: * While - DataSource only allows two specific types - of objects, DataSourceRef allows any - non-core object, as well as PersistentVolumeClaim - objects. * While DataSource ignores disallowed - values (dropping them), DataSourceRef preserves + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves all values, and generates an error if - a disallowed value is specified. (Alpha) - Using this field requires the AnyVolumeDataSource + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' properties: apiGroup: @@ -9411,12 +10008,25 @@ spec: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are @@ -9425,6 +10035,32 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -9449,12 +10085,13 @@ spec: a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes - to consider for binding. + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: description: matchExpressions is a list @@ -9508,8 +10145,9 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required - by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type @@ -9518,7 +10156,7 @@ spec: in claim spec. type: string volumeName: - description: VolumeName is the binding reference + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object @@ -9527,74 +10165,75 @@ spec: type: object type: object fc: - description: FC represents a Fibre Channel resource + description: fc represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: - description: 'Optional: FC target lun number' + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: - description: 'Optional: FC target worldwide names - (WWNs)' + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array wwids: - description: 'Optional: FC volume world wide identifiers - (wwids) Either wwids or combination of targetWWNs - and lun must be set, but not both simultaneously.' + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' items: type: string type: array type: object flexVolume: - description: FlexVolume represents a generic volume + description: flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: - description: Driver is the name of the driver to + description: driver is the name of the driver to use for this volume. type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". The default - filesystem depends on FlexVolume script. + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string - description: 'Optional: Extra command options if - any.' + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean secretRef: - description: 'Optional: SecretRef is reference to - the secret object containing sensitive information - to pass to the plugin scripts. This may be empty - if no secret object is specified. If the secret - object contains more than one secret, all secrets - are passed to the plugin scripts.' + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: @@ -9607,28 +10246,28 @@ spec: - driver type: object flocker: - description: Flocker represents a Flocker volume attached + description: flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: - description: Name of the dataset stored as metadata - -> name on the dataset for Flocker should be considered - as deprecated + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated type: string datasetUUID: - description: UUID of the dataset. This is unique - identifier of a Flocker dataset + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk + description: 'gcePersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk @@ -9636,21 +10275,22 @@ spec: from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: - description: 'Unique name of the PD resource in - GCE. Used to identify the disk in GCE. More info: - https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean @@ -9658,7 +10298,7 @@ spec: - pdName type: object gitRepo: - description: 'GitRepo represents a git repository at + description: 'gitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo @@ -9666,37 +10306,38 @@ spec: container.' properties: directory: - description: Target directory name. Must not contain - or start with '..'. If '.' is supplied, the volume - directory will be the git repository. Otherwise, - if specified, the volume will contain the git - repository in the subdirectory with the given - name. + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. type: string repository: - description: Repository URL + description: repository is the URL type: string revision: - description: Commit hash for the specified revision. + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: - description: 'Glusterfs represents a Glusterfs mount + description: 'glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: - description: 'EndpointsName is the endpoint name - that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: - description: 'Path is the Glusterfs volume path. + description: 'path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: - description: 'ReadOnly here will force the Glusterfs + description: 'readOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean @@ -9705,7 +10346,7 @@ spec: - path type: object hostPath: - description: 'HostPath represents a pre-existing file + description: 'hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are @@ -9716,71 +10357,73 @@ spec: directories as read/write.' properties: path: - description: 'Path of the directory on the host. + description: 'path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: - description: 'Type for HostPath Volume Defaults + description: 'type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: - description: 'ISCSI represents an ISCSI Disk resource + description: 'iscsi represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP - authentication + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: - description: whether support iSCSI Session CHAP - authentication + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName - is specified with iscsiInterface simultaneously, - new iSCSI interface : - will be created for the connection. + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: - description: Target iSCSI Qualified Name. + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI - transport. Defaults to 'default' (tcp). + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). type: string lun: - description: iSCSI Target Lun number. + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: - description: iSCSI Target Portal List. The portal - is either an IP or ip_addr:port if the port is - other than default (typically TCP ports 860 and - 3260). + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). items: type: string type: array readOnly: - description: ReadOnly here will force the ReadOnly + description: readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: - description: CHAP Secret for iSCSI target and initiator - authentication + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: description: 'Name of the referent. More info: @@ -9790,9 +10433,10 @@ spec: type: string type: object targetPortal: - description: iSCSI Target Portal. The Portal is - either an IP or ip_addr:port if the port is other - than default (typically TCP ports 860 and 3260). + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). type: string required: - iqn @@ -9800,24 +10444,24 @@ spec: - targetPortal type: object name: - description: 'Volume''s name. Must be a DNS_LABEL and - unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: - description: 'NFS represents an NFS mount on the host + description: 'nfs represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: - description: 'Path that is exported by the NFS server. + description: 'path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: - description: 'ReadOnly here will force the NFS export + description: 'readOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: - description: 'Server is the hostname or IP address + description: 'server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: @@ -9825,132 +10469,133 @@ spec: - server type: object persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents + description: 'persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim + description: 'claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: - description: Will force the ReadOnly setting in - VolumeMounts. Default false. + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController + description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: - description: ID that identifies Photon Controller - persistent disk + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: - description: PortworxVolume represents a portworx volume + description: portworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: - description: FSType represents the filesystem type + description: fSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean volumeID: - description: VolumeID uniquely identifies a Portworx + description: volumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: - description: Items for all in one resources secrets, - configmaps, and downward API + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: - description: Mode bits used to set permissions on - created files by default. Must be an octal value - between 0000 and 0777 or a decimal value between - 0 and 511. YAML accepts both octal and decimal - values, JSON requires decimal values for mode - bits. Directories within the path are not affected - by this setting. This might be in conflict with - other options that affect the file mode, like - fsGroup, and the result can be other mode bits - set. + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. format: int32 type: integer sources: - description: list of volume projections + description: sources is the list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: - description: information about the configMap - data to project + description: configMap information about the + configMap data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - ConfigMap will be projected into the - volume as a file whose name is the key - and content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the ConfigMap, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -9965,13 +10610,13 @@ spec: kind, uid?' type: string optional: - description: Specify whether the ConfigMap - or its keys must be defined + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object downwardAPI: - description: information about the downwardAPI - data to project + description: downwardAPI information about + the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume @@ -10061,53 +10706,53 @@ spec: type: array type: object secret: - description: information about the secret - data to project + description: secret information about the + secret data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - Secret will be projected into the volume - as a file whose name is the key and - content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the Secret, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -10122,16 +10767,16 @@ spec: kind, uid?' type: string optional: - description: Specify whether the Secret - or its key must be defined + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object serviceAccountToken: - description: information about the serviceAccountToken - data to project + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: - description: Audience is the intended + description: audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience @@ -10140,7 +10785,7 @@ spec: the identifier of the apiserver. type: string expirationSeconds: - description: ExpirationSeconds is the + description: expirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume @@ -10154,7 +10799,7 @@ spec: format: int64 type: integer path: - description: Path is the path relative + description: path is the path relative to the mount point of the file to project the token into. type: string @@ -10165,36 +10810,36 @@ spec: type: array type: object quobyte: - description: Quobyte represents a Quobyte mount on the + description: quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: - description: Group to map volume access to Default + description: group to map volume access to Default is no group type: string readOnly: - description: ReadOnly here will force the Quobyte + description: readOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: - description: Registry represents a single or multiple + description: registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: - description: Tenant owning the given Quobyte volume + description: tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: - description: User to map volume access to Defaults + description: user to map volume access to Defaults to serivceaccount user type: string volume: - description: Volume is a string that references + description: volume is a string that references an already created Quobyte volume by name. type: string required: @@ -10202,44 +10847,46 @@ spec: - volume type: object rbd: - description: 'RBD represents a Rados Block Device mount + description: 'rbd represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: - description: 'Keyring is the path to key ring for + description: 'keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: - description: 'A collection of Ceph monitors. More - info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: - description: 'The rados pool name. Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: - description: 'SecretRef is name of the authentication + description: 'secretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: @@ -10251,37 +10898,38 @@ spec: type: string type: object user: - description: 'The rados user name. Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: - description: ScaleIO represents a ScaleIO persistent + description: scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Default is - "xfs". + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". type: string gateway: - description: The host address of the ScaleIO API - Gateway. + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: - description: The name of the ScaleIO Protection - Domain for the configured storage. + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef references to the secret + description: secretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. @@ -10294,26 +10942,26 @@ spec: type: string type: object sslEnabled: - description: Flag to enable/disable SSL communication - with Gateway, default false + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: - description: Indicates whether the storage for a - volume should be ThickProvisioned or ThinProvisioned. + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: - description: The ScaleIO Storage Pool associated - with the protection domain. + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: - description: The name of the storage system as configured - in ScaleIO. + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: - description: The name of a volume already created - in the ScaleIO system that is associated with - this volume source. + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. type: string required: - gateway @@ -10321,27 +10969,27 @@ spec: - system type: object secret: - description: 'Secret represents a secret that should + description: 'secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced Secret will - be projected into the volume as a file whose name - is the key and content is the value. If specified, + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in @@ -10354,26 +11002,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -10381,30 +11031,31 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys - must be defined + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace - to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: - description: StorageOS represents a StorageOS volume + description: storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef specifies the secret to use + description: secretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: @@ -10416,12 +11067,12 @@ spec: type: string type: object volumeName: - description: VolumeName is the human-readable name + description: volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: - description: VolumeNamespace specifies the scope + description: volumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping @@ -10433,26 +11084,27 @@ spec: type: string type: object vsphereVolume: - description: VsphereVolume represents a vSphere volume + description: vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: - description: Storage Policy Based Management (SPBM) - profile ID associated with the StoragePolicyName. + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: - description: Storage Policy Based Management (SPBM) - profile name. + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: - description: Path that identifies vSphere volume - vmdk + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index 29c728ace..80142c4d2 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -48,37 +48,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -87,10 +88,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -98,12 +99,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -398,9 +399,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -455,7 +454,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -554,8 +553,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -606,7 +603,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -707,9 +704,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -764,7 +759,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -863,8 +858,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -915,7 +908,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -971,6 +964,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -991,7 +1006,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -1019,10 +1035,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -1241,6 +1276,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1261,7 +1318,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -1356,7 +1414,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -1370,9 +1429,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -1415,14 +1479,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -1564,6 +1625,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1584,8 +1667,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -1617,24 +1700,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -1653,27 +1739,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -1687,18 +1780,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1720,12 +1847,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -1770,8 +1898,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -1779,20 +1907,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -1800,19 +1973,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -1821,36 +2006,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -1864,14 +2050,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -1925,123 +2104,128 @@ spec: may be accessed by any container in the pod. properties: awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS + description: 'awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty).' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: - description: 'Specify "true" to force and set the - ReadOnly property in VolumeMounts to "true". If - omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: - description: 'Unique ID of the persistent disk resource - in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: - description: AzureDisk represents an Azure Data Disk + description: azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: - description: 'Host Caching mode: None, Read Only, - Read Write.' + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: - description: The Name of the data disk in the blob - storage + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: - description: The URI the data disk in the blob storage + description: diskURI is the URI of data disk in + the blob storage type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: - description: 'Expected values Shared: multiple blob - disks per storage account Dedicated: single blob - disk per storage account Managed: azure managed - data disk (only in managed availability set). - defaults to shared' + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: - description: AzureFile represents an Azure File Service + description: azureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretName: - description: the name of secret that contains Azure - Storage Account Name and Key + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: - description: Share Name + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: - description: CephFS represents a Ceph FS mount on the + description: cephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: - description: 'Required: Monitors is a collection - of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: - description: 'Optional: Used as the mounted root, - rather than the full Ceph tree, default is /' + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: - description: 'Optional: SecretFile is the path to - key ring for User, default is /etc/ceph/user.secret + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: - description: 'Optional: SecretRef is reference to - the authentication secret for User, default is - empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: @@ -2051,31 +2235,32 @@ spec: type: string type: object user: - description: 'Optional: User is the rados user name, - default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: - description: 'Cinder represents a cinder volume attached + description: 'cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Examples: "ext4", "xfs", "ntfs". Implicitly - inferred to be "ext4" if unspecified. More info: - https://examples.k8s.io/mysql-cinder-pd/README.md' + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: - description: 'Optional: Defaults to false (read/write). + description: 'readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: - description: 'Optional: points to a secret object - containing parameters used to connect to OpenStack.' + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' properties: name: description: 'Name of the referent. More info: @@ -2085,32 +2270,32 @@ spec: type: string type: object volumeID: - description: 'volume id used to identify the volume + description: 'volumeID used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: - description: ConfigMap represents a configMap that should + description: configMap represents a configMap that should populate this volume properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced ConfigMap + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified @@ -2125,26 +2310,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -2157,28 +2344,28 @@ spec: uid?' type: string optional: - description: Specify whether the ConfigMap or its - keys must be defined + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object csi: - description: CSI (Container Storage Interface) represents + description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external CSI drivers (Beta feature). properties: driver: - description: Driver is the name of the CSI driver + description: driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: - description: Filesystem type to mount. Ex. "ext4", - "xfs", "ntfs". If not provided, the empty value - is passed to the associated CSI driver which will - determine the default filesystem to apply. + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. type: string nodePublishSecretRef: - description: NodePublishSecretRef is a reference + description: nodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. @@ -2195,13 +2382,13 @@ spec: type: string type: object readOnly: - description: Specifies a read-only configuration + description: readOnly specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string - description: VolumeAttributes stores driver-specific + description: volumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. @@ -2210,7 +2397,7 @@ spec: - driver type: object downwardAPI: - description: DownwardAPI represents downward API about + description: downwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: @@ -2303,32 +2490,33 @@ spec: type: array type: object emptyDir: - description: 'EmptyDir represents a temporary directory + description: 'emptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: - description: 'What type of storage medium should - back this directory. The default is "" which means - to use the node''s default medium. Must be an - empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string - description: 'Total amount of local storage required - for this EmptyDir volume. The size limit is also - applicable for memory medium. The maximum usage - on memory medium EmptyDir would be the minimum - value between the SizeLimit specified here and - the sum of memory limits of all containers in - a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object ephemeral: - description: "Ephemeral represents a volume that is + description: "ephemeral represents a volume that is handled by a cluster storage driver. The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted @@ -2388,25 +2576,28 @@ spec: are also valid here. properties: accessModes: - description: 'AccessModes contains the desired + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to - specify either: * An existing VolumeSnapshot + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate - is enabled, this field will always have - the same contents as the DataSourceRef - field.' + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for @@ -2429,33 +2620,41 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from - which to populate the volume with data, - if a non-empty volume is desired. This - may be any local object from a non-empty + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the - functionality of the DataSource field + functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards - compatibility, both fields (DataSource - and DataSourceRef) will be set to the + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value automatically if one of them - is empty and the other is non-empty. There - are two important differences between - DataSource and DataSourceRef: * While - DataSource only allows two specific types - of objects, DataSourceRef allows any - non-core object, as well as PersistentVolumeClaim - objects. * While DataSource ignores disallowed - values (dropping them), DataSourceRef preserves + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves all values, and generates an error if - a disallowed value is specified. (Alpha) - Using this field requires the AnyVolumeDataSource + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' properties: apiGroup: @@ -2474,12 +2673,25 @@ spec: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are @@ -2488,6 +2700,32 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2512,12 +2750,13 @@ spec: a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes - to consider for binding. + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: description: matchExpressions is a list @@ -2571,8 +2810,9 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required - by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type @@ -2581,7 +2821,7 @@ spec: in claim spec. type: string volumeName: - description: VolumeName is the binding reference + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object @@ -2590,74 +2830,75 @@ spec: type: object type: object fc: - description: FC represents a Fibre Channel resource + description: fc represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: - description: 'Optional: FC target lun number' + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: - description: 'Optional: FC target worldwide names - (WWNs)' + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array wwids: - description: 'Optional: FC volume world wide identifiers - (wwids) Either wwids or combination of targetWWNs - and lun must be set, but not both simultaneously.' + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' items: type: string type: array type: object flexVolume: - description: FlexVolume represents a generic volume + description: flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: - description: Driver is the name of the driver to + description: driver is the name of the driver to use for this volume. type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". The default - filesystem depends on FlexVolume script. + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string - description: 'Optional: Extra command options if - any.' + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean secretRef: - description: 'Optional: SecretRef is reference to - the secret object containing sensitive information - to pass to the plugin scripts. This may be empty - if no secret object is specified. If the secret - object contains more than one secret, all secrets - are passed to the plugin scripts.' + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: @@ -2670,28 +2911,28 @@ spec: - driver type: object flocker: - description: Flocker represents a Flocker volume attached + description: flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: - description: Name of the dataset stored as metadata - -> name on the dataset for Flocker should be considered - as deprecated + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated type: string datasetUUID: - description: UUID of the dataset. This is unique - identifier of a Flocker dataset + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk + description: 'gcePersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk @@ -2699,21 +2940,22 @@ spec: from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: - description: 'Unique name of the PD resource in - GCE. Used to identify the disk in GCE. More info: - https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean @@ -2721,7 +2963,7 @@ spec: - pdName type: object gitRepo: - description: 'GitRepo represents a git repository at + description: 'gitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo @@ -2729,37 +2971,38 @@ spec: container.' properties: directory: - description: Target directory name. Must not contain - or start with '..'. If '.' is supplied, the volume - directory will be the git repository. Otherwise, - if specified, the volume will contain the git - repository in the subdirectory with the given - name. + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. type: string repository: - description: Repository URL + description: repository is the URL type: string revision: - description: Commit hash for the specified revision. + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: - description: 'Glusterfs represents a Glusterfs mount + description: 'glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: - description: 'EndpointsName is the endpoint name - that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: - description: 'Path is the Glusterfs volume path. + description: 'path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: - description: 'ReadOnly here will force the Glusterfs + description: 'readOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean @@ -2768,7 +3011,7 @@ spec: - path type: object hostPath: - description: 'HostPath represents a pre-existing file + description: 'hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are @@ -2779,71 +3022,73 @@ spec: directories as read/write.' properties: path: - description: 'Path of the directory on the host. + description: 'path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: - description: 'Type for HostPath Volume Defaults + description: 'type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: - description: 'ISCSI represents an ISCSI Disk resource + description: 'iscsi represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP - authentication + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: - description: whether support iSCSI Session CHAP - authentication + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName - is specified with iscsiInterface simultaneously, - new iSCSI interface : - will be created for the connection. + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: - description: Target iSCSI Qualified Name. + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI - transport. Defaults to 'default' (tcp). + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). type: string lun: - description: iSCSI Target Lun number. + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: - description: iSCSI Target Portal List. The portal - is either an IP or ip_addr:port if the port is - other than default (typically TCP ports 860 and - 3260). + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). items: type: string type: array readOnly: - description: ReadOnly here will force the ReadOnly + description: readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: - description: CHAP Secret for iSCSI target and initiator - authentication + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: description: 'Name of the referent. More info: @@ -2853,9 +3098,10 @@ spec: type: string type: object targetPortal: - description: iSCSI Target Portal. The Portal is - either an IP or ip_addr:port if the port is other - than default (typically TCP ports 860 and 3260). + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). type: string required: - iqn @@ -2863,24 +3109,24 @@ spec: - targetPortal type: object name: - description: 'Volume''s name. Must be a DNS_LABEL and - unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: - description: 'NFS represents an NFS mount on the host + description: 'nfs represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: - description: 'Path that is exported by the NFS server. + description: 'path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: - description: 'ReadOnly here will force the NFS export + description: 'readOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: - description: 'Server is the hostname or IP address + description: 'server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: @@ -2888,132 +3134,133 @@ spec: - server type: object persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents + description: 'persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim + description: 'claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: - description: Will force the ReadOnly setting in - VolumeMounts. Default false. + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController + description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: - description: ID that identifies Photon Controller - persistent disk + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: - description: PortworxVolume represents a portworx volume + description: portworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: - description: FSType represents the filesystem type + description: fSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean volumeID: - description: VolumeID uniquely identifies a Portworx + description: volumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: - description: Items for all in one resources secrets, - configmaps, and downward API + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: - description: Mode bits used to set permissions on - created files by default. Must be an octal value - between 0000 and 0777 or a decimal value between - 0 and 511. YAML accepts both octal and decimal - values, JSON requires decimal values for mode - bits. Directories within the path are not affected - by this setting. This might be in conflict with - other options that affect the file mode, like - fsGroup, and the result can be other mode bits - set. + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. format: int32 type: integer sources: - description: list of volume projections + description: sources is the list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: - description: information about the configMap - data to project + description: configMap information about the + configMap data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - ConfigMap will be projected into the - volume as a file whose name is the key - and content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the ConfigMap, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -3028,13 +3275,13 @@ spec: kind, uid?' type: string optional: - description: Specify whether the ConfigMap - or its keys must be defined + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object downwardAPI: - description: information about the downwardAPI - data to project + description: downwardAPI information about + the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume @@ -3124,53 +3371,53 @@ spec: type: array type: object secret: - description: information about the secret - data to project + description: secret information about the + secret data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - Secret will be projected into the volume - as a file whose name is the key and - content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the Secret, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -3185,16 +3432,16 @@ spec: kind, uid?' type: string optional: - description: Specify whether the Secret - or its key must be defined + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object serviceAccountToken: - description: information about the serviceAccountToken - data to project + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: - description: Audience is the intended + description: audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience @@ -3203,7 +3450,7 @@ spec: the identifier of the apiserver. type: string expirationSeconds: - description: ExpirationSeconds is the + description: expirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume @@ -3217,7 +3464,7 @@ spec: format: int64 type: integer path: - description: Path is the path relative + description: path is the path relative to the mount point of the file to project the token into. type: string @@ -3228,36 +3475,36 @@ spec: type: array type: object quobyte: - description: Quobyte represents a Quobyte mount on the + description: quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: - description: Group to map volume access to Default + description: group to map volume access to Default is no group type: string readOnly: - description: ReadOnly here will force the Quobyte + description: readOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: - description: Registry represents a single or multiple + description: registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: - description: Tenant owning the given Quobyte volume + description: tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: - description: User to map volume access to Defaults + description: user to map volume access to Defaults to serivceaccount user type: string volume: - description: Volume is a string that references + description: volume is a string that references an already created Quobyte volume by name. type: string required: @@ -3265,44 +3512,46 @@ spec: - volume type: object rbd: - description: 'RBD represents a Rados Block Device mount + description: 'rbd represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: - description: 'Keyring is the path to key ring for + description: 'keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: - description: 'A collection of Ceph monitors. More - info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: - description: 'The rados pool name. Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: - description: 'SecretRef is name of the authentication + description: 'secretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: @@ -3314,37 +3563,38 @@ spec: type: string type: object user: - description: 'The rados user name. Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: - description: ScaleIO represents a ScaleIO persistent + description: scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Default is - "xfs". + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". type: string gateway: - description: The host address of the ScaleIO API - Gateway. + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: - description: The name of the ScaleIO Protection - Domain for the configured storage. + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef references to the secret + description: secretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. @@ -3357,26 +3607,26 @@ spec: type: string type: object sslEnabled: - description: Flag to enable/disable SSL communication - with Gateway, default false + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: - description: Indicates whether the storage for a - volume should be ThickProvisioned or ThinProvisioned. + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: - description: The ScaleIO Storage Pool associated - with the protection domain. + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: - description: The name of the storage system as configured - in ScaleIO. + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: - description: The name of a volume already created - in the ScaleIO system that is associated with - this volume source. + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. type: string required: - gateway @@ -3384,27 +3634,27 @@ spec: - system type: object secret: - description: 'Secret represents a secret that should + description: 'secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced Secret will - be projected into the volume as a file whose name - is the key and content is the value. If specified, + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in @@ -3417,26 +3667,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -3444,30 +3696,31 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys - must be defined + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace - to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: - description: StorageOS represents a StorageOS volume + description: storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef specifies the secret to use + description: secretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: @@ -3479,12 +3732,12 @@ spec: type: string type: object volumeName: - description: VolumeName is the human-readable name + description: volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: - description: VolumeNamespace specifies the scope + description: volumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping @@ -3496,26 +3749,27 @@ spec: type: string type: object vsphereVolume: - description: VsphereVolume represents a vSphere volume + description: vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: - description: Storage Policy Based Management (SPBM) - profile ID associated with the StoragePolicyName. + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: - description: Storage Policy Based Management (SPBM) - profile name. + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: - description: Path that identifies vSphere volume - vmdk + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath @@ -3611,37 +3865,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -3650,10 +3905,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -3661,12 +3916,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -3681,37 +3936,38 @@ spec: Secret volumes support ownership management and SELinux relabeling." properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -3720,10 +3976,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -3731,12 +3987,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object type: object @@ -4029,9 +4285,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -4086,7 +4340,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -4185,8 +4439,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -4237,7 +4489,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -4338,9 +4590,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -4395,7 +4645,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -4494,8 +4744,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -4546,7 +4794,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -4804,6 +5052,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -4824,7 +5094,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -4864,6 +5135,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -4884,7 +5177,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -4912,10 +5206,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -5055,7 +5368,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -5069,9 +5383,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -5114,14 +5433,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -5300,6 +5616,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5320,7 +5658,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -5439,7 +5778,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -5470,14 +5810,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -5697,6 +6034,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5717,8 +6076,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -5750,24 +6109,27 @@ spec: description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' type: object spec: - description: 'Spec defines the desired characteristics of + description: 'spec defines the desired characteristics of a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the desired access + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to specify either: - * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the - contents of the specified data source. If the AnyVolumeDataSource - feature gate is enabled, this field will always have - the same contents as the DataSourceRef field.' + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for the resource @@ -5786,27 +6148,34 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from which to populate - the volume with data, if a non-empty volume is desired. - This may be any local object from a non-empty API group - (non core object) or a PersistentVolumeClaim object. - When this field is specified, volume binding will only - succeed if the type of the specified object matches - some installed volume populator or dynamic provisioner. - This field will replace the functionality of the DataSource + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, - both fields (DataSource and DataSourceRef) will be set - to the same value automatically if one of them is empty - and the other is non-empty. There are two important - differences between DataSource and DataSourceRef: * - While DataSource only allows two specific types of objects, - DataSourceRef allows any non-core object, as well - as PersistentVolumeClaim objects. * While DataSource - ignores disallowed values (dropping them), DataSourceRef preserves - all values, and generates an error if a disallowed value - is specified. (Alpha) Using this field requires the - AnyVolumeDataSource feature gate to be enabled.' + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' properties: apiGroup: description: APIGroup is the group for the resource @@ -5820,18 +6189,52 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum resources + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -5853,12 +6256,13 @@ spec: of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes to consider for - binding. + description: selector is a label query over volumes to + consider for binding. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -5903,8 +6307,8 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required by the - claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type of volume is @@ -5912,20 +6316,65 @@ spec: when not included in claim spec. type: string volumeName: - description: VolumeName is the binding reference to the + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object status: - description: 'Status represents the current information/status + description: 'status represents the current information/status of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: accessModes: - description: 'AccessModes contains the actual access modes + description: 'accessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular allocatedResources: additionalProperties: anyOf: @@ -5933,19 +6382,31 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: The storage resource within AllocatedResources - tracks the capacity allocated to a PVC. It may be larger - than the actual capacity when a volume expansion operation - is requested. For storage quota, the larger value from - allocatedResources and PVC.spec.resources is used. If - allocatedResources is not set, PVC.spec.resources alone - is used for quota calculation. If a volume expansion + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower - than the requested capacity. This is an alpha field - and requires enabling RecoverVolumeExpansionFailure - feature. + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." type: object capacity: additionalProperties: @@ -5954,36 +6415,37 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: Represents the actual resources of the underlying - volume. + description: capacity represents the actual resources + of the underlying volume. type: object conditions: - description: Current Condition of persistent volume claim. - If underlying persistent volume is being resized then - the Condition will be set to 'ResizeStarted'. + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. items: - description: PersistentVolumeClaimCondition contails + description: PersistentVolumeClaimCondition contains details about state of pvc properties: lastProbeTime: - description: Last time we probed the condition. + description: lastProbeTime is the time we probed + the condition. format: date-time type: string lastTransitionTime: - description: Last time the condition transitioned - from one status to another. + description: lastTransitionTime is the time the + condition transitioned from one status to another. format: date-time type: string message: - description: Human-readable message indicating details - about last transition. + description: message is the human-readable message + indicating details about last transition. type: string reason: - description: Unique, this should be a short, machine - understandable string that gives the reason for - condition's last transition. If it reports "ResizeStarted" - that means the underlying persistent volume is - being resized. + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. type: string status: type: string @@ -5997,14 +6459,7 @@ spec: type: object type: array phase: - description: Phase represents the current phase of PersistentVolumeClaim. - type: string - resizeStatus: - description: ResizeStatus stores status of resize operation. - ResizeStatus is not set by default but when expansion - is complete resizeStatus is set to empty string by resize - controller or kubelet. This is an alpha field and requires - enabling RecoverVolumeExpansionFailure feature. + description: phase represents the current phase of PersistentVolumeClaim. type: string type: object type: object @@ -6058,123 +6513,128 @@ spec: may be accessed by any container in the pod. properties: awsElasticBlockStore: - description: 'AWSElasticBlockStore represents an AWS + description: 'awsElasticBlockStore represents an AWS Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore TODO: how do we prevent errors in the filesystem from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty).' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' format: int32 type: integer readOnly: - description: 'Specify "true" to force and set the - ReadOnly property in VolumeMounts to "true". If - omitted, the default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: boolean volumeID: - description: 'Unique ID of the persistent disk resource - in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' type: string required: - volumeID type: object azureDisk: - description: AzureDisk represents an Azure Data Disk + description: azureDisk represents an Azure Data Disk mount on the host and bind mount to the pod. properties: cachingMode: - description: 'Host Caching mode: None, Read Only, - Read Write.' + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' type: string diskName: - description: The Name of the data disk in the blob - storage + description: diskName is the Name of the data disk + in the blob storage type: string diskURI: - description: The URI the data disk in the blob storage + description: diskURI is the URI of data disk in + the blob storage type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string kind: - description: 'Expected values Shared: multiple blob - disks per storage account Dedicated: single blob - disk per storage account Managed: azure managed - data disk (only in managed availability set). - defaults to shared' + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean required: - diskName - diskURI type: object azureFile: - description: AzureFile represents an Azure File Service + description: azureFile represents an Azure File Service mount on the host and bind mount to the pod. properties: readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretName: - description: the name of secret that contains Azure - Storage Account Name and Key + description: secretName is the name of secret that + contains Azure Storage Account Name and Key type: string shareName: - description: Share Name + description: shareName is the azure share Name type: string required: - secretName - shareName type: object cephfs: - description: CephFS represents a Ceph FS mount on the + description: cephFS represents a Ceph FS mount on the host that shares a pod's lifetime properties: monitors: - description: 'Required: Monitors is a collection - of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' items: type: string type: array path: - description: 'Optional: Used as the mounted root, - rather than the full Ceph tree, default is /' + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' type: string readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: boolean secretFile: - description: 'Optional: SecretFile is the path to - key ring for User, default is /etc/ceph/user.secret + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string secretRef: - description: 'Optional: SecretRef is reference to - the authentication secret for User, default is - empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' properties: name: description: 'Name of the referent. More info: @@ -6184,31 +6644,32 @@ spec: type: string type: object user: - description: 'Optional: User is the rados user name, - default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' type: string required: - monitors type: object cinder: - description: 'Cinder represents a cinder volume attached + description: 'cinder represents a cinder volume attached and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Examples: "ext4", "xfs", "ntfs". Implicitly - inferred to be "ext4" if unspecified. More info: - https://examples.k8s.io/mysql-cinder-pd/README.md' + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string readOnly: - description: 'Optional: Defaults to false (read/write). + description: 'readOnly defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: boolean secretRef: - description: 'Optional: points to a secret object - containing parameters used to connect to OpenStack.' + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' properties: name: description: 'Name of the referent. More info: @@ -6218,32 +6679,32 @@ spec: type: string type: object volumeID: - description: 'volume id used to identify the volume + description: 'volumeID used to identify the volume in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' type: string required: - volumeID type: object configMap: - description: ConfigMap represents a configMap that should + description: configMap represents a configMap that should populate this volume properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced ConfigMap + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified @@ -6258,26 +6719,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -6290,28 +6753,28 @@ spec: uid?' type: string optional: - description: Specify whether the ConfigMap or its - keys must be defined + description: optional specify whether the ConfigMap + or its keys must be defined type: boolean type: object csi: - description: CSI (Container Storage Interface) represents + description: csi (Container Storage Interface) represents ephemeral storage that is handled by certain external CSI drivers (Beta feature). properties: driver: - description: Driver is the name of the CSI driver + description: driver is the name of the CSI driver that handles this volume. Consult with your admin for the correct name as registered in the cluster. type: string fsType: - description: Filesystem type to mount. Ex. "ext4", - "xfs", "ntfs". If not provided, the empty value - is passed to the associated CSI driver which will - determine the default filesystem to apply. + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. type: string nodePublishSecretRef: - description: NodePublishSecretRef is a reference + description: nodePublishSecretRef is a reference to the secret object containing sensitive information to pass to the CSI driver to complete the CSI NodePublishVolume and NodeUnpublishVolume calls. @@ -6328,13 +6791,13 @@ spec: type: string type: object readOnly: - description: Specifies a read-only configuration + description: readOnly specifies a read-only configuration for the volume. Defaults to false (read/write). type: boolean volumeAttributes: additionalProperties: type: string - description: VolumeAttributes stores driver-specific + description: volumeAttributes stores driver-specific properties that are passed to the CSI driver. Consult your driver's documentation for supported values. @@ -6343,7 +6806,7 @@ spec: - driver type: object downwardAPI: - description: DownwardAPI represents downward API about + description: downwardAPI represents downward API about the pod that should populate this volume properties: defaultMode: @@ -6436,32 +6899,33 @@ spec: type: array type: object emptyDir: - description: 'EmptyDir represents a temporary directory + description: 'emptyDir represents a temporary directory that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' properties: medium: - description: 'What type of storage medium should - back this directory. The default is "" which means - to use the node''s default medium. Must be an - empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: anyOf: - type: integer - type: string - description: 'Total amount of local storage required - for this EmptyDir volume. The size limit is also - applicable for memory medium. The maximum usage - on memory medium EmptyDir would be the minimum - value between the SizeLimit specified here and - the sum of memory limits of all containers in - a pod. The default is nil which means that the - limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true type: object ephemeral: - description: "Ephemeral represents a volume that is + description: "ephemeral represents a volume that is handled by a cluster storage driver. The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted @@ -6521,25 +6985,28 @@ spec: are also valid here. properties: accessModes: - description: 'AccessModes contains the desired + description: 'accessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' items: type: string type: array dataSource: - description: 'This field can be used to - specify either: * An existing VolumeSnapshot + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. - If the AnyVolumeDataSource feature gate - is enabled, this field will always have - the same contents as the DataSourceRef - field.' + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' properties: apiGroup: description: APIGroup is the group for @@ -6562,33 +7029,41 @@ spec: - name type: object dataSourceRef: - description: 'Specifies the object from - which to populate the volume with data, - if a non-empty volume is desired. This - may be any local object from a non-empty + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the - functionality of the DataSource field + functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards - compatibility, both fields (DataSource - and DataSourceRef) will be set to the + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same value automatically if one of them - is empty and the other is non-empty. There - are two important differences between - DataSource and DataSourceRef: * While - DataSource only allows two specific types - of objects, DataSourceRef allows any - non-core object, as well as PersistentVolumeClaim - objects. * While DataSource ignores disallowed - values (dropping them), DataSourceRef preserves + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves all values, and generates an error if - a disallowed value is specified. (Alpha) - Using this field requires the AnyVolumeDataSource + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' properties: apiGroup: @@ -6607,12 +7082,25 @@ spec: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string required: - kind - name type: object resources: - description: 'Resources represents the minimum + description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are @@ -6621,6 +7109,32 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6645,12 +7159,13 @@ spec: a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object selector: - description: A label query over volumes - to consider for binding. + description: selector is a label query over + volumes to consider for binding. properties: matchExpressions: description: matchExpressions is a list @@ -6704,8 +7219,9 @@ spec: type: object type: object storageClassName: - description: 'Name of the StorageClass required - by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string volumeMode: description: volumeMode defines what type @@ -6714,7 +7230,7 @@ spec: in claim spec. type: string volumeName: - description: VolumeName is the binding reference + description: volumeName is the binding reference to the PersistentVolume backing this claim. type: string type: object @@ -6723,74 +7239,75 @@ spec: type: object type: object fc: - description: FC represents a Fibre Channel resource + description: fc represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod. properties: fsType: - description: 'Filesystem type to mount. Must be - a filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. TODO: how do we prevent errors in the filesystem from compromising the machine' type: string lun: - description: 'Optional: FC target lun number' + description: 'lun is Optional: FC target lun number' format: int32 type: integer readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean targetWWNs: - description: 'Optional: FC target worldwide names - (WWNs)' + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' items: type: string type: array wwids: - description: 'Optional: FC volume world wide identifiers - (wwids) Either wwids or combination of targetWWNs - and lun must be set, but not both simultaneously.' + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' items: type: string type: array type: object flexVolume: - description: FlexVolume represents a generic volume + description: flexVolume represents a generic volume resource that is provisioned/attached using an exec based plugin. properties: driver: - description: Driver is the name of the driver to + description: driver is the name of the driver to use for this volume. type: string fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". The default - filesystem depends on FlexVolume script. + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. type: string options: additionalProperties: type: string - description: 'Optional: Extra command options if - any.' + description: 'options is Optional: this field holds + extra command options if any.' type: object readOnly: - description: 'Optional: Defaults to false (read/write). - ReadOnly here will force the ReadOnly setting - in VolumeMounts.' + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' type: boolean secretRef: - description: 'Optional: SecretRef is reference to - the secret object containing sensitive information - to pass to the plugin scripts. This may be empty - if no secret object is specified. If the secret - object contains more than one secret, all secrets - are passed to the plugin scripts.' + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' properties: name: description: 'Name of the referent. More info: @@ -6803,28 +7320,28 @@ spec: - driver type: object flocker: - description: Flocker represents a Flocker volume attached + description: flocker represents a Flocker volume attached to a kubelet's host machine. This depends on the Flocker control service being running properties: datasetName: - description: Name of the dataset stored as metadata - -> name on the dataset for Flocker should be considered - as deprecated + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated type: string datasetUUID: - description: UUID of the dataset. This is unique - identifier of a Flocker dataset + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset type: string type: object gcePersistentDisk: - description: 'GCEPersistentDisk represents a GCE Disk + description: 'gcePersistentDisk represents a GCE Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk @@ -6832,21 +7349,22 @@ spec: from compromising the machine' type: string partition: - description: 'The partition in the volume that you - want to mount. If omitted, the default is to mount - by volume name. Examples: For volume /dev/sda1, - you specify the partition as "1". Similarly, the - volume partition for /dev/sda is "0" (or you can - leave the property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' format: int32 type: integer pdName: - description: 'Unique name of the PD resource in - GCE. Used to identify the disk in GCE. More info: - https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' type: boolean @@ -6854,7 +7372,7 @@ spec: - pdName type: object gitRepo: - description: 'GitRepo represents a git repository at + description: 'gitRepo represents a git repository at a particular revision. DEPRECATED: GitRepo is deprecated. To provision a container with a git repo, mount an EmptyDir into an InitContainer that clones the repo @@ -6862,37 +7380,38 @@ spec: container.' properties: directory: - description: Target directory name. Must not contain - or start with '..'. If '.' is supplied, the volume - directory will be the git repository. Otherwise, - if specified, the volume will contain the git - repository in the subdirectory with the given - name. + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. type: string repository: - description: Repository URL + description: repository is the URL type: string revision: - description: Commit hash for the specified revision. + description: revision is the commit hash for the + specified revision. type: string required: - repository type: object glusterfs: - description: 'Glusterfs represents a Glusterfs mount + description: 'glusterfs represents a Glusterfs mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' properties: endpoints: - description: 'EndpointsName is the endpoint name - that details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string path: - description: 'Path is the Glusterfs volume path. + description: 'path is the Glusterfs volume path. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: string readOnly: - description: 'ReadOnly here will force the Glusterfs + description: 'readOnly here will force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' type: boolean @@ -6901,7 +7420,7 @@ spec: - path type: object hostPath: - description: 'HostPath represents a pre-existing file + description: 'hostPath represents a pre-existing file or directory on the host machine that is directly exposed to the container. This is generally used for system agents or other privileged things that are @@ -6912,71 +7431,73 @@ spec: directories as read/write.' properties: path: - description: 'Path of the directory on the host. + description: 'path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string type: - description: 'Type for HostPath Volume Defaults + description: 'type for HostPath Volume Defaults to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' type: string required: - path type: object iscsi: - description: 'ISCSI represents an ISCSI Disk resource + description: 'iscsi represents an ISCSI Disk resource that is attached to a kubelet''s host machine and then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' properties: chapAuthDiscovery: - description: whether support iSCSI Discovery CHAP - authentication + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication type: boolean chapAuthSession: - description: whether support iSCSI Session CHAP - authentication + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication type: boolean fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi TODO: how do we prevent errors in the filesystem from compromising the machine' type: string initiatorName: - description: Custom iSCSI Initiator Name. If initiatorName - is specified with iscsiInterface simultaneously, - new iSCSI interface : - will be created for the connection. + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. type: string iqn: - description: Target iSCSI Qualified Name. + description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: - description: iSCSI Interface Name that uses an iSCSI - transport. Defaults to 'default' (tcp). + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). type: string lun: - description: iSCSI Target Lun number. + description: lun represents iSCSI Target Lun number. format: int32 type: integer portals: - description: iSCSI Target Portal List. The portal - is either an IP or ip_addr:port if the port is - other than default (typically TCP ports 860 and - 3260). + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). items: type: string type: array readOnly: - description: ReadOnly here will force the ReadOnly + description: readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. type: boolean secretRef: - description: CHAP Secret for iSCSI target and initiator - authentication + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication properties: name: description: 'Name of the referent. More info: @@ -6986,9 +7507,10 @@ spec: type: string type: object targetPortal: - description: iSCSI Target Portal. The Portal is - either an IP or ip_addr:port if the port is other - than default (typically TCP ports 860 and 3260). + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). type: string required: - iqn @@ -6996,24 +7518,24 @@ spec: - targetPortal type: object name: - description: 'Volume''s name. Must be a DNS_LABEL and - unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' type: string nfs: - description: 'NFS represents an NFS mount on the host + description: 'nfs represents an NFS mount on the host that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' properties: path: - description: 'Path that is exported by the NFS server. + description: 'path that is exported by the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string readOnly: - description: 'ReadOnly here will force the NFS export + description: 'readOnly here will force the NFS export to be mounted with read-only permissions. Defaults to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: boolean server: - description: 'Server is the hostname or IP address + description: 'server is the hostname or IP address of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' type: string required: @@ -7021,132 +7543,133 @@ spec: - server type: object persistentVolumeClaim: - description: 'PersistentVolumeClaimVolumeSource represents + description: 'persistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' properties: claimName: - description: 'ClaimName is the name of a PersistentVolumeClaim + description: 'claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' type: string readOnly: - description: Will force the ReadOnly setting in - VolumeMounts. Default false. + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. type: boolean required: - claimName type: object photonPersistentDisk: - description: PhotonPersistentDisk represents a PhotonController + description: photonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string pdID: - description: ID that identifies Photon Controller - persistent disk + description: pdID is the ID that identifies Photon + Controller persistent disk type: string required: - pdID type: object portworxVolume: - description: PortworxVolume represents a portworx volume + description: portworxVolume represents a portworx volume attached and mounted on kubelets host machine properties: fsType: - description: FSType represents the filesystem type + description: fSType represents the filesystem type to mount Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean volumeID: - description: VolumeID uniquely identifies a Portworx + description: volumeID uniquely identifies a Portworx volume type: string required: - volumeID type: object projected: - description: Items for all in one resources secrets, - configmaps, and downward API + description: projected items for all in one resources + secrets, configmaps, and downward API properties: defaultMode: - description: Mode bits used to set permissions on - created files by default. Must be an octal value - between 0000 and 0777 or a decimal value between - 0 and 511. YAML accepts both octal and decimal - values, JSON requires decimal values for mode - bits. Directories within the path are not affected - by this setting. This might be in conflict with - other options that affect the file mode, like - fsGroup, and the result can be other mode bits - set. + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. format: int32 type: integer sources: - description: list of volume projections + description: sources is the list of volume projections items: description: Projection that may be projected along with other supported volume types properties: configMap: - description: information about the configMap - data to project + description: configMap information about the + configMap data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - ConfigMap will be projected into the - volume as a file whose name is the key - and content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the ConfigMap, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -7161,13 +7684,13 @@ spec: kind, uid?' type: string optional: - description: Specify whether the ConfigMap - or its keys must be defined + description: optional specify whether + the ConfigMap or its keys must be defined type: boolean type: object downwardAPI: - description: information about the downwardAPI - data to project + description: downwardAPI information about + the downwardAPI data to project properties: items: description: Items is a list of DownwardAPIVolume @@ -7257,53 +7780,53 @@ spec: type: array type: object secret: - description: information about the secret - data to project + description: secret information about the + secret data to project properties: items: - description: If unspecified, each key-value - pair in the Data field of the referenced - Secret will be projected into the volume - as a file whose name is the key and - content is the value. If specified, - the listed keys will be projected into - the specified paths, and unlisted keys - will not be present. If a key is specified - which is not present in the Secret, - the volume setup will error unless it - is marked optional. Paths must be relative - and may not contain the '..' path or - start with '..'. + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits - used to set permissions on this - file. Must be an octal value between - 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts - both octal and decimal values, - JSON requires decimal values for - mode bits. If not specified, the - volume defaultMode will be used. - This might be in conflict with - other options that affect the - file mode, like fsGroup, and the - result can be other mode bits - set.' + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' format: int32 type: integer path: - description: The relative path of - the file to map the key to. May - not be an absolute path. May not - contain the path element '..'. - May not start with the string + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string '..'. type: string required: @@ -7318,16 +7841,16 @@ spec: kind, uid?' type: string optional: - description: Specify whether the Secret - or its key must be defined + description: optional field specify whether + the Secret or its key must be defined type: boolean type: object serviceAccountToken: - description: information about the serviceAccountToken - data to project + description: serviceAccountToken is information + about the serviceAccountToken data to project properties: audience: - description: Audience is the intended + description: audience is the intended audience of the token. A recipient of a token must identify itself with an identifier specified in the audience @@ -7336,7 +7859,7 @@ spec: the identifier of the apiserver. type: string expirationSeconds: - description: ExpirationSeconds is the + description: expirationSeconds is the requested duration of validity of the service account token. As the token approaches expiration, the kubelet volume @@ -7350,7 +7873,7 @@ spec: format: int64 type: integer path: - description: Path is the path relative + description: path is the path relative to the mount point of the file to project the token into. type: string @@ -7361,36 +7884,36 @@ spec: type: array type: object quobyte: - description: Quobyte represents a Quobyte mount on the + description: quobyte represents a Quobyte mount on the host that shares a pod's lifetime properties: group: - description: Group to map volume access to Default + description: group to map volume access to Default is no group type: string readOnly: - description: ReadOnly here will force the Quobyte + description: readOnly here will force the Quobyte volume to be mounted with read-only permissions. Defaults to false. type: boolean registry: - description: Registry represents a single or multiple + description: registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes type: string tenant: - description: Tenant owning the given Quobyte volume + description: tenant owning the given Quobyte volume in the Backend Used with dynamically provisioned Quobyte volumes, value is set by the plugin type: string user: - description: User to map volume access to Defaults + description: user to map volume access to Defaults to serivceaccount user type: string volume: - description: Volume is a string that references + description: volume is a string that references an already created Quobyte volume by name. type: string required: @@ -7398,44 +7921,46 @@ spec: - volume type: object rbd: - description: 'RBD represents a Rados Block Device mount + description: 'rbd represents a Rados Block Device mount on the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md' properties: fsType: - description: 'Filesystem type of the volume that - you want to mount. Tip: Ensure that the filesystem - type is supported by the host operating system. - Examples: "ext4", "xfs", "ntfs". Implicitly inferred - to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd TODO: how do we prevent errors in the filesystem from compromising the machine' type: string image: - description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string keyring: - description: 'Keyring is the path to key ring for + description: 'keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string monitors: - description: 'A collection of Ceph monitors. More - info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' items: type: string type: array pool: - description: 'The rados pool name. Default is rbd. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string readOnly: - description: 'ReadOnly here will force the ReadOnly + description: 'readOnly here will force the ReadOnly setting in VolumeMounts. Defaults to false. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: boolean secretRef: - description: 'SecretRef is name of the authentication + description: 'secretRef is name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' properties: @@ -7447,37 +7972,38 @@ spec: type: string type: object user: - description: 'The rados user name. Default is admin. - More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' type: string required: - image - monitors type: object scaleIO: - description: ScaleIO represents a ScaleIO persistent + description: scaleIO represents a ScaleIO persistent volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Default is - "xfs". + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". type: string gateway: - description: The host address of the ScaleIO API - Gateway. + description: gateway is the host address of the + ScaleIO API Gateway. type: string protectionDomain: - description: The name of the ScaleIO Protection - Domain for the configured storage. + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef references to the secret + description: secretRef references to the secret for ScaleIO user and other sensitive information. If this is not provided, Login operation will fail. @@ -7490,26 +8016,26 @@ spec: type: string type: object sslEnabled: - description: Flag to enable/disable SSL communication - with Gateway, default false + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false type: boolean storageMode: - description: Indicates whether the storage for a - volume should be ThickProvisioned or ThinProvisioned. + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. type: string storagePool: - description: The ScaleIO Storage Pool associated - with the protection domain. + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. type: string system: - description: The name of the storage system as configured - in ScaleIO. + description: system is the name of the storage system + as configured in ScaleIO. type: string volumeName: - description: The name of a volume already created - in the ScaleIO system that is associated with - this volume source. + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. type: string required: - gateway @@ -7517,27 +8043,27 @@ spec: - system type: object secret: - description: 'Secret represents a secret that should + description: 'secret represents a secret that should populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal - value between 0000 and 0777 or a decimal value - between 0 and 511. YAML accepts both octal and - decimal values, JSON requires decimal values for - mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This - might be in conflict with other options that affect - the file mode, like fsGroup, and the result can - be other mode bits set.' + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair - in the Data field of the referenced Secret will - be projected into the volume as a file whose name - is the key and content is the value. If specified, + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in @@ -7550,26 +8076,28 @@ spec: a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to - set permissions on this file. Must be an - octal value between 0000 and 0777 or a decimal - value between 0 and 511. YAML accepts both - octal and decimal values, JSON requires - decimal values for mode bits. If not specified, - the volume defaultMode will be used. This - might be in conflict with other options - that affect the file mode, like fsGroup, - and the result can be other mode bits set.' + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer path: - description: The relative path of the file - to map the key to. May not be an absolute - path. May not contain the path element '..'. - May not start with the string '..'. + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. type: string required: - key @@ -7577,30 +8105,31 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys - must be defined + description: optional field specify whether the + Secret or its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace - to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object storageos: - description: StorageOS represents a StorageOS volume + description: storageOS represents a StorageOS volume attached and mounted on Kubernetes nodes. properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string readOnly: - description: Defaults to false (read/write). ReadOnly - here will force the ReadOnly setting in VolumeMounts. + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. type: boolean secretRef: - description: SecretRef specifies the secret to use + description: secretRef specifies the secret to use for obtaining the StorageOS API credentials. If not specified, default values will be attempted. properties: @@ -7612,12 +8141,12 @@ spec: type: string type: object volumeName: - description: VolumeName is the human-readable name + description: volumeName is the human-readable name of the StorageOS volume. Volume names are only unique within a namespace. type: string volumeNamespace: - description: VolumeNamespace specifies the scope + description: volumeNamespace specifies the scope of the volume within StorageOS. If no namespace is specified then the Pod's namespace will be used. This allows the Kubernetes name scoping @@ -7629,26 +8158,27 @@ spec: type: string type: object vsphereVolume: - description: VsphereVolume represents a vSphere volume + description: vsphereVolume represents a vSphere volume attached and mounted on kubelets host machine properties: fsType: - description: Filesystem type to mount. Must be a - filesystem type supported by the host operating - system. Ex. "ext4", "xfs", "ntfs". Implicitly + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. type: string storagePolicyID: - description: Storage Policy Based Management (SPBM) - profile ID associated with the StoragePolicyName. + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. type: string storagePolicyName: - description: Storage Policy Based Management (SPBM) - profile name. + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. type: string volumePath: - description: Path that identifies vSphere volume - vmdk + description: volumePath is the path that identifies + vSphere volume vmdk type: string required: - volumePath diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 908075903..82de56b4b 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -48,37 +48,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -87,10 +88,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -98,12 +99,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -398,9 +399,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -455,7 +454,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -554,8 +553,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -606,7 +603,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -707,9 +704,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -764,7 +759,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -863,8 +858,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -915,7 +908,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -972,6 +965,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -992,7 +1007,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -1020,10 +1036,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -1240,7 +1275,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -1254,9 +1290,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -1299,14 +1340,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -1448,6 +1486,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1468,8 +1528,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -1561,37 +1621,38 @@ spec: description: Reference to secret which contains the certificates properties: defaultMode: - description: 'Optional: mode bits used to set permissions - on created files by default. Must be an octal value between - 0000 and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires decimal - values for mode bits. Defaults to 0644. Directories within - the path are not affected by this setting. This might be - in conflict with other options that affect the file mode, - like fsGroup, and the result can be other mode bits set.' + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' format: int32 type: integer items: - description: If unspecified, each key-value pair in the Data - field of the referenced Secret will be projected into the - volume as a file whose name is the key and content is the - value. If specified, the listed keys will be projected into - the specified paths, and unlisted keys will not be present. - If a key is specified which is not present in the Secret, - the volume setup will error unless it is marked optional. - Paths must be relative and may not contain the '..' path - or start with '..'. + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. items: description: Maps a string key to a path within a volume. properties: key: - description: The key to project. + description: key is the key to project. type: string mode: - description: 'Optional: mode bits used to set permissions - on this file. Must be an octal value between 0000 - and 0777 or a decimal value between 0 and 511. YAML - accepts both octal and decimal values, JSON requires + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires decimal values for mode bits. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, @@ -1600,10 +1661,10 @@ spec: format: int32 type: integer path: - description: The relative path of the file to map the - key to. May not be an absolute path. May not contain - the path element '..'. May not start with the string - '..'. + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. type: string required: - key @@ -1611,12 +1672,12 @@ spec: type: object type: array optional: - description: Specify whether the Secret or its keys must be - defined + description: optional field specify whether the Secret or + its keys must be defined type: boolean secretName: - description: 'Name of the secret in the pod''s namespace to - use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' type: string type: object required: @@ -1911,9 +1972,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -1968,7 +2027,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -2067,8 +2126,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -2119,7 +2176,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -2220,9 +2277,7 @@ spec: field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector - ({}) matches all namespaces. This field is beta-level - and is only honored when PodAffinityNamespaceSelector - feature is enabled. + ({}) matches all namespaces. properties: matchExpressions: description: matchExpressions is a list of label @@ -2277,7 +2332,7 @@ spec: term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list - and null namespaceSelector means "this pod's namespace" + and null namespaceSelector means "this pod's namespace". items: type: string type: array @@ -2376,8 +2431,6 @@ spec: the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. - This field is beta-level and is only honored when - PodAffinityNamespaceSelector feature is enabled. properties: matchExpressions: description: matchExpressions is a list of label @@ -2428,7 +2481,7 @@ spec: to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means - "this pod's namespace" + "this pod's namespace". items: type: string type: array @@ -2688,6 +2741,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2708,7 +2783,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -2748,6 +2824,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2768,7 +2866,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object service: @@ -2796,10 +2895,29 @@ spec: description: RollingUpdate is used to communicate parameters when Type is RollingUpdateStatefulSetStrategyType. properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true partition: description: Partition indicates the ordinal at which - the StatefulSet should be partitioned. Default value - is 0. + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. format: int32 type: integer type: object @@ -2952,7 +3070,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -2966,9 +3085,14 @@ spec: type: object supplementalGroups: description: A list of groups applied to the first process run - in each container, in addition to the container's primary GID. If - unspecified, no groups will be added to any container. Note - that this field cannot be set when spec.os.name is windows. + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. items: format: int64 type: integer @@ -3011,14 +3135,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -3191,6 +3312,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -3211,7 +3354,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: @@ -3357,7 +3501,8 @@ spec: in a file on the node should be used. The profile must be preconfigured on the node to work. Must be a descending path, relative to the kubelet's configured seccomp profile - location. Must only be set if type is "Localhost". + location. Must be set if type is "Localhost". Must NOT be + set for any other type. type: string type: description: "type indicates which kind of seccomp profile @@ -3388,14 +3533,11 @@ spec: type: string hostProcess: description: HostProcess determines if a container should - be run as a 'Host Process' container. This field is alpha-level - and will only be honored by components that enable the WindowsHostProcessContainers - feature flag. Setting this field without the feature flag - will result in errors when validating the Pod. All of a - Pod's containers must have the same effective HostProcess - value (it is not allowed to have a mix of HostProcess containers - and non-HostProcess containers). In addition, if HostProcess - is true then HostNetwork must also be set to true. + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. type: boolean runAsUserName: description: The UserName in Windows to run the entrypoint @@ -3615,6 +3757,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -3635,8 +3799,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object required: diff --git a/config/crd/patches/webhook_in_redis.yaml b/config/crd/patches/webhook_in_redis.yaml index e994c9fdc..70f9636d5 100644 --- a/config/crd/patches/webhook_in_redis.yaml +++ b/config/crd/patches/webhook_in_redis.yaml @@ -9,7 +9,7 @@ spec: webhook: clientConfig: service: - namespace: system + namespace: ot-operators name: webhook-service path: /convert conversionReviewVersions: ["v1beta2", "v1beta1"] diff --git a/config/crd/patches/webhook_in_redisclusters.yaml b/config/crd/patches/webhook_in_redisclusters.yaml index eac1b13c5..ad3894e42 100644 --- a/config/crd/patches/webhook_in_redisclusters.yaml +++ b/config/crd/patches/webhook_in_redisclusters.yaml @@ -9,7 +9,7 @@ spec: webhook: clientConfig: service: - namespace: system + namespace: ot-operators name: webhook-service path: /convert conversionReviewVersions: ["v1beta2", "v1beta1"] \ No newline at end of file diff --git a/config/crd/patches/webhook_in_redisreplications.yaml b/config/crd/patches/webhook_in_redisreplications.yaml index faa2152bb..d0d5882f0 100644 --- a/config/crd/patches/webhook_in_redisreplications.yaml +++ b/config/crd/patches/webhook_in_redisreplications.yaml @@ -9,7 +9,7 @@ spec: webhook: clientConfig: service: - namespace: system + namespace: ot-operators name: webhook-service path: /convert conversionReviewVersions: ["v1beta2", "v1beta1"] diff --git a/config/crd/patches/webhook_in_redissentinels.yaml b/config/crd/patches/webhook_in_redissentinels.yaml index 0a357ab72..01214cbdd 100644 --- a/config/crd/patches/webhook_in_redissentinels.yaml +++ b/config/crd/patches/webhook_in_redissentinels.yaml @@ -9,7 +9,7 @@ spec: webhook: clientConfig: service: - namespace: system + namespace: ot-operators name: webhook-service path: /convert conversionReviewVersions: ["v1beta2", "v1beta1"] diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index e0e93d2ef..44dba7b21 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -24,11 +24,11 @@ bases: # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. #- ../prometheus -patchesStrategicMerge: +#patchesStrategicMerge: # Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics +# If you want your redis-operator to expose the /metrics # endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml +#- manager_auth_proxy_patch.yaml # Mount the controller config file for loading manager configurations # through a ComponentConfig type @@ -36,39 +36,39 @@ patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -- manager_webhook_patch.yaml +#- manager_webhook_patch.yaml # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. # 'CERTMANAGER' needs to be enabled to use ca injection -- webhookcainjection_patch.yaml +#- webhookcainjection_patch.yaml # the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR - objref: - kind: Certificate - group: cert-manager.io - version: v1 - name: serving-cert # this name should match the one in certificate.yaml - fieldref: - fieldpath: metadata.namespace -- name: CERTIFICATE_NAME - objref: - kind: Certificate - group: cert-manager.io - version: v1 - name: serving-cert # this name should match the one in certificate.yaml -- name: SERVICE_NAMESPACE # namespace of the service - objref: - kind: Service - version: v1 - name: webhook-service - fieldref: - fieldpath: metadata.namespace -- name: SERVICE_NAME - objref: - kind: Service - version: v1 - name: webhook-service +#vars: +## [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldref: +# fieldpath: metadata.namespace +#- name: CERTIFICATE_NAME +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +#- name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +#- name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service \ No newline at end of file diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index 49b1f1ab3..e6f4e8f80 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -3,8 +3,8 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: controller-manager - namespace: system + name: redis-operator + namespace: ot-operators spec: template: spec: diff --git a/config/default/manager_config_patch.yaml b/config/default/manager_config_patch.yaml index 6c400155c..6ab58e02f 100644 --- a/config/default/manager_config_patch.yaml +++ b/config/default/manager_config_patch.yaml @@ -1,8 +1,8 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: controller-manager - namespace: system + name: redis-operator + namespace: ot-operators spec: template: spec: diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml index 738de350b..57ed10f51 100644 --- a/config/default/manager_webhook_patch.yaml +++ b/config/default/manager_webhook_patch.yaml @@ -1,8 +1,8 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: controller-manager - namespace: system + name: redis-operator + namespace: ot-operators spec: template: spec: diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index 9b8047b76..2db47a919 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -4,13 +4,13 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: - control-plane: controller-manager - name: controller-manager-metrics-monitor - namespace: system + control-plane: redis-operator + name: redis-operator-metrics-monitor + namespace: ot-operators spec: endpoints: - path: /metrics port: https selector: matchLabels: - control-plane: controller-manager + control-plane: redis-operator diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 75c1dc55a..2568322d3 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -10,7 +10,9 @@ rules: - '*' verbs: - get -- resources: +- apiGroups: + - "" + resources: - configmaps - events - namespaces diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index bf7a75309..f7b5eb7b3 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -5,7 +5,7 @@ metadata: roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: redis-operator + name: redis-operator-manager-role subjects: - kind: ServiceAccount name: redis-operator diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml index 6b9dff4e5..098340bf2 100644 --- a/config/webhook/service.yaml +++ b/config/webhook/service.yaml @@ -10,11 +10,11 @@ metadata: app.kubernetes.io/part-of: redis-operator app.kubernetes.io/managed-by: kustomize name: webhook-service - namespace: system + namespace: ot-operators spec: ports: - port: 443 protocol: TCP targetPort: 9443 selector: - control-plane: controller-manager + control-plane: redis-operator From 9ffe55a3631214af4be609822c59b9e93c9884fb Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 7 Oct 2023 16:56:56 +0800 Subject: [PATCH 027/203] [Fix] - sts will never be created (#663) * Fix err would be set nil Signed-off-by: drivebyer * nolint for shadow Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/poddisruption.go | 2 +- k8sutils/services.go | 2 +- k8sutils/statefulset.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 3029afea9..f1cc97075 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -120,7 +120,7 @@ func CreateOrUpdatePodDisruptionBudget(pdbDef *policyv1.PodDisruptionBudget) err logger := pdbLogger(pdbDef.Namespace, pdbDef.Name) storedPDB, err := GetPodDisruptionBudget(pdbDef.Namespace, pdbDef.Name) if err != nil { - if err = patch.DefaultAnnotator.SetLastAppliedAnnotation(pdbDef); err != nil { + if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(pdbDef); err != nil { //nolint logger.Error(err, "Unable to patch redis PodDisruptionBudget with comparison object") return err } diff --git a/k8sutils/services.go b/k8sutils/services.go index 9db0f340b..3d6548b5b 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -137,7 +137,7 @@ func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, owne storedService, err := getService(namespace, serviceMeta.Name) if err != nil { if errors.IsNotFound(err) { - if err = patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil { + if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil { //nolint logger.Error(err, "Unable to patch redis service with compare annotations") } return createService(namespace, serviceDef) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index cf219bdac..9c2d4cf8c 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -93,7 +93,7 @@ func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params storedStateful, err := GetStatefulSet(namespace, stsMeta.Name) statefulSetDef := generateStatefulSetsDef(stsMeta, params, ownerDef, initcontainerParams, containerParams, getSidecars(sidecars)) if err != nil { - if err = patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil { + if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil { //nolint logger.Error(err, "Unable to patch redis statefulset with comparison object") return err } @@ -661,7 +661,7 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS } logger.V(1).Info("recreating StatefulSet because the update operation wasn't possible", "reason", strings.Join(failMsg, ", ")) propagationPolicy := metav1.DeletePropagationForeground - if err = generateK8sClient().AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { + if err := generateK8sClient().AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { //nolint return errors.Wrap(err, "failed to delete StatefulSet to avoid forbidden action") } } From ea26e9d9ddb6932f46dd3936da356a973b47df3e Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 7 Oct 2023 14:42:02 +0530 Subject: [PATCH 028/203] [Test] : e2e Github Action Workflow (#661) * github action Signed-off-by: Shubham Gupta * fix naming Signed-off-by: Shubham Gupta * install kubectl Signed-off-by: Shubham Gupta * install kind utility Signed-off-by: Shubham Gupta * name kind Signed-off-by: Shubham Gupta * deploy operator * fix test dir Signed-off-by: Shubham Gupta * fix current dir Signed-off-by: Shubham Gupta * run without deploye Signed-off-by: Shubham Gupta * make deploye Signed-off-by: Shubham Gupta * make with version Signed-off-by: Shubham Gupta * upgrade kustomize Signed-off-by: Shubham Gupta * fix image Signed-off-by: Shubham Gupta * update pull policy Signed-off-by: Shubham Gupta * disable webhook for deployment * disable webhook Signed-off-by: Shubham Gupta * print logs Signed-off-by: Shubham Gupta * logs Signed-off-by: Shubham Gupta * check kind images Signed-off-by: Shubham Gupta * wait Signed-off-by: Shubham Gupta * log 2 Signed-off-by: Shubham Gupta * remove Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta Co-authored-by: drivebyer --- .github/workflows/e2e.yaml | 58 +++++++++++++++++++++++++++++++ Makefile | 2 +- config/manager/kustomization.yaml | 4 +-- config/manager/manager.yaml | 8 +++-- 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/e2e.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml new file mode 100644 index 000000000..e85476079 --- /dev/null +++ b/.github/workflows/e2e.yaml @@ -0,0 +1,58 @@ +name: E2E tests + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + test: + name: ${{ matrix.testpath }} + runs-on: ubuntu-latest + strategy: + matrix: + testpath: + - ./tests/e2e/v1beta2/setup + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build Dockerfile + run: docker build . --file Dockerfile --tag redis-operator:e2e + + - name: Install kuttl + run: | + curl -L https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64 -o /usr/local/bin/kuttl + chmod +x /usr/local/bin/kuttl + + - name: Install kubectl + run: | + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/ + + - name: Create k8s Kind Cluster + uses: helm/kind-action@v1.5.0 + with: + config: tests/_config/kind-config.yaml + cluster_name: kind + + - name: Load Docker image into Kind + run: | + kubectl cluster-info --context kind-kind + kind load docker-image redis-operator:e2e --name kind + + - name: Install Redis Operator + run: | + make deploy + + - name: Wait for Redis Operator to be ready + run: | + kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system + + - name: Run kuttl test + run: kuttl test ${{ matrix.testpath }} --config tests/_config/kuttl-test.yaml diff --git a/Makefile b/Makefile index 2c39a1d2b..24c1d4bf9 100644 --- a/Makefile +++ b/Makefile @@ -92,7 +92,7 @@ controller-gen: # Download kustomize locally if necessary KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: - $(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7) + $(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.4) # go-install-tool will 'go install' any package $2 and install it to $1. PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index ffa9cb596..5a3d95884 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -12,5 +12,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: controller - newName: quay.io/opstree/redis-operator - newTag: v0.15.0 + newName: redis-operator + newTag: e2e diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index d240cbabd..b935fa165 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -28,11 +28,15 @@ spec: containers: - command: - /manager + env: + - name: ENABLE_WEBHOOKS + value: "false" args: - --leader-elect - -zap-log-level=info - image: quay.io/opstree/redis-operator:v0.12.0 - imagePullPolicy: Always + - -enable-webhooks=false + image: redis-operator:e2e + imagePullPolicy: IfNotPresent name: manager securityContext: allowPrivilegeEscalation: false From aa02370c6628196fcfc98c6823c5f8db300a907e Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 7 Oct 2023 23:32:32 +0800 Subject: [PATCH 029/203] [Fix] : deploy can not set custom image:tag (#664) * fix deploy image to latest tag Signed-off-by: drivebyer * fix image name consistent with kustomization.yaml Signed-off-by: drivebyer * alway use image locally Co-authored-by: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> * Update config/manager/kustomization.yaml * check image Signed-off-by: Shubham Gupta * fix workflow Signed-off-by: Shubham Gupta --------- Signed-off-by: drivebyer Signed-off-by: Shubham Gupta Co-authored-by: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Co-authored-by: Shubham Gupta --- .github/workflows/e2e.yaml | 2 +- config/manager/kustomization.yaml | 4 ++-- config/manager/manager.yaml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index e85476079..c81aaef5b 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -48,7 +48,7 @@ jobs: - name: Install Redis Operator run: | - make deploy + make deploy IMG=redis-operator:e2e - name: Wait for Redis Operator to be ready run: | diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 5a3d95884..f5c1d54fc 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -12,5 +12,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization images: - name: controller - newName: redis-operator - newTag: e2e + newName: quay.io/opstree/redis-operator + newTag: v0.15.1 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index b935fa165..c355ec3d6 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -35,8 +35,8 @@ spec: - --leader-elect - -zap-log-level=info - -enable-webhooks=false - image: redis-operator:e2e - imagePullPolicy: IfNotPresent + image: controller + imagePullPolicy: Never name: manager securityContext: allowPrivilegeEscalation: false From f5c68daf4d91a9b37831fe0a05c750db80ef8ee4 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 10 Oct 2023 14:40:29 +0800 Subject: [PATCH 030/203] [Feat] : support ignore specify annotation key in statefulset (#666) * Support ignore specify annotation key in statefulset Signed-off-by: drivebyer * add e2e Signed-off-by: drivebyer * add test path Signed-off-by: drivebyer * [DEBUG] ignore test dir Signed-off-by: drivebyer * remove comment Signed-off-by: drivebyer * remove assert file, which already assert in setup directory Signed-off-by: drivebyer * add test dirs Signed-off-by: drivebyer * remove exporter Signed-off-by: drivebyer * add error assert Signed-off-by: drivebyer * add more assert Signed-off-by: drivebyer * add more assert Signed-off-by: drivebyer --------- Signed-off-by: drivebyer Signed-off-by: drivebyer --- .github/workflows/e2e.yaml | 1 + api/common_types.go | 1 + .../redis.redis.opstreelabs.in_redis.yaml | 8 + ...is.redis.opstreelabs.in_redisclusters.yaml | 8 + ...edis.opstreelabs.in_redisreplications.yaml | 8 + ...s.redis.opstreelabs.in_redissentinels.yaml | 8 + k8sutils/labels.go | 11 +- k8sutils/labels_test.go | 26 ++- k8sutils/poddisruption.go | 4 +- k8sutils/redis-cluster.go | 3 +- k8sutils/redis-replication.go | 3 +- k8sutils/redis-sentinel.go | 3 +- k8sutils/redis-standalone.go | 3 +- k8sutils/statefulset.go | 5 +- tests/_config/kuttl-test.yaml | 5 +- .../redis-cluster/00-install.yaml | 10 + .../ignore-annots/redis-cluster/cluster.yaml | 40 ++++ .../redis-cluster/ignore-annots-sts.yaml | 23 +++ .../redis-cluster/ready-cluster-sts.yaml | 27 +++ .../redis-cluster/ready-cluster.yaml | 9 + .../redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++++ .../redis-standalone/00-install.yaml | 10 + .../redis-standalone/ignore-annots-sts.yaml | 11 ++ .../redis-standalone/ready-pvc.yaml | 14 ++ .../redis-standalone/ready-standalone.yaml | 6 + .../redis-standalone/ready-sts.yaml | 17 ++ .../redis-standalone/standalone.yaml | 30 +++ 27 files changed, 461 insertions(+), 14 deletions(-) create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index c81aaef5b..1672cb4f0 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -16,6 +16,7 @@ jobs: matrix: testpath: - ./tests/e2e/v1beta2/setup + - ./tests/e2e/v1beta2/ignore-annots steps: - name: Checkout code diff --git a/api/common_types.go b/api/common_types.go index 8eeb7b76c..8d78ad389 100644 --- a/api/common_types.go +++ b/api/common_types.go @@ -15,6 +15,7 @@ type KubernetesConfig struct { ImagePullSecrets *[]corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` UpdateStrategy appsv1.StatefulSetUpdateStrategy `json:"updateStrategy,omitempty"` Service *ServiceConfig `json:"service,omitempty"` + IgnoreAnnotations []string `json:"ignoreAnnotations,omitempty"` } // ServiceConfig define the type of service to be created and its annotations diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index 24a475aa1..2222d4ed0 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -932,6 +932,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: @@ -5100,6 +5104,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index a7ad7a93e..2b9e3c39e 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -138,6 +138,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: @@ -5478,6 +5482,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index 80142c4d2..cf9dbd5bf 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -934,6 +934,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: @@ -5105,6 +5109,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 82de56b4b..91c5b1e5f 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -935,6 +935,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: @@ -2794,6 +2798,10 @@ spec: description: KubernetesConfig will be the JSON struct for Basic Redis Config properties: + ignoreAnnotations: + items: + type: string + type: array image: type: string imagePullPolicy: diff --git a/k8sutils/labels.go b/k8sutils/labels.go index 8e90dfcea..b8e780dc9 100644 --- a/k8sutils/labels.go +++ b/k8sutils/labels.go @@ -86,7 +86,7 @@ func redisSentinelAsOwner(cr *redisv1beta2.RedisSentinel) metav1.OwnerReference } // generateStatefulSetsAnots generates and returns statefulsets annotations -func generateStatefulSetsAnots(stsMeta metav1.ObjectMeta) map[string]string { +func generateStatefulSetsAnots(stsMeta metav1.ObjectMeta, ignoreAnnots []string) map[string]string { anots := map[string]string{ "redis.opstreelabs.in": "true", "redis.opstreelabs.instance": stsMeta.GetName(), @@ -94,14 +94,19 @@ func generateStatefulSetsAnots(stsMeta metav1.ObjectMeta) map[string]string { for k, v := range stsMeta.GetAnnotations() { anots[k] = v } - return filterAnnotations(anots) + return filterAnnotations(anots, ignoreAnnots...) } // filterAnnotations Remove autogenerated annotations which pose no use to downstream objects (Services,Pods,etc) -func filterAnnotations(anots map[string]string) map[string]string { +func filterAnnotations(anots map[string]string, ignoreAnnots ...string) map[string]string { // Filter out some problematic annotations we don't want in the template. delete(anots, "kubectl.kubernetes.io/last-applied-configuration") delete(anots, "banzaicloud.com/last-applied") + + for _, ignoreAnnot := range ignoreAnnots { + delete(anots, ignoreAnnot) + } + return anots } diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go index ba638fc27..10622b513 100644 --- a/k8sutils/labels_test.go +++ b/k8sutils/labels_test.go @@ -101,6 +101,7 @@ func TestAddOwnerRefToObject(t *testing.T) { func Test_generateStatefulSetsAnots(t *testing.T) { type args struct { stsMeta metav1.ObjectMeta + ignore []string } tests := []struct { name string @@ -128,10 +129,33 @@ func Test_generateStatefulSetsAnots(t *testing.T) { "redis.opstreelabs.instance": "sts", }, }, + { + name: "generateStatefulSetsAnots_with_ignore", + args: args{ + stsMeta: metav1.ObjectMeta{ + Name: "sts", + Namespace: "default", + Annotations: map[string]string{ + "app.kubernetes.io/name": "redis", + "operator.redis.com/redis": "redis", + "operator.redis.com/redis-uid": "1234567890", + "a": "b", + }, + }, + ignore: []string{"a"}, + }, + want: map[string]string{ + "app.kubernetes.io/name": "redis", + "operator.redis.com/redis": "redis", + "operator.redis.com/redis-uid": "1234567890", + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "sts", + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := generateStatefulSetsAnots(tt.args.stsMeta); !reflect.DeepEqual(got, tt.want) { + if got := generateStatefulSetsAnots(tt.args.stsMeta, tt.args.ignore); !reflect.DeepEqual(got, tt.want) { t.Errorf("generateStatefulSetsAnots() = %v, want %v", got, tt.want) } }) diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index f1cc97075..1e8cf8bee 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -20,7 +20,7 @@ func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role strin logger := pdbLogger(cr.Namespace, pdbName) if pdbParams != nil && pdbParams.Enabled { labels := getRedisLabels(cr.ObjectMeta.Name, cluster, role, cr.ObjectMeta.GetLabels()) - annotations := generateStatefulSetsAnots(cr.ObjectMeta) + annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) pdbDef := generatePodDisruptionBudgetDef(cr, role, pdbMeta, cr.Spec.RedisLeader.PodDisruptionBudget) return CreateOrUpdatePodDisruptionBudget(pdbDef) @@ -43,7 +43,7 @@ func ReconcileSentinelPodDisruptionBudget(cr *redisv1beta2.RedisSentinel, pdbPar logger := pdbLogger(cr.Namespace, pdbName) if pdbParams != nil && pdbParams.Enabled { labels := getRedisLabels(cr.ObjectMeta.Name, sentinel, "sentinel", cr.ObjectMeta.GetLabels()) - annotations := generateStatefulSetsAnots(cr.ObjectMeta) + annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) pdbDef := generateSentinelPodDisruptionBudgetDef(cr, "sentinel", pdbMeta, pdbParams) return CreateOrUpdatePodDisruptionBudget(pdbDef) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index a367cd55f..f12c5bd84 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -39,6 +39,7 @@ func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, e Tolerations: params.Tolerations, ServiceAccountName: cr.Spec.ServiceAccountName, UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, + IgnoreAnnotations: cr.Spec.KubernetesConfig.IgnoreAnnotations, } if cr.Spec.RedisExporter != nil { res.EnableMetrics = cr.Spec.RedisExporter.Enabled @@ -210,7 +211,7 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) labels := getRedisLabels(stateFulName, cluster, service.RedisStateFulType, cr.ObjectMeta.Labels) - annotations := generateStatefulSetsAnots(cr.ObjectMeta) + annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( cr.Namespace, diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 070f03032..df48c5d18 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -46,7 +46,7 @@ func CreateReplicationRedis(cr *redisv1beta2.RedisReplication) error { stateFulName := cr.ObjectMeta.Name logger := statefulSetLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) - annotations := generateStatefulSetsAnots(cr.ObjectMeta) + annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul(cr.Namespace, objectMetaInfo, @@ -76,6 +76,7 @@ func generateRedisReplicationParams(cr *redisv1beta2.RedisReplication) statefulS Tolerations: cr.Spec.Tolerations, TerminationGracePeriodSeconds: cr.Spec.TerminationGracePeriodSeconds, UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, + IgnoreAnnotations: cr.Spec.KubernetesConfig.IgnoreAnnotations, } if cr.Spec.KubernetesConfig.ImagePullSecrets != nil { res.ImagePullSecrets = cr.Spec.KubernetesConfig.ImagePullSecrets diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index fe11fd24c..8e6b42f53 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -64,7 +64,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) labels := getRedisLabels(stateFulName, cluster, service.RedisStateFulType, cr.ObjectMeta.Labels) - annotations := generateStatefulSetsAnots(cr.ObjectMeta) + annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( cr.Namespace, @@ -99,6 +99,7 @@ func generateRedisSentinelParams(cr *redisv1beta2.RedisSentinel, replicas int32, Tolerations: cr.Spec.Tolerations, ServiceAccountName: cr.Spec.ServiceAccountName, UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, + IgnoreAnnotations: cr.Spec.KubernetesConfig.IgnoreAnnotations, } if cr.Spec.KubernetesConfig.ImagePullSecrets != nil { diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 3276847aa..bd535e227 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -49,7 +49,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { func CreateStandaloneRedis(cr *redisv1beta2.Redis) error { logger := statefulSetLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) - annotations := generateStatefulSetsAnots(cr.ObjectMeta) + annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul(cr.Namespace, objectMetaInfo, @@ -80,6 +80,7 @@ func generateRedisStandaloneParams(cr *redisv1beta2.Redis) statefulSetParameters TerminationGracePeriodSeconds: cr.Spec.TerminationGracePeriodSeconds, Tolerations: cr.Spec.Tolerations, UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, + IgnoreAnnotations: cr.Spec.KubernetesConfig.IgnoreAnnotations, } if cr.Spec.KubernetesConfig.ImagePullSecrets != nil { res.ImagePullSecrets = cr.Spec.KubernetesConfig.ImagePullSecrets diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 9c2d4cf8c..fc8fbd51c 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -46,6 +46,7 @@ type statefulSetParameters struct { RecreateStatefulSet bool InitContainers *[]redisv1beta2.InitContainer TerminationGracePeriodSeconds *int64 + IgnoreAnnotations []string } // containerParameters will define container input params @@ -221,7 +222,7 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: stsMeta.GetLabels(), - Annotations: generateStatefulSetsAnots(stsMeta), + Annotations: generateStatefulSetsAnots(stsMeta, params.IgnoreAnnotations), }, Spec: corev1.PodSpec{ Containers: generateContainerDef( @@ -317,7 +318,7 @@ func createPVCTemplate(volumeName string, stsMeta metav1.ObjectMeta, storageSpec pvcTemplate.Name = volumeName pvcTemplate.Labels = stsMeta.GetLabels() // We want the same annoations as the StatefulSet here - pvcTemplate.Annotations = generateStatefulSetsAnots(stsMeta) + pvcTemplate.Annotations = generateStatefulSetsAnots(stsMeta, nil) if storageSpec.Spec.AccessModes == nil { pvcTemplate.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce} } else { diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml index 66a9a882e..fd45e9604 100644 --- a/tests/_config/kuttl-test.yaml +++ b/tests/_config/kuttl-test.yaml @@ -5,6 +5,7 @@ kindConfig: "./kind-config.yaml" parallel: 1 timeout: 300 testDirs: -- tests/e2e/v1beta2/setup -suppress : + - tests/e2e/v1beta2/setup + - tests/e2e/v1beta2/ignore-annots +suppress : - events \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml new file mode 100644 index 000000000..2f1edf235 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: + - cluster.yaml +assert: + - ready-cluster-sts.yaml + - ready-cluster.yaml + - ready-pvc.yaml +error: + - ignore-annots-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml new file mode 100644 index 000000000..c6137439e --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml @@ -0,0 +1,40 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 + annotations: + need-ignore-key: "need-ignore-value" +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + ignoreAnnotations: + - "need-ignore-key" + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml new file mode 100644 index 000000000..2e2ab3668 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + annotations: + need-ignore-key: "need-ignore-value" +spec: + template: + metadata: + annotations: + need-ignore-key: "need-ignore-value" +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + annotations: + need-ignore-key: "need-ignore-value" +spec: + template: + metadata: + annotations: + need-ignore-key: "need-ignore-value" \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml new file mode 100644 index 000000000..e0cd82e78 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader +spec: + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 +status: + replicas: 3 + readyReplicas: 3 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower +spec: + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..186f67d63 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml @@ -0,0 +1,9 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 + annotations: + need-ignore-key: "need-ignore-value" +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml new file mode 100644 index 000000000..7c6267c56 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: + - standalone.yaml +assert: + - ready-sts.yaml + - ready-pvc.yaml + - ready-standalone.yaml +error: + - ignore-annots-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml new file mode 100644 index 000000000..ced8a3244 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml @@ -0,0 +1,11 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-standalone-v1beta2 + annotations: + need-ignore-key: "need-ignore-value" +spec: + template: + metadata: + annotations: + need-ignore-key: "need-ignore-value" \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml new file mode 100644 index 000000000..777fa3656 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-standalone-v1beta2-redis-standalone-v1beta2-0 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml new file mode 100644 index 000000000..1e25d81c1 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml @@ -0,0 +1,6 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone-v1beta2 + annotations: + need-ignore-key: "need-ignore-value" \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml new file mode 100644 index 000000000..4e95a8910 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml @@ -0,0 +1,17 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +spec: + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 +status: + replicas: 1 + readyReplicas: 1 diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml new file mode 100644 index 000000000..a1b759b61 --- /dev/null +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml @@ -0,0 +1,30 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone-v1beta2 + annotations: + need-ignore-key: "need-ignore-value" +spec: + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + ignoreAnnotations: + - "need-ignore-key" + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi From 461cac47c5bc9933ba0966ab6c02e9bfb60ed8a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:28:05 +0530 Subject: [PATCH 031/203] Bump golang.org/x/net from 0.15.0 to 0.17.0 (#668) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.15.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.15.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index ed287b58b..b8210b8c2 100644 --- a/go.mod +++ b/go.mod @@ -57,10 +57,10 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.15.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 8eedf22f0..cbee05b11 100644 --- a/go.sum +++ b/go.sum @@ -240,8 +240,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= @@ -267,11 +267,11 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 861b8f384e650535b9eae00a1e307a47e4cff957 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:50:07 +0530 Subject: [PATCH 032/203] update tags (#669) Signed-off-by: Shubham Gupta --- .../v1beta2/ignore-annots/redis-cluster/00-install.yaml | 2 +- .../e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml | 4 ++-- .../ignore-annots/redis-cluster/ignore-annots-sts.yaml | 8 ++++++++ .../{ready-cluster-sts.yaml => ready-sts.yaml} | 8 ++++++++ .../ignore-annots/redis-standalone/standalone.yaml | 4 ++-- tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml | 2 +- tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml | 4 ++-- .../{ready-cluster-sts.yaml => ready-sts.yaml} | 8 ++++++++ tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml | 4 ++-- 9 files changed, 34 insertions(+), 10 deletions(-) rename tests/e2e/v1beta2/ignore-annots/redis-cluster/{ready-cluster-sts.yaml => ready-sts.yaml} (73%) rename tests/e2e/v1beta2/setup/redis-cluster/{ready-cluster-sts.yaml => ready-sts.yaml} (57%) diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml index 2f1edf235..97d68615d 100644 --- a/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml @@ -3,8 +3,8 @@ kind: TestStep apply: - cluster.yaml assert: - - ready-cluster-sts.yaml - ready-cluster.yaml + - ready-sts.yaml - ready-pvc.yaml error: - ignore-annots-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml index c6137439e..9744e4f3a 100644 --- a/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml @@ -14,8 +14,8 @@ spec: kubernetesConfig: ignoreAnnotations: - "need-ignore-key" - image: quay.io/opstree/redis:v7.0.12 - imagePullPolicy: IfNotPresent + image: quay.io/opstree/redis:latest + imagePullPolicy: Always resources: requests: cpu: 101m diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml index 2e2ab3668..ec4d3c68a 100644 --- a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml @@ -2,6 +2,10 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader annotations: need-ignore-key: "need-ignore-value" spec: @@ -14,6 +18,10 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower annotations: need-ignore-key: "need-ignore-value" spec: diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml similarity index 73% rename from tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml rename to tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml index e0cd82e78..d272d671b 100644 --- a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster-sts.yaml +++ b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml @@ -2,6 +2,10 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader spec: template: metadata: @@ -16,6 +20,10 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower spec: template: metadata: diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml index a1b759b61..6a940f706 100644 --- a/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml +++ b/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml @@ -11,8 +11,8 @@ spec: kubernetesConfig: ignoreAnnotations: - "need-ignore-key" - image: quay.io/opstree/redis:v7.0.12 - imagePullPolicy: IfNotPresent + image: quay.io/opstree/redis:latest + imagePullPolicy: Always resources: requests: cpu: 101m diff --git a/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml index 1aef14859..4f769cb53 100644 --- a/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml +++ b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml @@ -4,5 +4,5 @@ apply : - cluster.yaml assert : - ready-cluster.yaml - - ready-cluster-sts.yaml + - ready-sts.yaml - ready-pvc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml index 64814772c..ecf147104 100644 --- a/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml +++ b/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml @@ -10,8 +10,8 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.12 - imagePullPolicy: IfNotPresent + image: quay.io/opstree/redis:latest + imagePullPolicy: Always resources: requests: cpu: 101m diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster-sts.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml similarity index 57% rename from tests/e2e/v1beta2/setup/redis-cluster/ready-cluster-sts.yaml rename to tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml index 2b6704dbe..1053eb784 100644 --- a/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster-sts.yaml +++ b/tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml @@ -2,6 +2,10 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader status: replicas: 3 readyReplicas: 3 @@ -12,6 +16,10 @@ apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower status: replicas: 3 readyReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml b/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml index 327c9a946..c0cc6ded9 100644 --- a/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml +++ b/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml @@ -7,8 +7,8 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - image: quay.io/opstree/redis:v7.0.12 - imagePullPolicy: IfNotPresent + image: quay.io/opstree/redis:latest + imagePullPolicy: Always resources: requests: cpu: 101m From 91feb40d23e8b953a9d2d43d299cdc52afd94e81 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 16 Oct 2023 21:22:16 +0800 Subject: [PATCH 033/203] [Fix] : redis exporter mismatch environment (#670) Signed-off-by: drivebyer --- k8sutils/statefulset.go | 69 ++++++++++++++----------------- k8sutils/statefulset_test.go | 79 +++++++++++++++++++++--------------- 2 files changed, 77 insertions(+), 71 deletions(-) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index fc8fbd51c..e63b333b6 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -344,12 +344,10 @@ func generateContainerDef(name string, containerParams containerParameters, clus SecurityContext: containerParams.SecurityContext, Env: getEnvironmentVariables( containerParams.Role, - false, containerParams.EnabledPassword, containerParams.SecretName, containerParams.SecretKey, containerParams.PersistenceEnabled, - containerParams.RedisExporterEnv, containerParams.TLSConfig, containerParams.ACLConfig, containerParams.EnvVars, @@ -464,19 +462,8 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { Name: redisExporterContainer, Image: params.RedisExporterImage, ImagePullPolicy: params.RedisExporterImagePullPolicy, - Env: getEnvironmentVariables( - params.Role, - true, - params.EnabledPassword, - params.SecretName, - params.SecretKey, - params.PersistenceEnabled, - params.RedisExporterEnv, - params.TLSConfig, - params.ACLConfig, - params.EnvVars, - ), - VolumeMounts: getVolumeMount("", nil, false, false, nil, params.AdditionalMountPath, params.TLSConfig, params.ACLConfig), // We need/want the tls-certs but we DON'T need the PVC (if one is available) + Env: getExporterEnvironmentVariables(params.TLSConfig, params.RedisExporterEnv), + VolumeMounts: getVolumeMount("", nil, false, false, nil, params.AdditionalMountPath, params.TLSConfig, params.ACLConfig), // We need/want the tls-certs but we DON'T need the PVC (if one is available) Ports: []corev1.ContainerPort{ { Name: redisExporterPortName, @@ -491,6 +478,32 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { return exporterDefinition } +func getExporterEnvironmentVariables(tlsConfig *redisv1beta2.TLSConfig, env *[]corev1.EnvVar) []corev1.EnvVar { + var envVars []corev1.EnvVar + if tlsConfig != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", + Value: "/tls/tls.key", + }) + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_EXPORTER_TLS_CLIENT_CERT_FILE", + Value: "/tls/tls.crt", + }) + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_EXPORTER_TLS_CA_CERT_FILE", + Value: "/tls/ca.crt", + }) + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_EXPORTER_SKIP_TLS_VERIFICATION", + Value: "true", + }) + } + if env != nil { + envVars = append(envVars, *env...) + } + return envVars +} + // getVolumeMount gives information about persistence mount func getVolumeMount(name string, persistenceEnabled *bool, clusterMode bool, nodeConfVolume bool, externalConfig *string, mountpath []corev1.VolumeMount, tlsConfig *redisv1beta2.TLSConfig, aclConfig *redisv1beta2.ACLConfig) []corev1.VolumeMount { var VolumeMounts []corev1.VolumeMount @@ -557,8 +570,8 @@ func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { } // getEnvironmentVariables returns all the required Environment Variables -func getEnvironmentVariables(role string, enabledMetric bool, enabledPassword *bool, secretName *string, - secretKey *string, persistenceEnabled *bool, exporterEnvVar *[]corev1.EnvVar, tlsConfig *redisv1beta2.TLSConfig, +func getEnvironmentVariables(role string, enabledPassword *bool, secretName *string, + secretKey *string, persistenceEnabled *bool, tlsConfig *redisv1beta2.TLSConfig, aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar) []corev1.EnvVar { envVars := []corev1.EnvVar{ {Name: "SERVER_MODE", Value: role}, @@ -574,24 +587,6 @@ func getEnvironmentVariables(role string, enabledMetric bool, enabledPassword *b if tlsConfig != nil { envVars = append(envVars, GenerateTLSEnvironmentVariables(tlsConfig)...) - if enabledMetric { - envVars = append(envVars, corev1.EnvVar{ - Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", - Value: "/tls/tls.key", - }) - envVars = append(envVars, corev1.EnvVar{ - Name: "REDIS_EXPORTER_TLS_CLIENT_CERT_FILE", - Value: "/tls/tls.crt", - }) - envVars = append(envVars, corev1.EnvVar{ - Name: "REDIS_EXPORTER_TLS_CA_CERT_FILE", - Value: "/tls/ca.crt", - }) - envVars = append(envVars, corev1.EnvVar{ - Name: "REDIS_EXPORTER_SKIP_TLS_VERIFICATION", - Value: "true", - }) - } } if aclConfig != nil { @@ -623,10 +618,6 @@ func getEnvironmentVariables(role string, enabledMetric bool, enabledPassword *b envVars = append(envVars, corev1.EnvVar{Name: "PERSISTENCE_ENABLED", Value: "true"}) } - if exporterEnvVar != nil { - envVars = append(envVars, *exporterEnvVar...) - } - if envVar != nil { envVars = append(envVars, *envVar...) } diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 1bb954166..09a39ced9 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -222,12 +222,10 @@ func TestGetEnvironmentVariables(t *testing.T) { tests := []struct { name string role string - enabledMetric bool enabledPassword *bool secretName *string secretKey *string persistenceEnabled *bool - exporterEnvVar *[]corev1.EnvVar tlsConfig *redisv1beta2.TLSConfig aclConfig *redisv1beta2.ACLConfig envVar *[]corev1.EnvVar @@ -236,14 +234,10 @@ func TestGetEnvironmentVariables(t *testing.T) { { name: "Test with role sentinel, metrics true, password true, persistence true, exporter env, tls enabled, acl enabled and env var", role: "sentinel", - enabledMetric: true, enabledPassword: pointer.Bool(true), secretName: pointer.String("test-secret"), secretKey: pointer.String("test-key"), persistenceEnabled: pointer.Bool(true), - exporterEnvVar: &[]corev1.EnvVar{ - {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, - }, tlsConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "test_ca.crt", @@ -266,10 +260,6 @@ func TestGetEnvironmentVariables(t *testing.T) { {Name: "ACL_MODE", Value: "true"}, {Name: "PERSISTENCE_ENABLED", Value: "true"}, {Name: "REDIS_ADDR", Value: "redis://localhost:26379"}, - {Name: "REDIS_EXPORTER_SKIP_TLS_VERIFICATION", Value: "true"}, - {Name: "REDIS_EXPORTER_TLS_CA_CERT_FILE", Value: "/tls/ca.crt"}, - {Name: "REDIS_EXPORTER_TLS_CLIENT_CERT_FILE", Value: "/tls/tls.crt"}, - {Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", Value: "/tls/tls.key"}, {Name: "TLS_MODE", Value: "true"}, {Name: "REDIS_TLS_CA_KEY", Value: path.Join("/tls/", "test_ca.crt")}, {Name: "REDIS_TLS_CERT", Value: path.Join("/tls/", "test_tls.crt")}, @@ -285,18 +275,15 @@ func TestGetEnvironmentVariables(t *testing.T) { {Name: "SERVER_MODE", Value: "sentinel"}, {Name: "SETUP_MODE", Value: "sentinel"}, {Name: "TEST_ENV", Value: "test-value"}, - {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, }, }, { name: "Test with role redis, metrics false, password nil, persistence nil, exporter nil, tls nil, acl nil and nil env var", role: "redis", - enabledMetric: false, enabledPassword: nil, secretName: nil, secretKey: nil, persistenceEnabled: nil, - exporterEnvVar: nil, tlsConfig: nil, aclConfig: nil, envVar: nil, @@ -309,12 +296,10 @@ func TestGetEnvironmentVariables(t *testing.T) { { name: "Test with role redis, metrics false, password nil, persistence false, exporter nil, tls nil, acl nil and nil env var", role: "sentinel", - enabledMetric: false, enabledPassword: nil, secretName: nil, secretKey: nil, persistenceEnabled: pointer.Bool(false), - exporterEnvVar: nil, tlsConfig: nil, aclConfig: nil, envVar: nil, @@ -327,16 +312,12 @@ func TestGetEnvironmentVariables(t *testing.T) { { name: "Test with role cluster, metrics true, password true, persistence true, exporter env, tls nil, acl enabled and env var", role: "cluster", - enabledMetric: true, enabledPassword: pointer.Bool(true), secretName: pointer.String("test-secret"), secretKey: pointer.String("test-key"), persistenceEnabled: pointer.Bool(true), - exporterEnvVar: &[]corev1.EnvVar{ - {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, - }, - tlsConfig: nil, - aclConfig: &redisv1beta2.ACLConfig{}, + tlsConfig: nil, + aclConfig: &redisv1beta2.ACLConfig{}, envVar: &[]corev1.EnvVar{ {Name: "TEST_ENV", Value: "test-value"}, }, @@ -355,36 +336,70 @@ func TestGetEnvironmentVariables(t *testing.T) { {Name: "SERVER_MODE", Value: "cluster"}, {Name: "SETUP_MODE", Value: "cluster"}, {Name: "TEST_ENV", Value: "test-value"}, - {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, }, }, { name: "Test with cluster role and only metrics enabled", role: "cluster", - enabledMetric: true, enabledPassword: nil, secretName: nil, secretKey: nil, persistenceEnabled: nil, - exporterEnvVar: &[]corev1.EnvVar{ - {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, - }, - tlsConfig: nil, - aclConfig: nil, - envVar: nil, + tlsConfig: nil, + aclConfig: nil, + envVar: nil, expectedEnvironment: []corev1.EnvVar{ {Name: "REDIS_ADDR", Value: "redis://localhost:6379"}, {Name: "SERVER_MODE", Value: "cluster"}, {Name: "SETUP_MODE", Value: "cluster"}, - {Name: "TEST_EXPORTER_ENV", Value: "exporter-value"}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - actualEnvironment := getEnvironmentVariables(tt.role, tt.enabledMetric, tt.enabledPassword, tt.secretName, - tt.secretKey, tt.persistenceEnabled, tt.exporterEnvVar, tt.tlsConfig, tt.aclConfig, tt.envVar) + actualEnvironment := getEnvironmentVariables(tt.role, tt.enabledPassword, tt.secretName, + tt.secretKey, tt.persistenceEnabled, tt.tlsConfig, tt.aclConfig, tt.envVar) + + assert.ElementsMatch(t, tt.expectedEnvironment, actualEnvironment) + }) + } +} + +func Test_getExporterEnvironmentVariables(t *testing.T) { + tests := []struct { + name string + tlsConfig *redisv1beta2.TLSConfig + envVar *[]corev1.EnvVar + expectedEnvironment []corev1.EnvVar + }{ + { + name: "Test with tls enabled and env var", + tlsConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "test_ca.crt", + CertKeyFile: "test_tls.crt", + KeyFile: "test_tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "tls-secret", + }, + }, + }, + envVar: &[]corev1.EnvVar{ + {Name: "TEST_ENV", Value: "test-value"}, + }, + expectedEnvironment: []corev1.EnvVar{ + {Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", Value: "/tls/tls.key"}, + {Name: "REDIS_EXPORTER_TLS_CLIENT_CERT_FILE", Value: "/tls/tls.crt"}, + {Name: "REDIS_EXPORTER_TLS_CA_CERT_FILE", Value: "/tls/ca.crt"}, + {Name: "REDIS_EXPORTER_SKIP_TLS_VERIFICATION", Value: "true"}, + {Name: "TEST_ENV", Value: "test-value"}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actualEnvironment := getExporterEnvironmentVariables(tt.tlsConfig, tt.envVar) assert.ElementsMatch(t, tt.expectedEnvironment, actualEnvironment) }) From f7206cd0219fc553c02363af253d908523248064 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 21 Oct 2023 11:10:39 +0530 Subject: [PATCH 034/203] Add missing deepcopy (#672) Signed-off-by: Shubham Gupta --- api/v1beta2/zz_generated.deepcopy.go | 44 ++++++++++++++++++++++++++++ api/zz_generated.deepcopy.go | 5 ++++ 2 files changed, 49 insertions(+) diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index a813ba2c5..5e5fe2954 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -325,6 +325,17 @@ func (in *RedisClusterSpec) DeepCopyInto(out *RedisClusterSpec) { *out = new(bool) **out = **in } + if in.EnvVars != nil { + in, out := &in.EnvVars, &out.EnvVars + *out = new([]v1.EnvVar) + if **in != nil { + in, out := *in, *out + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisClusterSpec. @@ -630,6 +641,17 @@ func (in *RedisReplicationSpec) DeepCopyInto(out *RedisReplicationSpec) { *out = new(int64) **out = **in } + if in.EnvVars != nil { + in, out := &in.EnvVars, &out.EnvVars + *out = new([]v1.EnvVar) + if **in != nil { + in, out := *in, *out + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisReplicationSpec. @@ -830,6 +852,17 @@ func (in *RedisSentinelSpec) DeepCopyInto(out *RedisSentinelSpec) { *out = new(int64) **out = **in } + if in.EnvVars != nil { + in, out := &in.EnvVars, &out.EnvVars + *out = new([]v1.EnvVar) + if **in != nil { + in, out := *in, *out + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisSentinelSpec. @@ -955,6 +988,17 @@ func (in *RedisSpec) DeepCopyInto(out *RedisSpec) { *out = new(int64) **out = **in } + if in.EnvVars != nil { + in, out := &in.EnvVars, &out.EnvVars + *out = new([]v1.EnvVar) + if **in != nil { + in, out := *in, *out + *out = make([]v1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisSpec. diff --git a/api/zz_generated.deepcopy.go b/api/zz_generated.deepcopy.go index 35ff82c5c..efeda74c2 100644 --- a/api/zz_generated.deepcopy.go +++ b/api/zz_generated.deepcopy.go @@ -107,6 +107,11 @@ func (in *KubernetesConfig) DeepCopyInto(out *KubernetesConfig) { *out = new(ServiceConfig) (*in).DeepCopyInto(*out) } + if in.IgnoreAnnotations != nil { + in, out := &in.IgnoreAnnotations, &out.IgnoreAnnotations + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesConfig. From a7c4452643667185fe0e5d24a6f35d04203497f3 Mon Sep 17 00:00:00 2001 From: guangwu Date: Sat, 21 Oct 2023 14:26:13 +0800 Subject: [PATCH 035/203] fix: typo (#674) Signed-off-by: guoguangwu --- k8sutils/cluster-scaling.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index f58279834..b191b63f5 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -108,7 +108,7 @@ func getRedisClusterSlots(ctx context.Context, cr *redisv1beta2.RedisCluster, no } } - logger.V(1).Info("Total cluster slots to be transfered from", "node", nodeID, "is", totalSlots) + logger.V(1).Info("Total cluster slots to be transferred from", "node", nodeID, "is", totalSlots) return strconv.Itoa(totalSlots) } From 753438148b885bf42ed4b823175f2e50ae78f3c1 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 21 Oct 2023 13:05:15 +0530 Subject: [PATCH 036/203] add code-cov (#675) Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index bae7dc7b2..7a526277a 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -54,8 +54,14 @@ jobs: uses: actions/setup-go@v2 with: go-version: ${{ env.GolangVersion }} - - name: Run Go Tests - run: go test ./... + - name: Run Go Tests with coverage + run: go test ./... -coverprofile=coverage.txt -covermode=atomic + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v2 + with: + file: ./coverage.txt + fail_ci_if_error: true + verbose: true code_quality_golang_ci_lint: needs: [gofmt, govet] From 42dfc93c75a23a8f7a97869072d102258293d281 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 21 Oct 2023 13:16:36 +0530 Subject: [PATCH 037/203] feat: verify codgen in Makefile and Github workflow (#673) * fixing workflow Signed-off-by: Shubham Gupta * verify Signed-off-by: Shubham Gupta * fix version in makefile Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 26 +++++++++---------- .github/workflows/release-images.yaml | 8 +++--- .github/workflows/verify-codegen.yaml | 37 +++++++++++++++++++++++++++ Makefile | 15 ++++++++++- 4 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/verify-codegen.yaml diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 7a526277a..86e32aa14 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -8,11 +8,11 @@ on: - master env: - GolangVersion: 1.21 - ApplicationName: redis-operator + GOLANG_VERSION: 1.21 + APPLICATION_NAME: redis-operator DockerImagName: docker.io/opstree/redis-operator BuildDocs: true - AppVersion: "v0.15.0" + AppVersion: "v0.15.2" DOCKERFILE_PATH: '**/Dockerfile' jobs: @@ -21,9 +21,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: - go-version: ${{ env.GolangVersion }} + go-version: ${{ env.GOLANG_VERSION }} - name: Check Go Fmt run: | gofmt_files=$(go fmt ./... | wc -l) @@ -39,9 +39,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: - go-version: ${{ env.GolangVersion }} + go-version: ${{ env.GOLANG_VERSION }} - name: Run Go Vet run: go vet ./... @@ -51,9 +51,9 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: - go-version: ${{ env.GolangVersion }} + go-version: ${{ env.GOLANG_VERSION }} - name: Run Go Tests with coverage run: go test ./... -coverprofile=coverage.txt -covermode=atomic - name: Upload coverage to Codecov @@ -64,14 +64,14 @@ jobs: verbose: true code_quality_golang_ci_lint: - needs: [gofmt, govet] + needs: [gofmt, govet, gotest] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Go uses: actions/setup-go@v4 with: - go-version: ${{ env.GolangVersion }} + go-version: ${{ env.GOLANG_VERSION }} - name: Run GolangCI-Lint uses: golangci/golangci-lint-action@v3 with: @@ -79,7 +79,7 @@ jobs: args: --timeout=5m0s ./... container_quality_dockerfile_lint: - needs: [gofmt, govet] + needs: [gofmt, govet, gotest] runs-on: ubuntu-latest steps: - name: Checkout code @@ -101,7 +101,7 @@ jobs: - name: Checkout Code uses: actions/checkout@v2 - name: Setup Go Environment - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: ${{ env.GOLANG_VERSION }} - name: Set GOARCH diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 1cee0d163..03f8a1247 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -7,9 +7,9 @@ on: - master env: - ApplicationName: redis-operator + APPLICATION_NAME: redis-operator QuayImageName: quay.io/opstree/redis-operator - AppVersion: "v0.15.1" + APP_VERSION: "v0.15.1" DOCKERFILE_PATH: '**/Dockerfile' jobs: @@ -42,7 +42,7 @@ jobs: file: ${{ env.DOCKERFILE_PATH }} platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.QuayImageName }}:{{ env.AppVersion }}, ${{ env.QuayImageName }}:latest + tags: ${{ env.QuayImageName }}:{{ env.APP_VERSION }}, ${{ env.QuayImageName }}:latest trivy_scan: needs: [build_multi_arch] @@ -56,7 +56,7 @@ jobs: - name: Run Trivy vulnerability scanner for multi-arch image uses: aquasecurity/trivy-action@master with: - image-ref: ${{ env.QuayImageName }}:${{ env.AppVersion }} + image-ref: ${{ env.QuayImageName }}:${{ env.APP_VERSION }} format: 'template' template: '@/contrib/sarif.tpl' output: 'trivy-results-latest.sarif' diff --git a/.github/workflows/verify-codegen.yaml b/.github/workflows/verify-codegen.yaml new file mode 100644 index 000000000..4ac6795f9 --- /dev/null +++ b/.github/workflows/verify-codegen.yaml @@ -0,0 +1,37 @@ +name: Verify Codegen + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + verify-codegen: + runs-on: ubuntu-latest + + steps: + - name: Free disk space + uses: jlumbroso/free-disk-space@v1.3.0 + with: + tool-cache: true + android: true + dotnet: true + haskell: true + large-packages: false + docker-images: true + swap-storage: false + + - name: Checkout code + uses: actions/checkout@v2 + + - uses: actions/setup-go@v4 + with: + go-version-file: go.mod + cache-dependency-path: go.sum + + - name: Run codegen and verify no diffs + run: | + make verify-codegen diff --git a/Makefile b/Makefile index 24c1d4bf9..ad9403426 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # Current Operator version -VERSION ?= 0.15.0 +VERSION ?= 0.15.1 # Default bundle image tag BUNDLE_IMG ?= controller-bundle:$(VERSION) # Options for 'bundle-build' @@ -120,3 +120,16 @@ bundle: manifests kustomize .PHONY: bundle-build bundle-build: docker buildx build --platform="linux/arm64,linux/amd64" -f bundle.Dockerfile -t $(BUNDLE_IMG) . + +# Generate bundle manifests and metadata, then validate generated files. +.PHONY: codegen +codegen: generate manifests ## Rebuild all generated code + +# Verify that codegen is up to date. +.PHONY: verify-codegen +verify-codegen: codegen + @echo Checking codegen is up to date... >&2 + @git --no-pager diff -- . + @echo 'If this test fails, it is because the git diff is non-empty after running "make codegen".' >&2 + @echo 'To correct this, locally run "make codegen", commit the changes, and re-run tests.' >&2 + @git diff --quiet --exit-code -- . \ No newline at end of file From 5b003aeb86802535a4db2aae15ad19be2d197dbc Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 23 Oct 2023 19:30:50 +0800 Subject: [PATCH 038/203] [Test] : add redis replication setup case (#677) * [Test] : add redis replication setup case Signed-off-by: drivebyer * marking false Signed-off-by: drivebyer * fix for review Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/operator-ci.yaml | 4 +- .../setup/redis-replication/00-install.yaml | 8 ++ .../setup/redis-replication/ready-pvc.yaml | 44 +++++++++ .../setup/redis-replication/ready-sts.yaml | 19 ++++ .../setup/redis-replication/ready-svc.yaml | 90 +++++++++++++++++++ .../setup/redis-replication/replication.yaml | 38 ++++++++ 6 files changed, 201 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/v1beta2/setup/redis-replication/00-install.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-replication/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-replication/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-replication/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-replication/replication.yaml diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 86e32aa14..205339b76 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -57,10 +57,10 @@ jobs: - name: Run Go Tests with coverage run: go test ./... -coverprofile=coverage.txt -covermode=atomic - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 with: file: ./coverage.txt - fail_ci_if_error: true + fail_ci_if_error: false verbose: true code_quality_golang_ci_lint: diff --git a/tests/e2e/v1beta2/setup/redis-replication/00-install.yaml b/tests/e2e/v1beta2/setup/redis-replication/00-install.yaml new file mode 100644 index 000000000..19b92e39d --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-replication/00-install.yaml @@ -0,0 +1,8 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: + - replication.yaml +assert: + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-replication/ready-pvc.yaml b/tests/e2e/v1beta2/setup/redis-replication/ready-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-replication/ready-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/setup/redis-replication/ready-sts.yaml b/tests/e2e/v1beta2/setup/redis-replication/ready-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-replication/ready-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-replication/ready-svc.yaml b/tests/e2e/v1beta2/setup/redis-replication/ready-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-replication/ready-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-replication/replication.yaml b/tests/e2e/v1beta2/setup/redis-replication/replication.yaml new file mode 100644 index 000000000..8e4ba0705 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-replication/replication.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file From 5a4b6cf5e5ea9f9530ae8661b9aaedc3cd1aa768 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 23 Oct 2023 21:59:23 +0800 Subject: [PATCH 039/203] [Test] : add assert service to setup (#678) Signed-off-by: drivebyer --- .../setup/redis-cluster/00-install.yaml | 3 +- .../setup/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ .../setup/redis-standalone/00-install.yaml | 3 +- .../setup/redis-standalone/ready-svc.yaml | 96 +++++++++ 4 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-standalone/ready-svc.yaml diff --git a/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml index 4f769cb53..a4d7ca849 100644 --- a/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml +++ b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml @@ -5,4 +5,5 @@ apply : assert : - ready-cluster.yaml - ready-sts.yaml - - ready-pvc.yaml \ No newline at end of file + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml index 3155e0cca..f6256b4f1 100644 --- a/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml +++ b/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml @@ -5,4 +5,5 @@ apply : assert : # - ready-standalone.yaml - ready-sts.yaml - - ready-pvc.yaml \ No newline at end of file + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-standalone/ready-svc.yaml b/tests/e2e/v1beta2/setup/redis-standalone/ready-svc.yaml new file mode 100644 index 000000000..08b416ce2 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-standalone/ready-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2 + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file From 10fd741d54ddec1fc64ef6dc7f4c5bb916c66205 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 24 Oct 2023 02:24:56 +0800 Subject: [PATCH 040/203] [Fix] : setup label redis_setup_type to sentinel (#679) * fix label redis_setup_type to sentinel Signed-off-by: drivebyer * add test Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/redis-sentinel.go | 4 +- .../setup/redis-sentinel/00-install.yaml | 7 ++ .../setup/redis-sentinel/ready-sts.yaml | 35 +++++++ .../setup/redis-sentinel/ready-svc.yaml | 96 +++++++++++++++++++ .../setup/redis-sentinel/sentinel.yaml | 22 +++++ 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-sentinel/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-sentinel/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/setup/redis-sentinel/sentinel.yaml diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 8e6b42f53..a4b7260ec 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -63,7 +63,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) - labels := getRedisLabels(stateFulName, cluster, service.RedisStateFulType, cr.ObjectMeta.Labels) + labels := getRedisLabels(stateFulName, sentinel, service.RedisStateFulType, cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( @@ -199,7 +199,7 @@ func (service RedisSentinelSTS) getSentinelCount(cr *redisv1beta2.RedisSentinel) func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) - labels := getRedisLabels(serviceName, cluster, service.RedisServiceRole, cr.ObjectMeta.Labels) + labels := getRedisLabels(serviceName, sentinel, service.RedisServiceRole, cr.ObjectMeta.Labels) annotations := generateServiceAnots(cr.ObjectMeta, nil) if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml b/tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml new file mode 100644 index 000000000..21253678d --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: + - sentinel.yaml +assert: + - ready-sts.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/ready-sts.yaml b/tests/e2e/v1beta2/setup/redis-sentinel/ready-sts.yaml new file mode 100644 index 000000000..c6056ab05 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-sentinel/ready-sts.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + selector: + matchLabels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + serviceName: redis-sentinel-sentinel-headless + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/ready-svc.yaml b/tests/e2e/v1beta2/setup/redis-sentinel/ready-svc.yaml new file mode 100644 index 000000000..4ce66a032 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-sentinel/ready-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + clusterIP: None + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/sentinel.yaml b/tests/e2e/v1beta2/setup/redis-sentinel/sentinel.yaml new file mode 100644 index 000000000..d18d07f58 --- /dev/null +++ b/tests/e2e/v1beta2/setup/redis-sentinel/sentinel.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file From 52c67ffd6463f7f30896ddf5eb8099eb925b5342 Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 26 Oct 2023 22:26:33 +0800 Subject: [PATCH 041/203] [Fix] : wait follower statefulset ready before make cluster (#680) Signed-off-by: drivebyer --- controllers/rediscluster_controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 98530728d..930f1fcae 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -159,7 +159,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{RequeueAfter: time.Second * 120}, nil } - if int32(redisLeaderInfo.Status.ReadyReplicas) != leaderReplicas && int32(redisFollowerInfo.Status.ReadyReplicas) != followerReplicas { + if !(redisLeaderInfo.Status.ReadyReplicas == leaderReplicas && redisFollowerInfo.Status.ReadyReplicas == followerReplicas) { reqLogger.Info("Redis leader and follower nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) return ctrl.Result{RequeueAfter: time.Second * 120}, nil } From 4a857f99e9b87f53dc4cc8083f9316216321a98e Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 29 Oct 2023 00:19:08 +0530 Subject: [PATCH 042/203] test : validate all the cr in the example dir (#684) * validate-example Signed-off-by: Shubham Gupta * modify name Signed-off-by: Shubham Gupta * fixes Signed-off-by: Shubham Gupta * fix err Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * crd Signed-off-by: Shubham Gupta * fix examples Signed-off-by: Shubham Gupta * fix yamls Signed-off-by: Shubham Gupta * fix yaml Signed-off-by: Shubham Gupta * fix lint Signed-off-by: Shubham Gupta * fix lint Signed-off-by: Shubham Gupta * fix lint Signed-off-by: Shubham Gupta * fix lint Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/validate-example.yaml | 52 ++++++++++++++++ .../v1beta1/additional_config/configmap.yaml | 2 +- example/v1beta1/advance_config/clusterd.yaml | 10 ++-- .../v1beta1/advance_config/standalone.yaml | 10 ++-- example/v1beta1/affinity/clusterd.yaml | 2 +- example/v1beta1/eks-cluster.yaml | 26 -------- .../v1beta1/external_service/cluster-svc.yaml | 22 ++++--- .../external_service/replication-svc.yaml | 10 ++-- .../external_service/standalone-svc.yaml | 10 ++-- .../v1beta1/password_protected/secret.yaml | 6 +- example/v1beta1/redis-cluster.yaml | 54 ++++++++--------- example/v1beta1/redis-replication.yaml | 44 +++++++------- example/v1beta1/redis-sentinel.yaml | 6 +- example/v1beta1/redis-standalone.yaml | 50 ++++++++-------- .../v1beta1/redis_monitoring/clusterd.yaml | 2 +- example/v1beta1/redis_sentinel/sentinel.yaml | 6 +- .../tls_enabled/redis-replication.yaml | 1 + .../v1beta1/tls_enabled/redis-standalone.yaml | 1 + .../v1beta1/upgrade-strategy/standalone.yaml | 4 +- example/v1beta1/volume_mount/configmap.yaml | 3 +- .../v1beta1/volume_mount/redis-cluster.yaml | 11 ++-- .../volume_mount/redis-replication.yaml | 17 +++--- .../volume_mount/redis-standalone.yaml | 15 ++--- example/v1beta2/acl_config/acl-secret.yaml | 4 +- example/v1beta2/acl_config/cluster.yaml | 14 ++--- example/v1beta2/acl_config/replication.yaml | 22 +++---- example/v1beta2/acl_config/standalone.yaml | 14 ++--- .../v1beta2/additional_config/configmap.yaml | 2 +- example/v1beta2/advance_config/clusterd.yaml | 10 ++-- .../v1beta2/advance_config/standalone.yaml | 10 ++-- example/v1beta2/affinity/clusterd.yaml | 2 +- .../backup_restore/backup/env-secrets.yaml | 3 +- .../v1beta2/backup_restore/backup/job.yaml | 15 ++--- .../backup_restore/backup/role-binding.yaml | 3 +- .../v1beta2/backup_restore/backup/role.yaml | 3 +- .../backup/service-account.yaml | 3 +- .../backup_restore/restore/env-secret.yaml | 3 +- .../backup_restore/restore/redis-cluster.yaml | 60 +++++++++---------- example/v1beta2/eks-cluster.yaml | 26 -------- example/v1beta2/env_vars/redis-cluster.yaml | 19 +++--- .../v1beta2/env_vars/redis-replication.yaml | 18 +++--- example/v1beta2/env_vars/redis-sentinel.yaml | 14 ++--- .../v1beta2/env_vars/redis-standalone.yaml | 32 +++++----- .../v1beta2/external_service/cluster-svc.yaml | 22 ++++--- .../external_service/replication-svc.yaml | 10 ++-- .../external_service/standalone-svc.yaml | 10 ++-- .../v1beta2/password_protected/secret.yaml | 6 +- example/v1beta2/redis-cluster.yaml | 60 +++++++++---------- example/v1beta2/redis-replication.yaml | 38 ++++++------ example/v1beta2/redis-sentinel.yaml | 6 +- example/v1beta2/redis-standalone.yaml | 52 ++++++++-------- .../v1beta2/redis_monitoring/clusterd.yaml | 2 +- example/v1beta2/redis_sentinel/sentinel.yaml | 6 +- .../v1beta2/sidecar_features/configmap.yaml | 2 +- example/v1beta2/sidecar_features/sidecar.yaml | 20 +++---- .../v1beta2/tls_enabled/redis-cluster.yaml | 2 +- .../tls_enabled/redis-replication.yaml | 1 + .../v1beta2/tls_enabled/redis-standalone.yaml | 1 + .../v1beta2/upgrade-strategy/replication.yaml | 1 - .../v1beta2/upgrade-strategy/standalone.yaml | 4 +- example/v1beta2/volume_mount/configmap.yaml | 3 +- .../v1beta2/volume_mount/redis-cluster.yaml | 11 ++-- .../volume_mount/redis-replication.yaml | 17 +++--- .../volume_mount/redis-standalone.yaml | 15 ++--- 64 files changed, 472 insertions(+), 458 deletions(-) create mode 100644 .github/workflows/validate-example.yaml delete mode 100644 example/v1beta1/eks-cluster.yaml delete mode 100644 example/v1beta2/eks-cluster.yaml diff --git a/.github/workflows/validate-example.yaml b/.github/workflows/validate-example.yaml new file mode 100644 index 000000000..f0f11de98 --- /dev/null +++ b/.github/workflows/validate-example.yaml @@ -0,0 +1,52 @@ +name: Validate Examples + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + validate-examples: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install yamllint + run: sudo apt-get install -y yamllint + + - name: Lint YAML files + run: yamllint --strict ./example + + - name: Install kubectl + run: | + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/ + + - name: Create k8s Kind Cluster + uses: helm/kind-action@v1.5.0 + with: + cluster_name: kind + + - name: Apply CRD + run: | + for crd in $(find ./config/crd/bases -type f -name '*.yaml'); do + kubectl create -f $crd + done + + - name: Validate CRD Installation + run: | + CRDs=("redis" "redissentinels" "redisclusters" "redisreplications") + for crd in "${CRDs[@]}"; do + kubectl get crd $crd.redis.redis.opstreelabs.in || exit 1 + done + + - name: Validate CR + run: | + for example in $(find ./example -type f -name '*.yaml'); do + kubectl apply --dry-run=server -f $example + done \ No newline at end of file diff --git a/example/v1beta1/additional_config/configmap.yaml b/example/v1beta1/additional_config/configmap.yaml index f68ea80ac..d06cec022 100644 --- a/example/v1beta1/additional_config/configmap.yaml +++ b/example/v1beta1/additional_config/configmap.yaml @@ -6,5 +6,5 @@ metadata: data: redis-additional.conf: | tcp-keepalive 400 - slowlog-max-len 158 + slowlog-max-len 158 stream-node-max-bytes 2048 diff --git a/example/v1beta1/advance_config/clusterd.yaml b/example/v1beta1/advance_config/clusterd.yaml index 305a13c19..44493e436 100644 --- a/example/v1beta1/advance_config/clusterd.yaml +++ b/example/v1beta1/advance_config/clusterd.yaml @@ -32,8 +32,8 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: {} - # securityContext: {} - # priorityClassName: "" - # affinity: {} - # Tolerations: [] + # nodeSelector: {} + # securityContext: {} + # priorityClassName: "" + # affinity: {} + # Tolerations: [] diff --git a/example/v1beta1/advance_config/standalone.yaml b/example/v1beta1/advance_config/standalone.yaml index e76625154..f8d91bd74 100644 --- a/example/v1beta1/advance_config/standalone.yaml +++ b/example/v1beta1/advance_config/standalone.yaml @@ -28,8 +28,8 @@ spec: redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 - # nodeSelector: {} - # securityContext: {} - # priorityClassName: "" - # affinity: {} - # Tolerations: [] + # nodeSelector: {} + # securityContext: {} + # priorityClassName: "" + # affinity: {} + # Tolerations: [] diff --git a/example/v1beta1/affinity/clusterd.yaml b/example/v1beta1/affinity/clusterd.yaml index 535a98fde..89ae32a8e 100644 --- a/example/v1beta1/affinity/clusterd.yaml +++ b/example/v1beta1/affinity/clusterd.yaml @@ -38,7 +38,7 @@ spec: operator: In values: - redis-cluster-follower - - redis-cluster-leader + - redis-cluster-leader topologyKey: "kubernetes.io/hostname" storage: volumeClaimTemplate: diff --git a/example/v1beta1/eks-cluster.yaml b/example/v1beta1/eks-cluster.yaml deleted file mode 100644 index 4474537e3..000000000 --- a/example/v1beta1/eks-cluster.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig -metadata: - name: operator-testing - region: us-west-2 - version: "1.22" -managedNodeGroups: - - name: ng-1 - instanceType: t3a.medium - desiredCapacity: 3 - volumeSize: 30 - ssh: - allow: true - volumeType: gp3 -kubernetesNetworkConfig: - ipFamily: IPv4 -# ipFamily: IPv6 -addons: - - name: vpc-cni - - name: coredns - - name: kube-proxy - - name: aws-ebs-csi-driver - attachPolicyARNs: - - arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy -iam: - withOIDC: true diff --git a/example/v1beta1/external_service/cluster-svc.yaml b/example/v1beta1/external_service/cluster-svc.yaml index 8e68ca75f..bcc2eceb4 100644 --- a/example/v1beta1/external_service/cluster-svc.yaml +++ b/example/v1beta1/external_service/cluster-svc.yaml @@ -8,17 +8,16 @@ metadata: role: leader name: redis-cluster-leaders spec: - clusterIP: 10.102.152.77 ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-cluster-leader redis_setup_type: cluster role: leader -# type: LoadBalancer + # type: LoadBalancer type: NodePort --- apiVersion: v1 @@ -30,15 +29,14 @@ metadata: role: follower name: redis-cluster-followers spec: - clusterIP: 10.108.109.134 ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-cluster-follower redis_setup_type: cluster role: follower -# type: LoadBalancer + # type: LoadBalancer type: NodePort diff --git a/example/v1beta1/external_service/replication-svc.yaml b/example/v1beta1/external_service/replication-svc.yaml index 5e412de80..0b63b380c 100644 --- a/example/v1beta1/external_service/replication-svc.yaml +++ b/example/v1beta1/external_service/replication-svc.yaml @@ -9,13 +9,13 @@ metadata: name: redis-replication spec: ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-replication redis_setup_type: replication role: replication -# type: LoadBalancer + # type: LoadBalancer type: NodePort diff --git a/example/v1beta1/external_service/standalone-svc.yaml b/example/v1beta1/external_service/standalone-svc.yaml index df4efe038..2c8c8aec5 100644 --- a/example/v1beta1/external_service/standalone-svc.yaml +++ b/example/v1beta1/external_service/standalone-svc.yaml @@ -9,13 +9,13 @@ metadata: name: redis-standalone spec: ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-standalone redis_setup_type: standalone role: standalone -# type: LoadBalancer + # type: LoadBalancer type: NodePort diff --git a/example/v1beta1/password_protected/secret.yaml b/example/v1beta1/password_protected/secret.yaml index 2a91c0d81..cf1cf0a6a 100644 --- a/example/v1beta1/password_protected/secret.yaml +++ b/example/v1beta1/password_protected/secret.yaml @@ -1,8 +1,8 @@ ---- +--- apiVersion: v1 kind: Secret metadata: name: redis-secret data: - password: T3BzdHJlZUAxMjM0Cg== -type: Opaque \ No newline at end of file + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque diff --git a/example/v1beta1/redis-cluster.yaml b/example/v1beta1/redis-cluster.yaml index 148c4f74b..cf32d2868 100644 --- a/example/v1beta1/redis-cluster.yaml +++ b/example/v1beta1/redis-cluster.yaml @@ -23,8 +23,8 @@ spec: redisSecret: name: redis-secret key: password - # imagePullSecrets: - # - name: regcred + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -36,26 +36,26 @@ spec: limits: cpu: 100m memory: 128Mi -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username -# redisLeader: -# redisConfig: -# additionalRedisConfig: redis-external-config -# redisFollower: -# redisConfig: -# additionalRedisConfig: redis-external-config + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + # redisLeader: + # redisConfig: + # additionalRedisConfig: redis-external-config + # redisFollower: + # redisConfig: + # additionalRedisConfig: redis-external-config storage: volumeClaimTemplate: spec: @@ -64,8 +64,8 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: - # kubernetes.io/hostname: minikube - # priorityClassName: - # Affinity: - # Tolerations: [] + # nodeSelector: + # kubernetes.io/hostname: minikube + # priorityClassName: + # Affinity: + # Tolerations: [] diff --git a/example/v1beta1/redis-replication.yaml b/example/v1beta1/redis-replication.yaml index 5170612f9..49e4262b4 100644 --- a/example/v1beta1/redis-replication.yaml +++ b/example/v1beta1/redis-replication.yaml @@ -2,7 +2,7 @@ apiVersion: redis.redis.opstreelabs.in/v1beta1 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 securityContext: @@ -10,7 +10,7 @@ spec: fsGroup: 1000 # redisConfig: # additionalRedisConfig: redis-external-config - kubernetesConfig: + kubernetesConfig: image: quay.io/opstree/redis:v7.0.5 imagePullPolicy: IfNotPresent resources: @@ -20,11 +20,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -36,20 +36,20 @@ spec: limits: cpu: 100m memory: 128Mi -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username storage: volumeClaimTemplate: spec: @@ -57,4 +57,4 @@ spec: accessModes: ["ReadWriteOnce"] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/example/v1beta1/redis-sentinel.yaml b/example/v1beta1/redis-sentinel.yaml index 430916b6c..c6eca8fd8 100644 --- a/example/v1beta1/redis-sentinel.yaml +++ b/example/v1beta1/redis-sentinel.yaml @@ -8,10 +8,10 @@ spec: securityContext: runAsUser: 1000 fsGroup: 1000 - redisSentinelConfig: - redisReplicationName : redis-replication + redisSentinelConfig: + redisReplicationName: redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.12 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta1/redis-standalone.yaml b/example/v1beta1/redis-standalone.yaml index 00340ed64..c5359b8cc 100644 --- a/example/v1beta1/redis-standalone.yaml +++ b/example/v1beta1/redis-standalone.yaml @@ -16,11 +16,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -32,20 +32,20 @@ spec: limits: cpu: 100m memory: 128Mi -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username storage: volumeClaimTemplate: spec: @@ -54,9 +54,9 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: - # kubernetes.io/hostname: minikube - # securityContext: {} - # priorityClassName: - # affinity: - # Tolerations: [] + # nodeSelector: + # kubernetes.io/hostname: minikube + # securityContext: {} + # priorityClassName: + # affinity: + # Tolerations: [] diff --git a/example/v1beta1/redis_monitoring/clusterd.yaml b/example/v1beta1/redis_monitoring/clusterd.yaml index 119d86ef2..e28737c93 100644 --- a/example/v1beta1/redis_monitoring/clusterd.yaml +++ b/example/v1beta1/redis_monitoring/clusterd.yaml @@ -26,4 +26,4 @@ spec: resources: requests: storage: 1Gi - # storageClassName: standard + # storageClassName: standard diff --git a/example/v1beta1/redis_sentinel/sentinel.yaml b/example/v1beta1/redis_sentinel/sentinel.yaml index 430916b6c..c6eca8fd8 100644 --- a/example/v1beta1/redis_sentinel/sentinel.yaml +++ b/example/v1beta1/redis_sentinel/sentinel.yaml @@ -8,10 +8,10 @@ spec: securityContext: runAsUser: 1000 fsGroup: 1000 - redisSentinelConfig: - redisReplicationName : redis-replication + redisSentinelConfig: + redisReplicationName: redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.12 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta1/tls_enabled/redis-replication.yaml b/example/v1beta1/tls_enabled/redis-replication.yaml index ac8b34490..42711e713 100644 --- a/example/v1beta1/tls_enabled/redis-replication.yaml +++ b/example/v1beta1/tls_enabled/redis-replication.yaml @@ -1,3 +1,4 @@ +# yamllint disable-line rule:line-length # Examples of creating a valid TLS certificate can be found at ./config/certmanager via Cert-manager --- apiVersion: redis.redis.opstreelabs.in/v1beta1 diff --git a/example/v1beta1/tls_enabled/redis-standalone.yaml b/example/v1beta1/tls_enabled/redis-standalone.yaml index 3e254fd65..1e213afa7 100644 --- a/example/v1beta1/tls_enabled/redis-standalone.yaml +++ b/example/v1beta1/tls_enabled/redis-standalone.yaml @@ -1,3 +1,4 @@ +# yamllint disable-line rule:line-length # Examples of creating a valid TLS certificate can be found at ./config/certmanager via Cert-manager --- apiVersion: redis.redis.opstreelabs.in/v1beta1 diff --git a/example/v1beta1/upgrade-strategy/standalone.yaml b/example/v1beta1/upgrade-strategy/standalone.yaml index bfc1b445e..2ce6c1757 100644 --- a/example/v1beta1/upgrade-strategy/standalone.yaml +++ b/example/v1beta1/upgrade-strategy/standalone.yaml @@ -9,7 +9,7 @@ spec: imagePullPolicy: IfNotPresent updateStrategy: type: OnDelete -# type: RollingUpdate + # type: RollingUpdate securityContext: runAsUser: 1000 fsGroup: 1000 @@ -23,4 +23,4 @@ spec: storage: 1Gi redisExporter: enabled: false - image: quay.io/opstree/redis-exporter:v1.44.0 \ No newline at end of file + image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta1/volume_mount/configmap.yaml b/example/v1beta1/volume_mount/configmap.yaml index eb5501a23..b6bc927f1 100644 --- a/example/v1beta1/volume_mount/configmap.yaml +++ b/example/v1beta1/volume_mount/configmap.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -5,4 +6,4 @@ metadata: labels: app: myapplication data: - my-key: my-value \ No newline at end of file + my-key: my-value diff --git a/example/v1beta1/volume_mount/redis-cluster.yaml b/example/v1beta1/volume_mount/redis-cluster.yaml index 1b74ee260..799b1b914 100644 --- a/example/v1beta1/volume_mount/redis-cluster.yaml +++ b/example/v1beta1/volume_mount/redis-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta1 kind: RedisCluster metadata: @@ -22,8 +23,8 @@ spec: redisSecret: name: redis-secret key: password - # imagePullSecrets: - # - name: regcred + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -43,11 +44,11 @@ spec: resources: requests: storage: 1Gi - volumemount: + volumeMount: volume: - name: example-config configMap: name: example-configmap - mount: + mountPath: - mountPath: /config - name: example-config \ No newline at end of file + name: example-config diff --git a/example/v1beta1/volume_mount/redis-replication.yaml b/example/v1beta1/volume_mount/redis-replication.yaml index 58adea03a..bed424781 100644 --- a/example/v1beta1/volume_mount/redis-replication.yaml +++ b/example/v1beta1/volume_mount/redis-replication.yaml @@ -1,7 +1,8 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta1 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 # redisConfig: @@ -16,11 +17,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -40,11 +41,11 @@ spec: resources: requests: storage: 1Gi - volumemount: + volumeMount: volume: - name: example-config configMap: name: example-configmap - mount: + mountPath: - mountPath: /config name: example-config diff --git a/example/v1beta1/volume_mount/redis-standalone.yaml b/example/v1beta1/volume_mount/redis-standalone.yaml index 6d1a59f44..8af9ec3a0 100644 --- a/example/v1beta1/volume_mount/redis-standalone.yaml +++ b/example/v1beta1/volume_mount/redis-standalone.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta1 kind: Redis metadata: @@ -15,11 +16,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -39,11 +40,11 @@ spec: resources: requests: storage: 1Gi - volumemount: + volumeMount: volume: - name: example-config configMap: name: example-configmap - mount: + mountPath: - mountPath: /config name: example-config diff --git a/example/v1beta2/acl_config/acl-secret.yaml b/example/v1beta2/acl_config/acl-secret.yaml index 5f9bae4d7..734b4f086 100644 --- a/example/v1beta2/acl_config/acl-secret.yaml +++ b/example/v1beta2/acl_config/acl-secret.yaml @@ -1,8 +1,10 @@ +--- apiVersion: v1 data: + # yamllint disable-line rule:line-length user.acl: dXNlciBvcHN0cmVlIG9uIH4qICYqICtAYWxsID5hYmNAMTIzCnVzZXIgYnVpbGRwaXBlciBvbiB+KiAmKiArQGFsbCA+YWJjQDEyMwo= kind: Secret metadata: name: acl-secret namespace: default -type: Opaque \ No newline at end of file +type: Opaque diff --git a/example/v1beta2/acl_config/cluster.yaml b/example/v1beta2/acl_config/cluster.yaml index 70671263f..5a73ad257 100644 --- a/example/v1beta2/acl_config/cluster.yaml +++ b/example/v1beta2/acl_config/cluster.yaml @@ -20,14 +20,14 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred acl: - secret : - name: acl-secret + secret: + secretName: acl-secret redisExporter: enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta2/acl_config/replication.yaml b/example/v1beta2/acl_config/replication.yaml index 8b53a5ae6..dcd52ce0e 100644 --- a/example/v1beta2/acl_config/replication.yaml +++ b/example/v1beta2/acl_config/replication.yaml @@ -2,7 +2,7 @@ apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 podSecurityContext: @@ -10,7 +10,7 @@ spec: fsGroup: 1000 # redisConfig: # additionalRedisConfig: redis-external-config - kubernetesConfig: + kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: @@ -20,15 +20,15 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred acl: - secret : - name: acl-secret - + secret: + secretName: acl-secret + redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -48,4 +48,4 @@ spec: accessModes: ["ReadWriteOnce"] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/example/v1beta2/acl_config/standalone.yaml b/example/v1beta2/acl_config/standalone.yaml index f586f9727..ed243a828 100644 --- a/example/v1beta2/acl_config/standalone.yaml +++ b/example/v1beta2/acl_config/standalone.yaml @@ -16,14 +16,14 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred acl: - secret: - name: acl-secret + secret: + secretName: acl-secret redisExporter: enabled: false diff --git a/example/v1beta2/additional_config/configmap.yaml b/example/v1beta2/additional_config/configmap.yaml index f68ea80ac..d06cec022 100644 --- a/example/v1beta2/additional_config/configmap.yaml +++ b/example/v1beta2/additional_config/configmap.yaml @@ -6,5 +6,5 @@ metadata: data: redis-additional.conf: | tcp-keepalive 400 - slowlog-max-len 158 + slowlog-max-len 158 stream-node-max-bytes 2048 diff --git a/example/v1beta2/advance_config/clusterd.yaml b/example/v1beta2/advance_config/clusterd.yaml index 57d7ff97f..ade429f8b 100644 --- a/example/v1beta2/advance_config/clusterd.yaml +++ b/example/v1beta2/advance_config/clusterd.yaml @@ -38,8 +38,8 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: {} - # podSecurityContext: {} - # priorityClassName: "" - # affinity: {} - # Tolerations: [] + # nodeSelector: {} + # podSecurityContext: {} + # priorityClassName: "" + # affinity: {} + # Tolerations: [] diff --git a/example/v1beta2/advance_config/standalone.yaml b/example/v1beta2/advance_config/standalone.yaml index f74862b5a..cd4fe06ce 100644 --- a/example/v1beta2/advance_config/standalone.yaml +++ b/example/v1beta2/advance_config/standalone.yaml @@ -28,8 +28,8 @@ spec: redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 - # nodeSelector: {} - # podSecurityContext: {} - # priorityClassName: "" - # affinity: {} - # Tolerations: [] + # nodeSelector: {} + # podSecurityContext: {} + # priorityClassName: "" + # affinity: {} + # Tolerations: [] diff --git a/example/v1beta2/affinity/clusterd.yaml b/example/v1beta2/affinity/clusterd.yaml index 84623e61d..d7c3f64bf 100644 --- a/example/v1beta2/affinity/clusterd.yaml +++ b/example/v1beta2/affinity/clusterd.yaml @@ -38,7 +38,7 @@ spec: operator: In values: - redis-cluster-follower - - redis-cluster-leader + - redis-cluster-leader topologyKey: "kubernetes.io/hostname" storage: volumeClaimTemplate: diff --git a/example/v1beta2/backup_restore/backup/env-secrets.yaml b/example/v1beta2/backup_restore/backup/env-secrets.yaml index ae124980b..84e1be7e9 100644 --- a/example/v1beta2/backup_restore/backup/env-secrets.yaml +++ b/example/v1beta2/backup_restore/backup/env-secrets.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Secret metadata: @@ -15,4 +16,4 @@ stringData: AWS_S3_BUCKET: shubham-redis AWS_DEFAULT_REGION: ap-south-1 AWS_ACCESS_KEY_ID: "" - AWS_SECRET_ACCESS_KEY: "" \ No newline at end of file + AWS_SECRET_ACCESS_KEY: "" diff --git a/example/v1beta2/backup_restore/backup/job.yaml b/example/v1beta2/backup_restore/backup/job.yaml index 6b9fcdc87..414eb1433 100644 --- a/example/v1beta2/backup_restore/backup/job.yaml +++ b/example/v1beta2/backup_restore/backup/job.yaml @@ -1,3 +1,4 @@ +--- apiVersion: batch/v1 kind: Job metadata: @@ -10,11 +11,11 @@ spec: spec: serviceAccountName: backup-service-account containers: - - name: redis-operator-backup-container - image: "quay.io/opstree/redis-operator-backup:v0.15.1" - command: ["/bin/bash", "-c", "/backup/backup.bash"] - imagePullPolicy: Always - envFrom: - - secretRef: - name: env-secrets + - name: redis-operator-backup-container + image: "quay.io/opstree/redis-operator-backup:v0.15.1" + command: ["/bin/bash", "-c", "/backup/backup.bash"] + imagePullPolicy: Always + envFrom: + - secretRef: + name: env-secrets restartPolicy: Never diff --git a/example/v1beta2/backup_restore/backup/role-binding.yaml b/example/v1beta2/backup_restore/backup/role-binding.yaml index bdab12539..a60dc5234 100644 --- a/example/v1beta2/backup_restore/backup/role-binding.yaml +++ b/example/v1beta2/backup_restore/backup/role-binding.yaml @@ -1,3 +1,4 @@ +--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: @@ -8,4 +9,4 @@ subjects: roleRef: kind: Role name: modify-pods - apiGroup: rbac.authorization.k8s.io \ No newline at end of file + apiGroup: rbac.authorization.k8s.io diff --git a/example/v1beta2/backup_restore/backup/role.yaml b/example/v1beta2/backup_restore/backup/role.yaml index 1ab15a715..d84c34535 100644 --- a/example/v1beta2/backup_restore/backup/role.yaml +++ b/example/v1beta2/backup_restore/backup/role.yaml @@ -1,3 +1,4 @@ +--- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: @@ -5,4 +6,4 @@ metadata: rules: - apiGroups: ["*"] resources: ["*"] - verbs: ["*"] \ No newline at end of file + verbs: ["*"] diff --git a/example/v1beta2/backup_restore/backup/service-account.yaml b/example/v1beta2/backup_restore/backup/service-account.yaml index d860c2d63..6be2a7ac8 100644 --- a/example/v1beta2/backup_restore/backup/service-account.yaml +++ b/example/v1beta2/backup_restore/backup/service-account.yaml @@ -1,4 +1,5 @@ +--- apiVersion: v1 kind: ServiceAccount metadata: - name: backup-service-account \ No newline at end of file + name: backup-service-account diff --git a/example/v1beta2/backup_restore/restore/env-secret.yaml b/example/v1beta2/backup_restore/restore/env-secret.yaml index 03748498a..9a20b1270 100644 --- a/example/v1beta2/backup_restore/restore/env-secret.yaml +++ b/example/v1beta2/backup_restore/restore/env-secret.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Secret metadata: @@ -14,4 +15,4 @@ stringData: AWS_S3_BUCKET: shubham-redis AWS_DEFAULT_REGION: ap-south-1 AWS_ACCESS_KEY_ID: "" - AWS_SECRET_ACCESS_KEY: "" \ No newline at end of file + AWS_SECRET_ACCESS_KEY: "" diff --git a/example/v1beta2/backup_restore/restore/redis-cluster.yaml b/example/v1beta2/backup_restore/restore/redis-cluster.yaml index 50fdaea5e..d51445ffe 100644 --- a/example/v1beta2/backup_restore/restore/redis-cluster.yaml +++ b/example/v1beta2/backup_restore/restore/redis-cluster.yaml @@ -20,11 +20,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred initContainer: enabled: true image: quay.io/opstree/redis-operator-restore:latest @@ -88,26 +88,26 @@ spec: secretKeyRef: name: env-secrets key: AWS_SECRET_ACCESS_KEY -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username -# redisLeader: -# redisConfig: -# additionalRedisConfig: redis-external-config -# redisFollower: -# redisConfig: -# additionalRedisConfig: redis-external-config + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + # redisLeader: + # redisConfig: + # additionalRedisConfig: redis-external-config + # redisFollower: + # redisConfig: + # additionalRedisConfig: redis-external-config redisLeader: redisConfig: @@ -130,8 +130,8 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: - # kubernetes.io/hostname: minikube - # priorityClassName: - # Affinity: - # Tolerations: [] + # nodeSelector: + # kubernetes.io/hostname: minikube + # priorityClassName: + # Affinity: + # Tolerations: [] diff --git a/example/v1beta2/eks-cluster.yaml b/example/v1beta2/eks-cluster.yaml deleted file mode 100644 index 4474537e3..000000000 --- a/example/v1beta2/eks-cluster.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig -metadata: - name: operator-testing - region: us-west-2 - version: "1.22" -managedNodeGroups: - - name: ng-1 - instanceType: t3a.medium - desiredCapacity: 3 - volumeSize: 30 - ssh: - allow: true - volumeType: gp3 -kubernetesNetworkConfig: - ipFamily: IPv4 -# ipFamily: IPv6 -addons: - - name: vpc-cni - - name: coredns - - name: kube-proxy - - name: aws-ebs-csi-driver - attachPolicyARNs: - - arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy -iam: - withOIDC: true diff --git a/example/v1beta2/env_vars/redis-cluster.yaml b/example/v1beta2/env_vars/redis-cluster.yaml index 082c1ae81..c573cd98c 100644 --- a/example/v1beta2/env_vars/redis-cluster.yaml +++ b/example/v1beta2/env_vars/redis-cluster.yaml @@ -21,15 +21,15 @@ spec: cpu: 101m memory: 128Mi env: - - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" - - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred storage: volumeClaimTemplate: spec: @@ -45,4 +45,3 @@ spec: resources: requests: storage: 1Gi - diff --git a/example/v1beta2/env_vars/redis-replication.yaml b/example/v1beta2/env_vars/redis-replication.yaml index 99214c8bc..3c27d74c9 100644 --- a/example/v1beta2/env_vars/redis-replication.yaml +++ b/example/v1beta2/env_vars/redis-replication.yaml @@ -2,7 +2,7 @@ apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 podSecurityContext: @@ -10,7 +10,7 @@ spec: fsGroup: 1000 # redisConfig: # additionalRedisConfig: redis-external-config - kubernetesConfig: + kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: @@ -23,13 +23,13 @@ spec: redisSecret: name: redis-secret key: password - # imagePullSecrets: - # - name: regcred + # imagePullSecrets: + # - name: regcred env: - - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" - - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" storage: volumeClaimTemplate: spec: @@ -37,4 +37,4 @@ spec: accessModes: ["ReadWriteOnce"] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/example/v1beta2/env_vars/redis-sentinel.yaml b/example/v1beta2/env_vars/redis-sentinel.yaml index 6dd84edeb..26e9ef6c9 100644 --- a/example/v1beta2/env_vars/redis-sentinel.yaml +++ b/example/v1beta2/env_vars/redis-sentinel.yaml @@ -11,10 +11,10 @@ spec: pdb: enabled: false minAvailable: 1 - redisSentinelConfig: - redisReplicationName : redis-replication + redisSentinelConfig: + redisReplicationName: redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.12 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: @@ -24,7 +24,7 @@ spec: cpu: 101m memory: 128Mi env: - - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" - - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" \ No newline at end of file + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" diff --git a/example/v1beta2/env_vars/redis-standalone.yaml b/example/v1beta2/env_vars/redis-standalone.yaml index e0dd08947..89af0c973 100644 --- a/example/v1beta2/env_vars/redis-standalone.yaml +++ b/example/v1beta2/env_vars/redis-standalone.yaml @@ -8,7 +8,7 @@ spec: # additionalRedisConfig: redis-external-config podSecurityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent @@ -19,11 +19,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -36,10 +36,10 @@ spec: cpu: 100m memory: 128Mi env: - - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" - - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" storage: volumeClaimTemplate: spec: @@ -48,9 +48,9 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: - # kubernetes.io/hostname: minikube - # podSecurityContext: {} - # priorityClassName: - # affinity: - # Tolerations: [] + # nodeSelector: + # kubernetes.io/hostname: minikube + # podSecurityContext: {} + # priorityClassName: + # affinity: + # Tolerations: [] diff --git a/example/v1beta2/external_service/cluster-svc.yaml b/example/v1beta2/external_service/cluster-svc.yaml index 8e68ca75f..bcc2eceb4 100644 --- a/example/v1beta2/external_service/cluster-svc.yaml +++ b/example/v1beta2/external_service/cluster-svc.yaml @@ -8,17 +8,16 @@ metadata: role: leader name: redis-cluster-leaders spec: - clusterIP: 10.102.152.77 ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-cluster-leader redis_setup_type: cluster role: leader -# type: LoadBalancer + # type: LoadBalancer type: NodePort --- apiVersion: v1 @@ -30,15 +29,14 @@ metadata: role: follower name: redis-cluster-followers spec: - clusterIP: 10.108.109.134 ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-cluster-follower redis_setup_type: cluster role: follower -# type: LoadBalancer + # type: LoadBalancer type: NodePort diff --git a/example/v1beta2/external_service/replication-svc.yaml b/example/v1beta2/external_service/replication-svc.yaml index 5e412de80..0b63b380c 100644 --- a/example/v1beta2/external_service/replication-svc.yaml +++ b/example/v1beta2/external_service/replication-svc.yaml @@ -9,13 +9,13 @@ metadata: name: redis-replication spec: ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-replication redis_setup_type: replication role: replication -# type: LoadBalancer + # type: LoadBalancer type: NodePort diff --git a/example/v1beta2/external_service/standalone-svc.yaml b/example/v1beta2/external_service/standalone-svc.yaml index df4efe038..2c8c8aec5 100644 --- a/example/v1beta2/external_service/standalone-svc.yaml +++ b/example/v1beta2/external_service/standalone-svc.yaml @@ -9,13 +9,13 @@ metadata: name: redis-standalone spec: ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 selector: app: redis-standalone redis_setup_type: standalone role: standalone -# type: LoadBalancer + # type: LoadBalancer type: NodePort diff --git a/example/v1beta2/password_protected/secret.yaml b/example/v1beta2/password_protected/secret.yaml index 2a91c0d81..cf1cf0a6a 100644 --- a/example/v1beta2/password_protected/secret.yaml +++ b/example/v1beta2/password_protected/secret.yaml @@ -1,8 +1,8 @@ ---- +--- apiVersion: v1 kind: Secret metadata: name: redis-secret data: - password: T3BzdHJlZUAxMjM0Cg== -type: Opaque \ No newline at end of file + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque diff --git a/example/v1beta2/redis-cluster.yaml b/example/v1beta2/redis-cluster.yaml index 87b308e3a..4b8fb65f4 100644 --- a/example/v1beta2/redis-cluster.yaml +++ b/example/v1beta2/redis-cluster.yaml @@ -20,11 +20,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -36,26 +36,26 @@ spec: limits: cpu: 100m memory: 128Mi -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username -# redisLeader: -# redisConfig: -# additionalRedisConfig: redis-external-config -# redisFollower: -# redisConfig: -# additionalRedisConfig: redis-external-config + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username + # redisLeader: + # redisConfig: + # additionalRedisConfig: redis-external-config + # redisFollower: + # redisConfig: + # additionalRedisConfig: redis-external-config storage: volumeClaimTemplate: spec: @@ -71,8 +71,8 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: - # kubernetes.io/hostname: minikube - # priorityClassName: - # Affinity: - # Tolerations: [] + # nodeSelector: + # kubernetes.io/hostname: minikube + # priorityClassName: + # Affinity: + # Tolerations: [] diff --git a/example/v1beta2/redis-replication.yaml b/example/v1beta2/redis-replication.yaml index e7a11022e..1f4ca8194 100644 --- a/example/v1beta2/redis-replication.yaml +++ b/example/v1beta2/redis-replication.yaml @@ -2,7 +2,7 @@ apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 podSecurityContext: @@ -10,7 +10,7 @@ spec: fsGroup: 1000 # redisConfig: # additionalRedisConfig: redis-external-config - kubernetesConfig: + kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent resources: @@ -23,8 +23,8 @@ spec: redisSecret: name: redis-secret key: password - # imagePullSecrets: - # - name: regcred + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -36,20 +36,20 @@ spec: limits: cpu: 100m memory: 128Mi -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username storage: volumeClaimTemplate: spec: @@ -57,4 +57,4 @@ spec: accessModes: ["ReadWriteOnce"] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/example/v1beta2/redis-sentinel.yaml b/example/v1beta2/redis-sentinel.yaml index e53105d6e..771e66d77 100644 --- a/example/v1beta2/redis-sentinel.yaml +++ b/example/v1beta2/redis-sentinel.yaml @@ -11,10 +11,10 @@ spec: pdb: enabled: false minAvailable: 1 - redisSentinelConfig: - redisReplicationName : redis-replication + redisSentinelConfig: + redisReplicationName: redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.12 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/redis-standalone.yaml b/example/v1beta2/redis-standalone.yaml index 27e2b5e7f..11e903441 100644 --- a/example/v1beta2/redis-standalone.yaml +++ b/example/v1beta2/redis-standalone.yaml @@ -8,7 +8,7 @@ spec: # additionalRedisConfig: redis-external-config podSecurityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent @@ -19,11 +19,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -35,20 +35,20 @@ spec: limits: cpu: 100m memory: 128Mi -# Environment Variables for Redis Exporter - # env: - # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - # value: "true" - # - name: UI_PROPERTIES_FILE_NAME - # valueFrom: - # configMapKeyRef: - # name: game-demo - # key: ui_properties_file_name - # - name: SECRET_USERNAME - # valueFrom: - # secretKeyRef: - # name: mysecret - # key: username + # Environment Variables for Redis Exporter + # env: + # - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + # value: "true" + # - name: UI_PROPERTIES_FILE_NAME + # valueFrom: + # configMapKeyRef: + # name: game-demo + # key: ui_properties_file_name + # - name: SECRET_USERNAME + # valueFrom: + # secretKeyRef: + # name: mysecret + # key: username storage: volumeClaimTemplate: spec: @@ -57,9 +57,9 @@ spec: resources: requests: storage: 1Gi - # nodeSelector: - # kubernetes.io/hostname: minikube - # podSecurityContext: {} - # priorityClassName: - # affinity: - # Tolerations: [] + # nodeSelector: + # kubernetes.io/hostname: minikube + # podSecurityContext: {} + # priorityClassName: + # affinity: + # Tolerations: [] diff --git a/example/v1beta2/redis_monitoring/clusterd.yaml b/example/v1beta2/redis_monitoring/clusterd.yaml index 8ba5e9ea5..82a6659f2 100644 --- a/example/v1beta2/redis_monitoring/clusterd.yaml +++ b/example/v1beta2/redis_monitoring/clusterd.yaml @@ -33,4 +33,4 @@ spec: resources: requests: storage: 1Gi - # storageClassName: standard + # storageClassName: standard diff --git a/example/v1beta2/redis_sentinel/sentinel.yaml b/example/v1beta2/redis_sentinel/sentinel.yaml index 78f838906..389bfe1a4 100644 --- a/example/v1beta2/redis_sentinel/sentinel.yaml +++ b/example/v1beta2/redis_sentinel/sentinel.yaml @@ -8,10 +8,10 @@ spec: podSecurityContext: runAsUser: 1000 fsGroup: 1000 - redisSentinelConfig: - redisReplicationName : redis-replication + redisSentinelConfig: + redisReplicationName: redis-replication kubernetesConfig: - image: quay.io/opstree/redis-sentinel:v7.0.12 + image: quay.io/opstree/redis-sentinel:v7.0.12 imagePullPolicy: IfNotPresent resources: requests: diff --git a/example/v1beta2/sidecar_features/configmap.yaml b/example/v1beta2/sidecar_features/configmap.yaml index 1dbc1c582..b6bc927f1 100644 --- a/example/v1beta2/sidecar_features/configmap.yaml +++ b/example/v1beta2/sidecar_features/configmap.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -6,4 +7,3 @@ metadata: app: myapplication data: my-key: my-value - \ No newline at end of file diff --git a/example/v1beta2/sidecar_features/sidecar.yaml b/example/v1beta2/sidecar_features/sidecar.yaml index 7b3b1f4f7..bd9ae03ee 100644 --- a/example/v1beta2/sidecar_features/sidecar.yaml +++ b/example/v1beta2/sidecar_features/sidecar.yaml @@ -16,11 +16,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -38,11 +38,11 @@ spec: imagePullPolicy: Always command: ["/bin/sh", "-c", "sleep 50000"] mountPath: - - name: test - mountPath: /home + - name: test + mountPath: /home ports: - - name: port - containerPort: 9000 + - name: port + containerPort: 9000 storage: volumeClaimTemplate: @@ -57,4 +57,4 @@ spec: - name: test configMap: name: example-configmap - terminationGracePeriodSeconds: 20 #custom terimationgraceperiodseconds + terminationGracePeriodSeconds: 20 # custom terimationgraceperiodseconds diff --git a/example/v1beta2/tls_enabled/redis-cluster.yaml b/example/v1beta2/tls_enabled/redis-cluster.yaml index 7147edd43..cae718b7b 100644 --- a/example/v1beta2/tls_enabled/redis-cluster.yaml +++ b/example/v1beta2/tls_enabled/redis-cluster.yaml @@ -55,4 +55,4 @@ spec: accessModes: ["ReadWriteOnce"] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/example/v1beta2/tls_enabled/redis-replication.yaml b/example/v1beta2/tls_enabled/redis-replication.yaml index 743e6d7fb..72e5c3f22 100644 --- a/example/v1beta2/tls_enabled/redis-replication.yaml +++ b/example/v1beta2/tls_enabled/redis-replication.yaml @@ -1,3 +1,4 @@ +# yamllint disable-line rule:line-length # Examples of creating a valid TLS certificate can be found at ./config/certmanager via Cert-manager --- apiVersion: redis.redis.opstreelabs.in/v1beta2 diff --git a/example/v1beta2/tls_enabled/redis-standalone.yaml b/example/v1beta2/tls_enabled/redis-standalone.yaml index ca30a243c..64d85061b 100644 --- a/example/v1beta2/tls_enabled/redis-standalone.yaml +++ b/example/v1beta2/tls_enabled/redis-standalone.yaml @@ -1,3 +1,4 @@ +# yamllint disable-line rule:line-length # Examples of creating a valid TLS certificate can be found at ./config/certmanager via Cert-manager --- apiVersion: redis.redis.opstreelabs.in/v1beta2 diff --git a/example/v1beta2/upgrade-strategy/replication.yaml b/example/v1beta2/upgrade-strategy/replication.yaml index 834b2e186..ae7678829 100644 --- a/example/v1beta2/upgrade-strategy/replication.yaml +++ b/example/v1beta2/upgrade-strategy/replication.yaml @@ -8,7 +8,6 @@ spec: kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent - type: OnDelete # type: RollingUpdate podSecurityContext: runAsUser: 1000 diff --git a/example/v1beta2/upgrade-strategy/standalone.yaml b/example/v1beta2/upgrade-strategy/standalone.yaml index e8e1aacbe..0d514a497 100644 --- a/example/v1beta2/upgrade-strategy/standalone.yaml +++ b/example/v1beta2/upgrade-strategy/standalone.yaml @@ -9,7 +9,7 @@ spec: imagePullPolicy: IfNotPresent updateStrategy: type: OnDelete -# type: RollingUpdate + # type: RollingUpdate podSecurityContext: runAsUser: 1000 fsGroup: 1000 @@ -23,4 +23,4 @@ spec: storage: 1Gi redisExporter: enabled: false - image: quay.io/opstree/redis-exporter:v1.44.0 \ No newline at end of file + image: quay.io/opstree/redis-exporter:v1.44.0 diff --git a/example/v1beta2/volume_mount/configmap.yaml b/example/v1beta2/volume_mount/configmap.yaml index eb5501a23..b6bc927f1 100644 --- a/example/v1beta2/volume_mount/configmap.yaml +++ b/example/v1beta2/volume_mount/configmap.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: ConfigMap metadata: @@ -5,4 +6,4 @@ metadata: labels: app: myapplication data: - my-key: my-value \ No newline at end of file + my-key: my-value diff --git a/example/v1beta2/volume_mount/redis-cluster.yaml b/example/v1beta2/volume_mount/redis-cluster.yaml index a7f069d63..15207de89 100644 --- a/example/v1beta2/volume_mount/redis-cluster.yaml +++ b/example/v1beta2/volume_mount/redis-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -22,8 +23,8 @@ spec: redisSecret: name: redis-secret key: password - # imagePullSecrets: - # - name: regcred + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -49,11 +50,11 @@ spec: resources: requests: storage: 1Gi - volumemount: + volumeMount: volume: - name: example-config configMap: name: example-configmap - mount: + mountPath: - mountPath: /config - name: example-config \ No newline at end of file + name: example-config diff --git a/example/v1beta2/volume_mount/redis-replication.yaml b/example/v1beta2/volume_mount/redis-replication.yaml index 4c081689c..d78030ffe 100644 --- a/example/v1beta2/volume_mount/redis-replication.yaml +++ b/example/v1beta2/volume_mount/redis-replication.yaml @@ -1,7 +1,8 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 # redisConfig: @@ -16,11 +17,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -40,11 +41,11 @@ spec: resources: requests: storage: 1Gi - volumemount: + volumeMount: volume: - name: example-config configMap: name: example-configmap - mount: + mountPath: - mountPath: /config name: example-config diff --git a/example/v1beta2/volume_mount/redis-standalone.yaml b/example/v1beta2/volume_mount/redis-standalone.yaml index cbb1a96da..c89d8aa61 100644 --- a/example/v1beta2/volume_mount/redis-standalone.yaml +++ b/example/v1beta2/volume_mount/redis-standalone.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: @@ -15,11 +16,11 @@ spec: limits: cpu: 101m memory: 128Mi - # redisSecret: - # name: redis-secret - # key: password - # imagePullSecrets: - # - name: regcred + # redisSecret: + # name: redis-secret + # key: password + # imagePullSecrets: + # - name: regcred redisExporter: enabled: false image: quay.io/opstree/redis-exporter:v1.44.0 @@ -39,11 +40,11 @@ spec: resources: requests: storage: 1Gi - volumemount: + volumeMount: volume: - name: example-config configMap: name: example-configmap - mount: + mountPath: - mountPath: /config name: example-config From 89c2daa647c851adb1276cf771e7041761be2eae Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 29 Oct 2023 02:01:26 +0530 Subject: [PATCH 043/203] test : Add Unit Test for redis-standalone.yaml (#683) * standalone-unit-test Signed-off-by: Shubham Gupta * more test Signed-off-by: Shubham Gupta * Add test Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- k8sutils/redis-standalone_test.go | 308 +++++++++++++++++++++++++++ k8sutils/statefulset.go | 1 - tests/testdata/redis-standalone.yaml | 140 ++++++++++++ 3 files changed, 448 insertions(+), 1 deletion(-) create mode 100644 k8sutils/redis-standalone_test.go create mode 100644 tests/testdata/redis-standalone.yaml diff --git a/k8sutils/redis-standalone_test.go b/k8sutils/redis-standalone_test.go new file mode 100644 index 000000000..394f03845 --- /dev/null +++ b/k8sutils/redis-standalone_test.go @@ -0,0 +1,308 @@ +package k8sutils + +import ( + "os" + "path/filepath" + "testing" + + common "github.com/OT-CONTAINER-KIT/redis-operator/api" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/utils/pointer" +) + +func Test_generateRedisStandaloneParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") + expected := statefulSetParameters{ + Replicas: pointer.Int32(1), + ClusterMode: false, + NodeConfVolume: false, + // Metadata: metav1.ObjectMeta{ + // Name: "redis-standalone", + // Namespace: "redis", + // Labels: map[string]string{ + // "app": "redis-standalone"}, + // Annotations: map[string]string{ + // "opstreelabs.in.redis": "true"}, + // }, + NodeSelector: map[string]string{ + "node-role.kubernetes.io/infra": "worker"}, + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + FSGroup: pointer.Int64(1000), + }, + PriorityClassName: "high-priority", + Affinity: &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"worker"}, + }, + }, + }, + }, + }, + }, + }, + Tolerations: &[]corev1.Toleration{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + PersistentVolumeClaim: corev1.PersistentVolumeClaim{ + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: pointer.String("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + EnableMetrics: true, + ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, + ExternalConfig: pointer.String("redis-external-config"), + ServiceAccountName: pointer.String("redis-sa"), + TerminationGracePeriodSeconds: pointer.Int64(30), + IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.Redis{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisStandaloneParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} + +func Test_generateRedisStandaloneContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") + expected := containerParameters{ + Image: "quay.io/opstree/redis:v7.0.12", + ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(1000), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + }, + RedisExporterImage: "quay.io/opstree/redis-exporter:v1.44.0", + RedisExporterImagePullPolicy: corev1.PullPolicy("Always"), + RedisExporterResources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + RedisExporterEnv: &[]corev1.EnvVar{ + { + Name: "REDIS_EXPORTER_INCL_SYSTEM_METRICS", + Value: "true", + }, + { + Name: "UI_PROPERTIES_FILE_NAME", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "game-demo", + }, + Key: "ui_properties_file_name", + }, + }, + }, + { + Name: "SECRET_USERNAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "mysecret", + }, + Key: "username", + }, + }, + }, + }, + Role: "standalone", + EnabledPassword: pointer.Bool(true), + SecretName: pointer.String("redis-secret"), + SecretKey: pointer.String("password"), + PersistenceEnabled: pointer.Bool(true), + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.key", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-cert", + }, + }, + }, + ACLConfig: &redisv1beta2.ACLConfig{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "acl-secret", + }, + }, + EnvVars: &[]corev1.EnvVar{ + { + Name: "CUSTOM_ENV_VAR_1", + Value: "custom_value_1", + }, + { + Name: "CUSTOM_ENV_VAR_2", + Value: "custom_value_2", + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.Redis{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisStandaloneContainerParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} + +func Test_generateRedisStandaloneInitContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") + expected := initContainerParameters{ + Enabled: pointer.Bool(true), + Image: "quay.io/opstree/redis-operator-restore:latest", + ImagePullPolicy: corev1.PullPolicy("Always"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + Role: "standalone", + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Arguments: []string{"--restore-from", "redis-standalone-restore"}, + PersistenceEnabled: pointer.Bool(true), + AdditionalEnvVariable: &[]corev1.EnvVar{ + { + Name: "CLUSTER_NAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAME", + }, + }, + }, + { + Name: "CLUSTER_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAMESPACE", + }, + }, + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.Redis{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisStandaloneInitContainerParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index e63b333b6..4145a7406 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -44,7 +44,6 @@ type statefulSetParameters struct { ServiceAccountName *string UpdateStrategy appsv1.StatefulSetUpdateStrategy RecreateStatefulSet bool - InitContainers *[]redisv1beta2.InitContainer TerminationGracePeriodSeconds *int64 IgnoreAnnotations []string } diff --git a/tests/testdata/redis-standalone.yaml b/tests/testdata/redis-standalone.yaml new file mode 100644 index 000000000..a3b351259 --- /dev/null +++ b/tests/testdata/redis-standalone.yaml @@ -0,0 +1,140 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone + namespace: redis + labels: + app: redis-standalone + annotations: + opstreelabs.in/redis: "true" +spec: + redisConfig: + additionalRedisConfig: redis-external-config + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + add: ["NET_BIND_SERVICE"] + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: mysecret + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + ignoreAnnotations: + - "opstreelabs.in/ignore" + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + value: "true" + - name: UI_PROPERTIES_FILE_NAME + valueFrom: + configMapKeyRef: + name: game-demo + key: ui_properties_file_name + - name: SECRET_USERNAME + valueFrom: + secretKeyRef: + name: mysecret + key: username + storage: + volumeClaimTemplate: + spec: + storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumeMount: + volume: + - name: example-config + configMap: + name: example-configmap + mountPath: + - mountPath: /config + name: example-config + nodeSelector: + node-role.kubernetes.io/infra: worker + priorityClassName: high-priority + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/infra + operator: In + values: + - worker + tolerations: + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoExecute" + serviceAccountName: redis-sa + terminationGracePeriodSeconds: 30 + acl: + secret: + secretName: acl-secret + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + initContainer: + enabled: true + image: quay.io/opstree/redis-operator-restore:latest + imagePullPolicy: Always + command: ["/bin/bash", "-c", "/app/restore.bash"] + args: ["--restore-from", "redis-standalone-restore"] + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: CLUSTER_NAME + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAME + - name: CLUSTER_NAMESPACE + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAMESPACE From f7e6a28ade6a1b192e7127e94e437fbf1fac962a Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 29 Oct 2023 18:17:42 +0530 Subject: [PATCH 044/203] makefile : Add Target to run e2e Test (#685) * makefile targets for e2e Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- Makefile | 18 +++++++++++++++++- tests/_config/kind-config.yaml | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ad9403426..aed1dd5da 100644 --- a/Makefile +++ b/Makefile @@ -132,4 +132,20 @@ verify-codegen: codegen @git --no-pager diff -- . @echo 'If this test fails, it is because the git diff is non-empty after running "make codegen".' >&2 @echo 'To correct this, locally run "make codegen", commit the changes, and re-run tests.' >&2 - @git diff --quiet --exit-code -- . \ No newline at end of file + @git diff --quiet --exit-code -- . + +.PHONY: install-kuttl +install-kuttl: + curl -L https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64 -o $(shell pwd)/bin/kuttl + chmod +x $(shell pwd)/bin/kuttl + +.PHONY: e2e-kind-setup +e2e-kind-setup: + docker build -t redis-operator:e2e -f Dockerfile . + kind create cluster --config tests/_config/kind-config.yaml + kind load docker-image redis-operator:e2e --name kind + make deploy IMG=redis-operator:e2e + +.PHONY: e2e-test +e2e-test: e2e-kind-setup install-kuttl + $(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml \ No newline at end of file diff --git a/tests/_config/kind-config.yaml b/tests/_config/kind-config.yaml index 752e993cd..da75a970a 100644 --- a/tests/_config/kind-config.yaml +++ b/tests/_config/kind-config.yaml @@ -1,5 +1,6 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 +name: kind nodes: - role: control-plane - role: worker From 520d3a29bd3f89ffcafea533fe9950d9dc167eba Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 6 Nov 2023 21:12:27 +0800 Subject: [PATCH 045/203] test: add test for redisreplication/redissentinel/rediscluster (#687) * ut for redis replication Signed-off-by: drivebyer * ut for redis sentinel Signed-off-by: drivebyer * ut for redis cluster Signed-off-by: drivebyer * remove useless field Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/redis-cluster.go | 1 - k8sutils/redis-cluster_test.go | 514 ++++++++++++++++++++++++++ k8sutils/redis-replication_test.go | 300 +++++++++++++++ k8sutils/redis-sentinel.go | 1 - k8sutils/redis-sentinel_test.go | 247 +++++++++++++ k8sutils/statefulset.go | 1 - tests/testdata/redis-cluster.yaml | 177 +++++++++ tests/testdata/redis-replication.yaml | 141 +++++++ tests/testdata/redis-sentinel.yaml | 120 ++++++ 9 files changed, 1499 insertions(+), 3 deletions(-) create mode 100644 k8sutils/redis-cluster_test.go create mode 100644 k8sutils/redis-replication_test.go create mode 100644 k8sutils/redis-sentinel_test.go create mode 100644 tests/testdata/redis-cluster.yaml create mode 100644 tests/testdata/redis-replication.yaml create mode 100644 tests/testdata/redis-sentinel.yaml diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index f12c5bd84..d3a523cc2 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -27,7 +27,6 @@ type RedisClusterService struct { // generateRedisClusterParams generates Redis cluster information func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, externalConfig *string, params RedisClusterSTS) statefulSetParameters { res := statefulSetParameters{ - Metadata: cr.ObjectMeta, Replicas: &replicas, ClusterMode: true, NodeConfVolume: cr.Spec.Storage.NodeConfVolume, diff --git a/k8sutils/redis-cluster_test.go b/k8sutils/redis-cluster_test.go new file mode 100644 index 000000000..2e1d1ddb3 --- /dev/null +++ b/k8sutils/redis-cluster_test.go @@ -0,0 +1,514 @@ +package k8sutils + +import ( + "os" + "path/filepath" + "testing" + + common "github.com/OT-CONTAINER-KIT/redis-operator/api" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/utils/pointer" +) + +func Test_generateRedisClusterParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-cluster.yaml") + + expectedLeaderSTS := statefulSetParameters{ + Replicas: pointer.Int32(3), + ClusterMode: true, + NodeConfVolume: true, + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + FSGroup: pointer.Int64(1000), + }, + PriorityClassName: "high-priority", + Affinity: &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"redisLeader"}, + }, + }, + }, + }, + }, + }, + }, + Tolerations: &[]corev1.Toleration{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + PersistentVolumeClaim: corev1.PersistentVolumeClaim{ + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: pointer.String("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + NodeConfPersistentVolumeClaim: corev1.PersistentVolumeClaim{ + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: pointer.String("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + EnableMetrics: true, + ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, + ExternalConfig: pointer.String("redis-external-config-leader"), + ServiceAccountName: pointer.String("redis-sa"), + IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, + } + expectedFollowerSTS := statefulSetParameters{ + Replicas: pointer.Int32(3), + ClusterMode: true, + NodeConfVolume: true, + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + FSGroup: pointer.Int64(1000), + }, + PriorityClassName: "high-priority", + Affinity: &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"redisFollower"}, + }, + }, + }, + }, + }, + }, + }, + Tolerations: &[]corev1.Toleration{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + PersistentVolumeClaim: corev1.PersistentVolumeClaim{ + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: pointer.String("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + NodeConfPersistentVolumeClaim: corev1.PersistentVolumeClaim{ + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: pointer.String("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + EnableMetrics: true, + ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, + ExternalConfig: pointer.String("redis-external-config-follower"), + ServiceAccountName: pointer.String("redis-sa"), + IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisCluster{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actualLeaderSTS := generateRedisClusterParams(input, *input.Spec.Size, input.Spec.RedisLeader.RedisConfig.AdditionalRedisConfig, RedisClusterSTS{ + RedisStateFulType: "leader", + ExternalConfig: input.Spec.RedisLeader.RedisConfig.AdditionalRedisConfig, + SecurityContext: input.Spec.RedisLeader.SecurityContext, + Affinity: input.Spec.RedisLeader.Affinity, + TerminationGracePeriodSeconds: input.Spec.RedisLeader.TerminationGracePeriodSeconds, + ReadinessProbe: input.Spec.RedisLeader.ReadinessProbe, + LivenessProbe: input.Spec.RedisLeader.LivenessProbe, + NodeSelector: input.Spec.RedisLeader.NodeSelector, + Tolerations: input.Spec.RedisLeader.Tolerations, + }) + assert.EqualValues(t, expectedLeaderSTS, actualLeaderSTS, "Expected %+v, got %+v", expectedLeaderSTS, actualLeaderSTS) + + actualFollowerSTS := generateRedisClusterParams(input, *input.Spec.Size, input.Spec.RedisFollower.RedisConfig.AdditionalRedisConfig, RedisClusterSTS{ + RedisStateFulType: "follower", + ExternalConfig: input.Spec.RedisFollower.RedisConfig.AdditionalRedisConfig, + SecurityContext: input.Spec.RedisFollower.SecurityContext, + Affinity: input.Spec.RedisFollower.Affinity, + TerminationGracePeriodSeconds: input.Spec.RedisFollower.TerminationGracePeriodSeconds, + ReadinessProbe: input.Spec.RedisFollower.ReadinessProbe, + LivenessProbe: input.Spec.RedisFollower.LivenessProbe, + NodeSelector: input.Spec.RedisFollower.NodeSelector, + Tolerations: input.Spec.RedisFollower.Tolerations, + }) + assert.EqualValues(t, expectedFollowerSTS, actualFollowerSTS, "Expected %+v, got %+v", expectedFollowerSTS, actualFollowerSTS) +} + +func Test_generateRedisClusterContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-cluster.yaml") + expectedLeaderContainer := containerParameters{ + Image: "quay.io/opstree/redis:v7.0.12", + ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(1000), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + }, + RedisExporterImage: "quay.io/opstree/redis-exporter:v1.44.0", + RedisExporterImagePullPolicy: corev1.PullPolicy("Always"), + RedisExporterResources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + RedisExporterEnv: &[]corev1.EnvVar{ + { + Name: "REDIS_EXPORTER_INCL_SYSTEM_METRICS", + Value: "true", + }, + { + Name: "UI_PROPERTIES_FILE_NAME", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "game-demo", + }, + Key: "ui_properties_file_name", + }, + }, + }, + { + Name: "SECRET_USERNAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "mysecret", + }, + Key: "username", + }, + }, + }, + }, + Role: "cluster", + EnabledPassword: pointer.Bool(true), + SecretName: pointer.String("redis-secret"), + SecretKey: pointer.String("password"), + PersistenceEnabled: pointer.Bool(true), + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.key", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-cert", + }, + }, + }, + ACLConfig: &redisv1beta2.ACLConfig{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "acl-secret", + }, + }, + EnvVars: &[]corev1.EnvVar{ + { + Name: "CUSTOM_ENV_VAR_1", + Value: "custom_value_1", + }, + { + Name: "CUSTOM_ENV_VAR_2", + Value: "custom_value_2", + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + expectedFollowerContainer := containerParameters{ + Image: "quay.io/opstree/redis:v7.0.12", + ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(1000), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + }, + RedisExporterImage: "quay.io/opstree/redis-exporter:v1.44.0", + RedisExporterImagePullPolicy: corev1.PullPolicy("Always"), + RedisExporterResources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + RedisExporterEnv: &[]corev1.EnvVar{ + { + Name: "REDIS_EXPORTER_INCL_SYSTEM_METRICS", + Value: "true", + }, + { + Name: "UI_PROPERTIES_FILE_NAME", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "game-demo", + }, + Key: "ui_properties_file_name", + }, + }, + }, + { + Name: "SECRET_USERNAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "mysecret", + }, + Key: "username", + }, + }, + }, + }, + Role: "cluster", + EnabledPassword: pointer.Bool(true), + SecretName: pointer.String("redis-secret"), + SecretKey: pointer.String("password"), + PersistenceEnabled: pointer.Bool(true), + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.key", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-cert", + }, + }, + }, + ACLConfig: &redisv1beta2.ACLConfig{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "acl-secret", + }, + }, + EnvVars: &[]corev1.EnvVar{ + { + Name: "CUSTOM_ENV_VAR_1", + Value: "custom_value_1", + }, + { + Name: "CUSTOM_ENV_VAR_2", + Value: "custom_value_2", + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisCluster{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actualLeaderContainer := generateRedisClusterContainerParams(input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe) + assert.EqualValues(t, expectedLeaderContainer, actualLeaderContainer, "Expected %+v, got %+v", expectedLeaderContainer, actualLeaderContainer) + + actualFollowerContainer := generateRedisClusterContainerParams(input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe) + assert.EqualValues(t, expectedFollowerContainer, actualFollowerContainer, "Expected %+v, got %+v", expectedFollowerContainer, actualFollowerContainer) +} + +func Test_generateRedisClusterInitContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-cluster.yaml") + expected := initContainerParameters{ + Enabled: pointer.Bool(true), + Image: "quay.io/opstree/redis-operator-restore:latest", + ImagePullPolicy: corev1.PullPolicy("Always"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + Role: "cluster", + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Arguments: []string{"--restore-from", "redis-cluster-restore"}, + PersistenceEnabled: pointer.Bool(true), + AdditionalEnvVariable: &[]corev1.EnvVar{ + { + Name: "CLUSTER_NAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAME", + }, + }, + }, + { + Name: "CLUSTER_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAMESPACE", + }, + }, + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisCluster{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisClusterInitContainerParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} diff --git a/k8sutils/redis-replication_test.go b/k8sutils/redis-replication_test.go new file mode 100644 index 000000000..8b4a2e7f9 --- /dev/null +++ b/k8sutils/redis-replication_test.go @@ -0,0 +1,300 @@ +package k8sutils + +import ( + "os" + "path/filepath" + "testing" + + common "github.com/OT-CONTAINER-KIT/redis-operator/api" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/utils/pointer" +) + +func Test_generateRedisReplicationParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") + expected := statefulSetParameters{ + Replicas: pointer.Int32(3), + ClusterMode: false, + NodeConfVolume: false, + NodeSelector: map[string]string{ + "node-role.kubernetes.io/infra": "worker"}, + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + FSGroup: pointer.Int64(1000), + }, + PriorityClassName: "high-priority", + Affinity: &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"worker"}, + }, + }, + }, + }, + }, + }, + }, + Tolerations: &[]corev1.Toleration{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + PersistentVolumeClaim: corev1.PersistentVolumeClaim{ + Spec: corev1.PersistentVolumeClaimSpec{ + StorageClassName: pointer.String("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + EnableMetrics: true, + ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, + ExternalConfig: pointer.String("redis-external-config"), + ServiceAccountName: pointer.String("redis-sa"), + TerminationGracePeriodSeconds: pointer.Int64(30), + IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisReplication{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisReplicationParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} + +func Test_generateRedisReplicationContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") + expected := containerParameters{ + Image: "quay.io/opstree/redis:v7.0.12", + ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(1000), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + }, + RedisExporterImage: "quay.io/opstree/redis-exporter:v1.44.0", + RedisExporterImagePullPolicy: corev1.PullPolicy("Always"), + RedisExporterResources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + RedisExporterEnv: &[]corev1.EnvVar{ + { + Name: "REDIS_EXPORTER_INCL_SYSTEM_METRICS", + Value: "true", + }, + { + Name: "UI_PROPERTIES_FILE_NAME", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "game-demo", + }, + Key: "ui_properties_file_name", + }, + }, + }, + { + Name: "SECRET_USERNAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "mysecret", + }, + Key: "username", + }, + }, + }, + }, + Role: "replication", + EnabledPassword: pointer.Bool(true), + SecretName: pointer.String("redis-secret"), + SecretKey: pointer.String("password"), + PersistenceEnabled: pointer.Bool(true), + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.key", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-cert", + }, + }, + }, + ACLConfig: &redisv1beta2.ACLConfig{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "acl-secret", + }, + }, + EnvVars: &[]corev1.EnvVar{ + { + Name: "CUSTOM_ENV_VAR_1", + Value: "custom_value_1", + }, + { + Name: "CUSTOM_ENV_VAR_2", + Value: "custom_value_2", + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisReplication{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisReplicationContainerParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} + +func Test_generateRedisReplicationInitContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") + expected := initContainerParameters{ + Enabled: pointer.Bool(true), + Image: "quay.io/opstree/redis-operator-restore:latest", + ImagePullPolicy: corev1.PullPolicy("Always"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + Role: "replication", + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Arguments: []string{"--restore-from", "redis-replication-restore"}, + PersistenceEnabled: pointer.Bool(true), + AdditionalEnvVariable: &[]corev1.EnvVar{ + { + Name: "CLUSTER_NAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAME", + }, + }, + }, + { + Name: "CLUSTER_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAMESPACE", + }, + }, + }, + }, + AdditionalVolume: []corev1.Volume{ + { + Name: "example-config", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "example-configmap", + }, + }, + }, + }, + }, + AdditionalMountPath: []corev1.VolumeMount{ + { + MountPath: "/config", + Name: "example-config", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisReplication{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisReplicationInitContainerParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index a4b7260ec..da39bd284 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -87,7 +87,6 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr func generateRedisSentinelParams(cr *redisv1beta2.RedisSentinel, replicas int32, externalConfig *string, affinity *corev1.Affinity) statefulSetParameters { res := statefulSetParameters{ - Metadata: cr.ObjectMeta, Replicas: &replicas, ClusterMode: false, NodeConfVolume: false, diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go new file mode 100644 index 000000000..883bc78d5 --- /dev/null +++ b/k8sutils/redis-sentinel_test.go @@ -0,0 +1,247 @@ +package k8sutils + +import ( + "context" + "os" + "path/filepath" + "testing" + + common "github.com/OT-CONTAINER-KIT/redis-operator/api" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/utils/pointer" +) + +func Test_generateRedisSentinelParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-sentinel.yaml") + expected := statefulSetParameters{ + Replicas: pointer.Int32(3), + ClusterMode: false, + NodeConfVolume: false, + NodeSelector: map[string]string{ + "node-role.kubernetes.io/infra": "worker"}, + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + FSGroup: pointer.Int64(1000), + }, + PriorityClassName: "high-priority", + Affinity: &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"worker"}, + }, + }, + }, + }, + }, + }, + }, + Tolerations: &[]corev1.Toleration{ + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoSchedule, + }, + { + Key: "node-role.kubernetes.io/infra", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + EnableMetrics: true, + ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, + ServiceAccountName: pointer.String("redis-sa"), + TerminationGracePeriodSeconds: pointer.Int64(30), + IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisSentinel{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisSentinelParams(input, *input.Spec.Size, nil, input.Spec.Affinity) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} + +func Test_generateRedisSentinelContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-sentinel.yaml") + expected := containerParameters{ + Image: "quay.io/opstree/redis:v7.0.12", + ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("101m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(1000), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + Add: []corev1.Capability{"NET_BIND_SERVICE"}, + }, + }, + RedisExporterImage: "quay.io/opstree/redis-exporter:v1.44.0", + RedisExporterImagePullPolicy: corev1.PullPolicy("Always"), + RedisExporterResources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + RedisExporterEnv: &[]corev1.EnvVar{ + { + Name: "REDIS_EXPORTER_INCL_SYSTEM_METRICS", + Value: "true", + }, + { + Name: "UI_PROPERTIES_FILE_NAME", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "game-demo", + }, + Key: "ui_properties_file_name", + }, + }, + }, + { + Name: "SECRET_USERNAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "mysecret", + }, + Key: "username", + }, + }, + }, + }, + Role: "sentinel", + EnabledPassword: pointer.Bool(true), + SecretName: pointer.String("redis-secret"), + SecretKey: pointer.String("password"), + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.key", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-cert", + }, + }, + }, + AdditionalEnvVariable: &[]corev1.EnvVar{}, + EnvVars: &[]corev1.EnvVar{ + { + Name: "CUSTOM_ENV_VAR_1", + Value: "custom_value_1", + }, + { + Name: "CUSTOM_ENV_VAR_2", + Value: "custom_value_2", + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisSentinel{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisSentinelContainerParams(context.TODO(), input, nil, nil) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} + +func Test_generateRedisSentinelInitContainerParams(t *testing.T) { + path := filepath.Join("..", "tests", "testdata", "redis-sentinel.yaml") + expected := initContainerParameters{ + Enabled: pointer.Bool(true), + Image: "quay.io/opstree/redis-operator-restore:latest", + ImagePullPolicy: corev1.PullPolicy("Always"), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + Role: "sentinel", + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Arguments: []string{"--restore-from", "redis-sentinel-restore"}, + AdditionalEnvVariable: &[]corev1.EnvVar{ + { + Name: "CLUSTER_NAME", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAME", + }, + }, + }, + { + Name: "CLUSTER_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "env-secrets", + }, + Key: "CLUSTER_NAMESPACE", + }, + }, + }, + }, + } + + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("Failed to read file %s: %v", path, err) + } + + input := &redisv1beta2.RedisSentinel{} + err = yaml.UnmarshalStrict(data, input) + if err != nil { + t.Fatalf("Failed to unmarshal file %s: %v", path, err) + } + + actual := generateRedisSentinelInitContainerParams(input) + assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) +} diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 4145a7406..16e76395c 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -30,7 +30,6 @@ type statefulSetParameters struct { Replicas *int32 ClusterMode bool NodeConfVolume bool - Metadata metav1.ObjectMeta NodeSelector map[string]string PodSecurityContext *corev1.PodSecurityContext PriorityClassName string diff --git a/tests/testdata/redis-cluster.yaml b/tests/testdata/redis-cluster.yaml new file mode 100644 index 000000000..b107d6508 --- /dev/null +++ b/tests/testdata/redis-cluster.yaml @@ -0,0 +1,177 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-cluster + namespace: redis + labels: + app: redis-cluster + annotations: + opstreelabs.in/redis: "true" +spec: + clusterSize: 3 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: mysecret + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + ignoreAnnotations: + - "opstreelabs.in/ignore" + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisLeader: + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + readOnlyRootFilesystem: true + capabilities: + drop: [ "ALL" ] + add: [ "NET_BIND_SERVICE" ] + replicas: 3 + redisConfig: + additionalRedisConfig: redis-external-config-leader + tolerations: + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoExecute" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/infra + operator: In + values: + - redisLeader + redisFollower: + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + readOnlyRootFilesystem: true + capabilities: + drop: [ "ALL" ] + add: [ "NET_BIND_SERVICE" ] + replicas: 3 + redisConfig: + additionalRedisConfig: redis-external-config-follower + tolerations: + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoExecute" + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/infra + operator: In + values: + - redisFollower + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + value: "true" + - name: UI_PROPERTIES_FILE_NAME + valueFrom: + configMapKeyRef: + name: game-demo + key: ui_properties_file_name + - name: SECRET_USERNAME + valueFrom: + secretKeyRef: + name: mysecret + key: username + persistenceEnabled: true + storage: + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumeClaimTemplate: + spec: + storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumeMount: + volume: + - name: example-config + configMap: + name: example-configmap + mountPath: + - mountPath: /config + name: example-config + priorityClassName: high-priority + serviceAccountName: redis-sa + acl: + secret: + secretName: acl-secret + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + initContainer: + enabled: true + image: quay.io/opstree/redis-operator-restore:latest + imagePullPolicy: Always + command: ["/bin/bash", "-c", "/app/restore.bash"] + args: ["--restore-from", "redis-cluster-restore"] + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: CLUSTER_NAME + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAME + - name: CLUSTER_NAMESPACE + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAMESPACE \ No newline at end of file diff --git a/tests/testdata/redis-replication.yaml b/tests/testdata/redis-replication.yaml new file mode 100644 index 000000000..2f695bfe1 --- /dev/null +++ b/tests/testdata/redis-replication.yaml @@ -0,0 +1,141 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-replication + namespace: redis + labels: + app: redis-replication + annotations: + opstreelabs.in/redis: "true" +spec: + clusterSize: 3 + redisConfig: + additionalRedisConfig: redis-external-config + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + add: ["NET_BIND_SERVICE"] + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: mysecret + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + ignoreAnnotations: + - "opstreelabs.in/ignore" + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + value: "true" + - name: UI_PROPERTIES_FILE_NAME + valueFrom: + configMapKeyRef: + name: game-demo + key: ui_properties_file_name + - name: SECRET_USERNAME + valueFrom: + secretKeyRef: + name: mysecret + key: username + storage: + volumeClaimTemplate: + spec: + storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + volumeMount: + volume: + - name: example-config + configMap: + name: example-configmap + mountPath: + - mountPath: /config + name: example-config + nodeSelector: + node-role.kubernetes.io/infra: worker + priorityClassName: high-priority + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/infra + operator: In + values: + - worker + tolerations: + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoExecute" + serviceAccountName: redis-sa + terminationGracePeriodSeconds: 30 + acl: + secret: + secretName: acl-secret + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + initContainer: + enabled: true + image: quay.io/opstree/redis-operator-restore:latest + imagePullPolicy: Always + command: ["/bin/bash", "-c", "/app/restore.bash"] + args: ["--restore-from", "redis-replication-restore"] + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: CLUSTER_NAME + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAME + - name: CLUSTER_NAMESPACE + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAMESPACE diff --git a/tests/testdata/redis-sentinel.yaml b/tests/testdata/redis-sentinel.yaml new file mode 100644 index 000000000..40bf80154 --- /dev/null +++ b/tests/testdata/redis-sentinel.yaml @@ -0,0 +1,120 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-sentinel + namespace: redis + labels: + app: redis-sentinel + annotations: + opstreelabs.in/redis: "true" +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + runAsNonRoot: true + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + add: ["NET_BIND_SERVICE"] + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: + - name: mysecret + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + ignoreAnnotations: + - "opstreelabs.in/ignore" + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS + value: "true" + - name: UI_PROPERTIES_FILE_NAME + valueFrom: + configMapKeyRef: + name: game-demo + key: ui_properties_file_name + - name: SECRET_USERNAME + valueFrom: + secretKeyRef: + name: mysecret + key: username + nodeSelector: + node-role.kubernetes.io/infra: worker + priorityClassName: high-priority + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/infra + operator: In + values: + - worker + tolerations: + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoSchedule" + - key: "node-role.kubernetes.io/infra" + operator: "Exists" + effect: "NoExecute" + serviceAccountName: redis-sa + terminationGracePeriodSeconds: 30 + TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: redis-tls-cert + env: + - name: CUSTOM_ENV_VAR_1 + value: "custom_value_1" + - name: CUSTOM_ENV_VAR_2 + value: "custom_value_2" + initContainer: + enabled: true + image: quay.io/opstree/redis-operator-restore:latest + imagePullPolicy: Always + command: ["/bin/bash", "-c", "/app/restore.bash"] + args: ["--restore-from", "redis-sentinel-restore"] + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + env: + - name: CLUSTER_NAME + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAME + - name: CLUSTER_NAMESPACE + valueFrom: + secretKeyRef: + name: env-secrets + key: CLUSTER_NAMESPACE From 5bf8182035ce29cc303d1de5cc25d5a1fb937f3e Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 6 Nov 2023 22:00:24 +0800 Subject: [PATCH 046/203] adjust some log level (#686) Signed-off-by: drivebyer --- config/manager/manager.yaml | 2 +- controllers/redisreplication_controller.go | 2 +- k8sutils/poddisruption.go | 2 +- k8sutils/services.go | 2 +- k8sutils/statefulset.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index c355ec3d6..ca6be761b 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -33,7 +33,7 @@ spec: value: "false" args: - --leader-elect - - -zap-log-level=info + - -zap-log-level=debug - -enable-webhooks=false image: controller imagePullPolicy: Never diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index ab7efb08e..3a0eaae17 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -70,7 +70,7 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req // Check that the Leader and Follower are ready in redis replication if int32(redisReplicationInfo.Status.ReadyReplicas) != totalReplicas { - reqLogger.Info("Redis leader and follower nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas)), "Expected.Replicas", totalReplicas) + reqLogger.Info("Redis replication nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas)), "Expected.Replicas", totalReplicas) return ctrl.Result{RequeueAfter: time.Second * 60}, nil } diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 1e8cf8bee..00d1b7620 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -218,7 +218,7 @@ func GetPodDisruptionBudget(namespace string, pdb string) (*policyv1.PodDisrupti } pdbInfo, err := generateK8sClient().PolicyV1().PodDisruptionBudgets(namespace).Get(context.TODO(), pdb, getOpts) if err != nil { - logger.Info("Redis PodDisruptionBudget get action failed") + logger.V(1).Info("Redis PodDisruptionBudget get action failed") return nil, err } logger.V(1).Info("Redis PodDisruptionBudget get action was successful") diff --git a/k8sutils/services.go b/k8sutils/services.go index 3d6548b5b..c93dab87d 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -118,7 +118,7 @@ func getService(namespace string, service string) (*corev1.Service, error) { } serviceInfo, err := generateK8sClient().CoreV1().Services(namespace).Get(context.TODO(), service, getOpts) if err != nil { - logger.Info("Redis service get action is failed") + logger.V(1).Info("Redis service get action is failed") return nil, err } logger.V(1).Info("Redis service get action is successful") diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 16e76395c..7defa8e8f 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -672,7 +672,7 @@ func GetStatefulSet(namespace string, stateful string) (*appsv1.StatefulSet, err } statefulInfo, err := generateK8sClient().AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, getOpts) if err != nil { - logger.Info("Redis statefulset get action failed") + logger.V(1).Info("Redis statefulset get action failed") return nil, err } logger.V(1).Info("Redis statefulset get action was successful") From 1fd09c40a92538aeb8957b7d7a32762b08338c0b Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 13:53:16 +0530 Subject: [PATCH 047/203] fix logs (#690) Signed-off-by: Shubham Gupta --- controllers/rediscluster_controller.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 930f1fcae..91560bb36 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -120,7 +120,10 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request redisLeaderInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-leader") if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + if errors.IsNotFound(err) { + return ctrl.Result{RequeueAfter: time.Second * 60}, nil + } + return ctrl.Result{}, err } if int32(redisLeaderInfo.Status.ReadyReplicas) == leaderReplicas { @@ -151,7 +154,10 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } redisFollowerInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-follower") if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + if errors.IsNotFound(err) { + return ctrl.Result{RequeueAfter: time.Second * 60}, nil + } + return ctrl.Result{}, err } if leaderReplicas == 0 { From d0ce0668e8efb90af797a8d835f9e8d053dc23f4 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:10:24 +0530 Subject: [PATCH 048/203] push image (#691) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 03f8a1247..f055e3d55 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -9,8 +9,8 @@ on: env: APPLICATION_NAME: redis-operator QuayImageName: quay.io/opstree/redis-operator - APP_VERSION: "v0.15.1" - DOCKERFILE_PATH: '**/Dockerfile' + APP_VERSION: "v0.15.2" + DOCKERFILE_PATH: './Dockerfile' jobs: setup: @@ -28,7 +28,7 @@ jobs: with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.ACCESS_TOKEN }} + password: ${{ secrets.QUAY_PASSWORD }} build_multi_arch: needs: setup From 3531d5b00b4971e6de99bd96f20b399b792caaa7 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:21:27 +0530 Subject: [PATCH 049/203] Fix: Release Workflow (#692) * push image Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index f055e3d55..f0af80a38 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -13,7 +13,7 @@ env: DOCKERFILE_PATH: './Dockerfile' jobs: - setup: + release_image: if: github.event.pull_request.merged == true runs-on: ubuntu-latest steps: @@ -30,11 +30,6 @@ jobs: username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} - build_multi_arch: - needs: setup - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - name: Build and push multi-arch latest image uses: docker/build-push-action@v2 with: @@ -45,7 +40,7 @@ jobs: tags: ${{ env.QuayImageName }}:{{ env.APP_VERSION }}, ${{ env.QuayImageName }}:latest trivy_scan: - needs: [build_multi_arch] + needs: [release_image] runs-on: ubuntu-latest steps: - name: Checkout From 88252755e35d4e8b9c701825067bf65828fcee5f Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:35:36 +0530 Subject: [PATCH 050/203] fix (#693) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index f0af80a38..70348a011 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -24,7 +24,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Login to Quay.io - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: quay.io username: ${{ secrets.QUAY_USERNAME }} From 737dd02c310ed1acdcf4597c15045e38d0136313 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:48:36 +0530 Subject: [PATCH 051/203] qemu (#694) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 70348a011..164c273e2 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -23,6 +23,9 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Login to Quay.io uses: docker/login-action@v3 with: From a2e4b79314a7cefb4778923049612a46730989b9 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 23:09:40 +0530 Subject: [PATCH 052/203] fix (#695) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 164c273e2..3fa65f685 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -40,7 +40,7 @@ jobs: file: ${{ env.DOCKERFILE_PATH }} platforms: linux/amd64,linux/arm64 push: true - tags: ${{ env.QuayImageName }}:{{ env.APP_VERSION }}, ${{ env.QuayImageName }}:latest + tags: ${{ env.QuayImageName }}:${{ env.APP_VERSION }}, ${{ env.QuayImageName }}:latest trivy_scan: needs: [release_image] From 56996ef25e877f21fed21e587912ea1bb3f3ef75 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 8 Nov 2023 23:29:55 +0530 Subject: [PATCH 053/203] fix-env (#696) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index 3fa65f685..cefe56970 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -16,6 +16,7 @@ jobs: release_image: if: github.event.pull_request.merged == true runs-on: ubuntu-latest + environment: release-image steps: - name: Checkout uses: actions/checkout@v2 From 916779166e14be9b8f2484ed32b2263aff5922d1 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:45:57 +0530 Subject: [PATCH 054/203] test: Make Code Testable (#697) * testing-client Signed-off-by: Shubham Gupta * client_test.go Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * push Signed-off-by: Shubham Gupta * fix Client Signed-off-by: Shubham Gupta * fix Dockerfile Signed-off-by: Shubham Gupta * try fixing lint Signed-off-by: Shubham Gupta * fix ci Signed-off-by: Shubham Gupta * fix CI Signed-off-by: Shubham Gupta * fix CI Signed-off-by: Shubham Gupta * ignoree Signed-off-by: Shubham Gupta * change location Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 16 +++- .golangci.yml | 12 +-- Dockerfile | 1 + controllers/redis_controller.go | 10 ++- k8sutils/client.go | 34 ++++---- k8sutils/client_test.go | 78 ++++++++++++++++++ k8sutils/finalizer.go | 37 ++++++--- k8sutils/finalizers_test.go | 122 +++++++++++++++++++++++++++++ k8sutils/poddisruption.go | 28 ++++++- k8sutils/redis-sentinel.go | 7 +- k8sutils/redis.go | 23 +++++- k8sutils/secrets.go | 19 ++++- k8sutils/services.go | 21 ++++- k8sutils/statefulset.go | 33 ++++++-- k8sutils/status.go | 2 +- main.go | 21 ++++- mocks/log/logger.go | 5 ++ 17 files changed, 399 insertions(+), 70 deletions(-) create mode 100644 k8sutils/client_test.go create mode 100644 k8sutils/finalizers_test.go create mode 100644 mocks/log/logger.go diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 205339b76..f9322b585 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -64,7 +64,7 @@ jobs: verbose: true code_quality_golang_ci_lint: - needs: [gofmt, govet, gotest] + needs: [gofmt, govet] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -72,14 +72,24 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ env.GOLANG_VERSION }} + + - name: Download Go modules + run: go mod download + + - name: Check disk space + run: df -h + + - name: List Go module cache + run: ls -la $(go env GOPATH)/pkg/mod + - name: Run GolangCI-Lint uses: golangci/golangci-lint-action@v3 with: version: v1.54.0 - args: --timeout=5m0s ./... + args: --timeout=5m0s ./... --verbose --out-format=github-actions container_quality_dockerfile_lint: - needs: [gofmt, govet, gotest] + needs: [gofmt, govet] runs-on: ubuntu-latest steps: - name: Checkout code diff --git a/.golangci.yml b/.golangci.yml index 2a38a4fa8..48fc1e0d6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,11 +6,13 @@ linters-settings: gofmt: simplify: true -# linters: -# enable-all: true -# disable: -# - errcheck -# - tagliatelle +linters: + disable: + - errcheck + - tagliatelle + - ineffassign + - staticcheck + # Exclude the files that are causing the errors issues: exclude-rules: diff --git a/Dockerfile b/Dockerfile index 2bf6f87f0..f953b9f25 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ COPY main.go main.go COPY api/ api/ COPY controllers/ controllers/ COPY k8sutils/ k8sutils/ +COPY mocks/ mocks/ # Build ARG LDFLAGS="-s -w" diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index 9b07469f8..ee7224ade 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -25,6 +25,8 @@ import ( "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -32,8 +34,10 @@ import ( // RedisReconciler reconciles a Redis object type RedisReconciler struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme + K8sClient kubernetes.Interface + Dk8sClinet dynamic.Interface + Log logr.Logger + Scheme *runtime.Scheme } // Reconcile is part of the main kubernetes reconciliation loop which aims @@ -53,7 +57,7 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl reqLogger.Info("Found annotations redis.opstreelabs.in/skip-reconcile, so skipping reconcile") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } - if err = k8sutils.HandleRedisFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { return ctrl.Result{}, err } diff --git a/k8sutils/client.go b/k8sutils/client.go index 54078ab7e..a12031004 100644 --- a/k8sutils/client.go +++ b/k8sutils/client.go @@ -8,34 +8,28 @@ import ( "k8s.io/client-go/tools/clientcmd" ) -// generateK8sClient create client for kubernetes -func generateK8sClient() *kubernetes.Clientset { - config, err := generateK8sConfig() - if err != nil { - panic(err.Error()) - } - clientset, err := kubernetes.NewForConfig(config) +type K8sConfigProvider = func() (*rest.Config, error) + +// GenerateK8sClient create client for kubernetes +func GenerateK8sClient(configProvider K8sConfigProvider) (kubernetes.Interface, error) { + config, err := configProvider() if err != nil { - panic(err.Error()) + return nil, err } - return clientset + return kubernetes.NewForConfig(config) } -// generateK8sClient create Dynamic client for kubernetes -func generateK8sDynamicClient() dynamic.Interface { - config, err := generateK8sConfig() - if err != nil { - panic(err.Error()) - } - dynamicClientset, err := dynamic.NewForConfig(config) +// GenerateK8sClient create Dynamic client for kubernetes +func GenerateK8sDynamicClient(configProvider K8sConfigProvider) (dynamic.Interface, error) { + config, err := configProvider() if err != nil { - panic(err.Error()) + return nil, err } - return dynamicClientset + return dynamic.NewForConfig(config) } -// generateK8sConfig will load the kube config file -func generateK8sConfig() (*rest.Config, error) { +// GenerateK8sConfig will load the kube config file +func GenerateK8sConfig() (*rest.Config, error) { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() // if you want to change the loading rules (which files in which order), you can do so here configOverrides := &clientcmd.ConfigOverrides{} diff --git a/k8sutils/client_test.go b/k8sutils/client_test.go new file mode 100644 index 000000000..13618dc70 --- /dev/null +++ b/k8sutils/client_test.go @@ -0,0 +1,78 @@ +package k8sutils + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/client-go/rest" +) + +func mockK8sConfigProvider() (*rest.Config, error) { + return &rest.Config{}, nil +} +func mockInvalidK8sConfigProvider() (*rest.Config, error) { + return nil, errors.New("invalid configuration") +} + +func TestGenerateK8sClient(t *testing.T) { + tests := []struct { + name string + configProvider func() (*rest.Config, error) + wantErr bool + }{ + { + name: "valid config", + configProvider: mockK8sConfigProvider, + wantErr: false, + }, + { + name: "invalid config", + configProvider: mockInvalidK8sConfigProvider, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := GenerateK8sClient(tt.configProvider) + if tt.wantErr { + assert.Error(t, err, "GenerateK8sClient() should return an error for invalid config") + } else { + assert.NoError(t, err, "GenerateK8sClient() should not return an error for valid config") + assert.NotNil(t, client, "expected a non-nil Kubernetes client") + } + }) + } +} + +func TestGenerateK8sDynamicClient(t *testing.T) { + tests := []struct { + name string + configProvider func() (*rest.Config, error) + wantErr bool + }{ + { + name: "valid config", + configProvider: mockK8sConfigProvider, + wantErr: false, + }, + { + name: "invalid config", + configProvider: mockInvalidK8sConfigProvider, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client, err := GenerateK8sDynamicClient(tt.configProvider) + if tt.wantErr { + assert.Error(t, err, "GenerateK8sDynamicClient() should return an error for invalid config") + } else { + assert.NoError(t, err, "GenerateK8sDynamicClient() should not return an error for valid config") + assert.NotNil(t, client, "expected a non-nil Kubernetes client") + } + }) + } +} diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index e0e6c74bd..cb68d0c1b 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -2,12 +2,15 @@ package k8sutils import ( "context" + "fmt" "strconv" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + mockLog "github.com/OT-CONTAINER-KIT/redis-operator/mocks/log" "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) @@ -26,16 +29,15 @@ func finalizerLogger(namespace string, name string) logr.Logger { } // HandleRedisFinalizer finalize resource if instance is marked to be deleted -func HandleRedisFinalizer(cr *redisv1beta2.Redis, cl client.Client) error { - logger := finalizerLogger(cr.Namespace, RedisFinalizer) +func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisFinalizer) { - if err := finalizeRedisPVC(cr); err != nil { + if err := finalizeRedisPVC(k8sClient, logger, cr); err != nil { return err } controllerutil.RemoveFinalizer(cr, RedisFinalizer) - if err := cl.Update(context.TODO(), cr); err != nil { - logger.Error(err, "Could not remove finalizer "+RedisFinalizer) + if err := ctrlclient.Update(context.TODO(), cr); err != nil { + logger.Error(err, "Could not remove finalizer", "finalizer", RedisFinalizer) return err } } @@ -134,12 +136,11 @@ func AddRedisSentinelFinalizer(cr *redisv1beta2.RedisSentinel, cl client.Client) } // finalizeRedisPVC delete PVC -func finalizeRedisPVC(cr *redisv1beta2.Redis) error { - logger := finalizerLogger(cr.Namespace, RedisFinalizer) - PVCName := cr.Name + "-" + cr.Name + "-0" - err := generateK8sClient().CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) +func finalizeRedisPVC(client kubernetes.Interface, logger mockLog.LoggerInterface, cr *redisv1beta2.Redis) error { + PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) + err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { - logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) + logger.Error(err, "Could not delete Persistent Volume Claim", "PVCName", PVCName) return err } return nil @@ -148,10 +149,15 @@ func finalizeRedisPVC(cr *redisv1beta2.Redis) error { // finalizeRedisClusterPVC delete PVCs func finalizeRedisClusterPVC(cr *redisv1beta2.RedisCluster) error { logger := finalizerLogger(cr.Namespace, RedisClusterFinalizer) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } for _, role := range []string{"leader", "follower"} { for i := 0; i < int(cr.Spec.GetReplicaCounts(role)); i++ { PVCName := cr.Name + "-" + cr.Name + "-" + role + "-" + strconv.Itoa(i) - err := generateK8sClient().CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) + err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) return err @@ -160,7 +166,7 @@ func finalizeRedisClusterPVC(cr *redisv1beta2.RedisCluster) error { if cr.Spec.Storage.NodeConfVolume { for i := 0; i < int(cr.Spec.GetReplicaCounts(role)); i++ { PVCName := "node-conf" + cr.Name + "-" + role + "-" + strconv.Itoa(i) - err := generateK8sClient().CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) + err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) return err @@ -175,9 +181,14 @@ func finalizeRedisClusterPVC(cr *redisv1beta2.RedisCluster) error { // finalizeRedisReplicationPVC delete PVCs func finalizeRedisReplicationPVC(cr *redisv1beta2.RedisReplication) error { logger := finalizerLogger(cr.Namespace, RedisReplicationFinalizer) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } for i := 0; i < int(cr.Spec.GetReplicationCounts("replication")); i++ { PVCName := cr.Name + "-" + cr.Name + "-" + strconv.Itoa(i) - err := generateK8sClient().CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) + err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) return err diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go new file mode 100644 index 000000000..4ab301919 --- /dev/null +++ b/k8sutils/finalizers_test.go @@ -0,0 +1,122 @@ +package k8sutils + +import ( + "context" + "fmt" + "testing" + + "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr/testr" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sClientFake "k8s.io/client-go/kubernetes/fake" +) + +// func TestHandleRedisFinalizer(t *testing.T) { +// cr := &v1beta2.Redis{ +// TypeMeta: metav1.TypeMeta{ +// Kind: "Redis", +// APIVersion: "redis.opstreelabs.in/v1beta2", +// }, +// ObjectMeta: metav1.ObjectMeta{ +// Name: "test-redis", +// Namespace: "default", +// DeletionTimestamp: &metav1.Time{Time: time.Now()}, +// Finalizers: []string{RedisFinalizer}, +// }, +// } + +// // Create a fake controller-runtime client +// scheme := runtime.NewScheme() +// mockAddToScheme := v1beta2.SchemeBuilder.Register(&v1beta2.Redis{}, &v1beta2.RedisList{}).AddToScheme(scheme) +// utilruntime.Must(mockAddToScheme) + +// ctrlFakeclient := ctrlClientFake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(cr.DeepCopyObject()).Build() +// k8sFakeClient := k8sClientFake.NewSimpleClientset(cr.DeepCopyObject()) + +// logger := testr.New(t) +// // Run the HandleRedisFinalizer function +// err := HandleRedisFinalizer(ctrlFakeclient, k8sFakeClient, logger, cr) +// assert.NoError(t, err) + +// // Check if the PVC was deleted +// PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) +// _, err = k8sFakeClient.CoreV1().PersistentVolumeClaims(cr.Namespace).Get(context.TODO(), PVCName, metav1.GetOptions{}) +// assert.True(t, k8serrors.IsNotFound(err)) + +// // Check if the finalizer was removed +// updatedCR := &v1beta2.Redis{} +// err = ctrlFakeclient.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "test-redis"}, updatedCR) +// assert.NoError(t, err) +// assert.NotContains(t, updatedCR.GetFinalizers(), RedisFinalizer) + +// // Ensure the logger's Error method was not called +// //logger.AssertNotCalled(t, "Error", mock.Anything, mock.Anything, mock.Anything) +// } + +func TestFinalizeRedisPVC(t *testing.T) { + tests := []struct { + name string + existingPVC *corev1.PersistentVolumeClaim + expectError bool + errorExpected error + }{ + { + name: "PVC exists and is deleted successfully", + existingPVC: &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis-test-redis-0", + Namespace: "default", + }, + }, + expectError: false, + errorExpected: nil, + }, + { + name: "PVC does not exist and no error should be returned", + existingPVC: &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "nonexistent", + Namespace: "default", + }, + }, + expectError: false, + errorExpected: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + cr := &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis", + Namespace: "default", + }, + } + var k8sClient *k8sClientFake.Clientset + if tc.existingPVC != nil { + k8sClient = k8sClientFake.NewSimpleClientset(tc.existingPVC.DeepCopyObject()) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + err := finalizeRedisPVC(k8sClient, logger, cr) + if tc.expectError { + assert.Error(t, err) + assert.Equal(t, tc.errorExpected, err) + } else { + assert.NoError(t, err) + } + + // Verify that the PVC is not found in case of success or non-existent PVC + if !tc.expectError { + pvcName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) + _, err = k8sClient.CoreV1().PersistentVolumeClaims(cr.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{}) + assert.True(t, k8serrors.IsNotFound(err)) + } + }) + } +} diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 00d1b7620..2886f7ccb 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -177,7 +177,12 @@ func patchPodDisruptionBudget(storedPdb *policyv1.PodDisruptionBudget, newPdb *p // createPodDisruptionBudget is a method to create PodDisruptionBudgets in Kubernetes func createPodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudget) error { logger := pdbLogger(namespace, pdb.Name) - _, err := generateK8sClient().PolicyV1().PodDisruptionBudgets(namespace).Create(context.TODO(), pdb, metav1.CreateOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + _, err = client.PolicyV1().PodDisruptionBudgets(namespace).Create(context.TODO(), pdb, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis PodDisruptionBudget creation failed") return err @@ -189,7 +194,12 @@ func createPodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudg // updatePodDisruptionBudget is a method to update PodDisruptionBudgets in Kubernetes func updatePodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudget) error { logger := pdbLogger(namespace, pdb.Name) - _, err := generateK8sClient().PolicyV1().PodDisruptionBudgets(namespace).Update(context.TODO(), pdb, metav1.UpdateOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + _, err = client.PolicyV1().PodDisruptionBudgets(namespace).Update(context.TODO(), pdb, metav1.UpdateOptions{}) if err != nil { logger.Error(err, "Redis PodDisruptionBudget update failed") return err @@ -201,7 +211,12 @@ func updatePodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudg // deletePodDisruptionBudget is a method to delete PodDisruptionBudgets in Kubernetes func deletePodDisruptionBudget(namespace string, pdbName string) error { logger := pdbLogger(namespace, pdbName) - err := generateK8sClient().PolicyV1().PodDisruptionBudgets(namespace).Delete(context.TODO(), pdbName, metav1.DeleteOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + err = client.PolicyV1().PodDisruptionBudgets(namespace).Delete(context.TODO(), pdbName, metav1.DeleteOptions{}) if err != nil { logger.Error(err, "Redis PodDisruption deletion failed") return err @@ -213,10 +228,15 @@ func deletePodDisruptionBudget(namespace string, pdbName string) error { // GetPodDisruptionBudget is a method to get PodDisruptionBudgets in Kubernetes func GetPodDisruptionBudget(namespace string, pdb string) (*policyv1.PodDisruptionBudget, error) { logger := pdbLogger(namespace, pdb) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return nil, err + } getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("PodDisruptionBudget", "policy/v1"), } - pdbInfo, err := generateK8sClient().PolicyV1().PodDisruptionBudgets(namespace).Get(context.TODO(), pdb, getOpts) + pdbInfo, err := client.PolicyV1().PodDisruptionBudgets(namespace).Get(context.TODO(), pdb, getOpts) if err != nil { logger.V(1).Info("Redis PodDisruptionBudget get action failed") return nil, err diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index da39bd284..23d9ce509 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -283,6 +283,11 @@ func getSentinelEnvVariable(ctx context.Context, cr *redisv1beta2.RedisSentinel) func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSentinel) string { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) + dClient, err := GenerateK8sDynamicClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Failed to generate dynamic client") + return "" + } replicationName := cr.Spec.RedisSentinelConfig.RedisReplicationName replicationNamespace := cr.Namespace @@ -291,7 +296,7 @@ func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSent var realMasterPod string // Get Request on Dynamic Client - customObject, err := generateK8sDynamicClient().Resource(schema.GroupVersionResource{ + customObject, err := dClient.Resource(schema.GroupVersionResource{ Group: "redis.redis.opstreelabs.in", Version: "v1beta2", Resource: "redisreplications", diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 6973363f0..dda5aabef 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -27,7 +27,12 @@ type RedisDetails struct { // getRedisServerIP will return the IP of redis service func getRedisServerIP(redisInfo RedisDetails) string { logger := generateRedisManagerLogger(redisInfo.Namespace, redisInfo.PodName) - redisPod, err := generateK8sClient().CoreV1().Pods(redisInfo.Namespace).Get(context.TODO(), redisInfo.PodName, metav1.GetOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Error in getting k8s client") + return "" + } + redisPod, err := client.CoreV1().Pods(redisInfo.Namespace).Get(context.TODO(), redisInfo.PodName, metav1.GetOptions{}) if err != nil { logger.Error(err, "Error in getting redis pod IP") } @@ -358,7 +363,12 @@ func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) execErr bytes.Buffer ) logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - config, err := generateK8sConfig() + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return + } + config, err := GenerateK8sConfig() if err != nil { logger.Error(err, "Could not find pod to execute") return @@ -369,7 +379,7 @@ func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) return } - req := generateK8sClient().CoreV1().RESTClient().Post().Resource("pods").Name(podName).Namespace(cr.Namespace).SubResource("exec") + req := client.CoreV1().RESTClient().Post().Resource("pods").Name(podName).Namespace(cr.Namespace).SubResource("exec") req.VersionedParams(&corev1.PodExecOptions{ Container: pod.Spec.Containers[targetContainer].Name, Command: cmd, @@ -397,7 +407,12 @@ func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) // getContainerID will return the id of container from pod func getContainerID(cr *redisv1beta2.RedisCluster, podName string) (int, *corev1.Pod) { logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - pod, err := generateK8sClient().CoreV1().Pods(cr.Namespace).Get(context.TODO(), podName, metav1.GetOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return -1, nil + } + pod, err := client.CoreV1().Pods(cr.Namespace).Get(context.TODO(), podName, metav1.GetOptions{}) if err != nil { logger.Error(err, "Could not get pod info") } diff --git a/k8sutils/secrets.go b/k8sutils/secrets.go index 0cb7a935b..4636b54b0 100644 --- a/k8sutils/secrets.go +++ b/k8sutils/secrets.go @@ -17,7 +17,12 @@ var log = logf.Log.WithName("controller_redis") // getRedisPassword method will return the redis password func getRedisPassword(namespace, name, secretKey string) (string, error) { logger := secretLogger(namespace, name) - secretName, err := generateK8sClient().CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return "", err + } + secretName, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { logger.Error(err, "Failed in getting existing secret for redis") return "", err @@ -36,9 +41,13 @@ func secretLogger(namespace string, name string) logr.Logger { } func getRedisTLSConfig(cr *redisv1beta2.RedisCluster, redisInfo RedisDetails) *tls.Config { + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + return nil + } if cr.Spec.TLS != nil { reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name) - secretName, err := generateK8sClient().CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) + secretName, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) if err != nil { reqLogger.Error(err, "Failed in getting TLS secret for redis") } @@ -84,9 +93,13 @@ func getRedisTLSConfig(cr *redisv1beta2.RedisCluster, redisInfo RedisDetails) *t } func getRedisReplicationTLSConfig(cr *redisv1beta2.RedisReplication, redisInfo RedisDetails) *tls.Config { + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + return nil + } if cr.Spec.TLS != nil { reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name) - secretName, err := generateK8sClient().CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) + secretName, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) if err != nil { reqLogger.Error(err, "Failed in getting TLS secret for redis") } diff --git a/k8sutils/services.go b/k8sutils/services.go index c93dab87d..0bcf56944 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -89,7 +89,12 @@ func generateServiceType(k8sServiceType string) corev1.ServiceType { // createService is a method to create service is Kubernetes func createService(namespace string, service *corev1.Service) error { logger := serviceLogger(namespace, service.Name) - _, err := generateK8sClient().CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + _, err = client.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis service creation is failed") return err @@ -101,7 +106,12 @@ func createService(namespace string, service *corev1.Service) error { // updateService is a method to update service is Kubernetes func updateService(namespace string, service *corev1.Service) error { logger := serviceLogger(namespace, service.Name) - _, err := generateK8sClient().CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + _, err = client.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) if err != nil { logger.Error(err, "Redis service update failed") return err @@ -113,10 +123,15 @@ func updateService(namespace string, service *corev1.Service) error { // getService is a method to get service is Kubernetes func getService(namespace string, service string) (*corev1.Service, error) { logger := serviceLogger(namespace, service) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return nil, err + } getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("Service", "v1"), } - serviceInfo, err := generateK8sClient().CoreV1().Services(namespace).Get(context.TODO(), service, getOpts) + serviceInfo, err := client.CoreV1().Services(namespace).Get(context.TODO(), service, getOpts) if err != nil { logger.V(1).Info("Redis service get action is failed") return nil, err diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 7defa8e8f..3be4b54f2 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -107,7 +107,11 @@ func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params // patchStateFulSet will patch Redis Kubernetes StateFulSet func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.StatefulSet, namespace string, recreateStateFulSet bool) error { logger := statefulSetLogger(namespace, storedStateful.Name) - + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } // We want to try and keep this atomic as possible. newStateful.ResourceVersion = storedStateful.ResourceVersion newStateful.CreationTimestamp = storedStateful.CreationTimestamp @@ -155,7 +159,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St }, ), } - pvcs, err := generateK8sClient().CoreV1().PersistentVolumeClaims(storedStateful.Namespace).List(context.Background(), listOpt) + pvcs, err := client.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).List(context.Background(), listOpt) if err != nil { return err } @@ -166,7 +170,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St if realCapacity != stateCapacity { realUpdate = true pvc.Spec.Resources.Requests = newStateful.Spec.VolumeClaimTemplates[0].Spec.Resources.Requests - _, err = generateK8sClient().CoreV1().PersistentVolumeClaims(storedStateful.Namespace).Update(context.Background(), &pvc, metav1.UpdateOptions{}) + _, err = client.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).Update(context.Background(), &pvc, metav1.UpdateOptions{}) if err != nil { if !updateFailed { updateFailed = true @@ -629,7 +633,12 @@ func getEnvironmentVariables(role string, enabledPassword *bool, secretName *str // createStatefulSet is a method to create statefulset in Kubernetes func createStatefulSet(namespace string, stateful *appsv1.StatefulSet) error { logger := statefulSetLogger(namespace, stateful.Name) - _, err := generateK8sClient().AppsV1().StatefulSets(namespace).Create(context.TODO(), stateful, metav1.CreateOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + _, err = client.AppsV1().StatefulSets(namespace).Create(context.TODO(), stateful, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis stateful creation failed") return err @@ -641,7 +650,12 @@ func createStatefulSet(namespace string, stateful *appsv1.StatefulSet) error { // updateStatefulSet is a method to update statefulset in Kubernetes func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool) error { logger := statefulSetLogger(namespace, stateful.Name) - _, err := generateK8sClient().AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{}) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return err + } + _, err = client.AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{}) if recreateStateFulSet { sErr, ok := err.(*apierrors.StatusError) if ok && sErr.ErrStatus.Code == 422 && sErr.ErrStatus.Reason == metav1.StatusReasonInvalid { @@ -651,7 +665,7 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS } logger.V(1).Info("recreating StatefulSet because the update operation wasn't possible", "reason", strings.Join(failMsg, ", ")) propagationPolicy := metav1.DeletePropagationForeground - if err := generateK8sClient().AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { //nolint + if err := client.AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { //nolint return errors.Wrap(err, "failed to delete StatefulSet to avoid forbidden action") } } @@ -667,10 +681,15 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS // GetStateFulSet is a method to get statefulset in Kubernetes func GetStatefulSet(namespace string, stateful string) (*appsv1.StatefulSet, error) { logger := statefulSetLogger(namespace, stateful) + client, err := GenerateK8sClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Could not generate kubernetes client") + return nil, err + } getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("StatefulSet", "apps/v1"), } - statefulInfo, err := generateK8sClient().AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, getOpts) + statefulInfo, err := client.AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, getOpts) if err != nil { logger.V(1).Info("Redis statefulset get action failed") return nil, err diff --git a/k8sutils/status.go b/k8sutils/status.go index 1232b2384..3cc32353d 100644 --- a/k8sutils/status.go +++ b/k8sutils/status.go @@ -26,7 +26,7 @@ func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.Redis cr.Status.ReadyLeaderReplicas = readyLeaderReplicas cr.Status.ReadyFollowerReplicas = readyFollowerReplicas - client := generateK8sDynamicClient() + client, err := GenerateK8sDynamicClient(GenerateK8sConfig) gvr := schema.GroupVersionResource{ Group: "redis.redis.opstreelabs.in", Version: "v1beta2", diff --git a/main.go b/main.go index 70d82f333..ec277322a 100644 --- a/main.go +++ b/main.go @@ -36,6 +36,7 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/controllers" + "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" // +kubebuilder:scaffold:imports @@ -100,10 +101,24 @@ func main() { os.Exit(1) } + k8sclient, err := k8sutils.GenerateK8sClient(k8sutils.GenerateK8sConfig) + if err != nil { + setupLog.Error(err, "unable to create k8s client") + os.Exit(1) + } + + dk8sClinet, err := k8sutils.GenerateK8sDynamicClient(k8sutils.GenerateK8sConfig) + if err != nil { + setupLog.Error(err, "unable to create k8s dynamic client") + os.Exit(1) + } + if err = (&controllers.RedisReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("Redis"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + K8sClient: k8sclient, + Dk8sClinet: dk8sClinet, + Log: ctrl.Log.WithName("controllers").WithName("Redis"), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Redis") os.Exit(1) diff --git a/mocks/log/logger.go b/mocks/log/logger.go new file mode 100644 index 000000000..78f1e666a --- /dev/null +++ b/mocks/log/logger.go @@ -0,0 +1,5 @@ +package log + +type LoggerInterface interface { + Error(error, string, ...interface{}) +} From defdcdfab67fa69b7127f7f12861b41f5e0cff15 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:06:12 +0530 Subject: [PATCH 055/203] Add : Mock Client (#699) Signed-off-by: Shubham Gupta --- mocks/client/client_mock.go | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 mocks/client/client_mock.go diff --git a/mocks/client/client_mock.go b/mocks/client/client_mock.go new file mode 100644 index 000000000..382378559 --- /dev/null +++ b/mocks/client/client_mock.go @@ -0,0 +1,67 @@ +package client + +import ( + "context" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" +) + +type MockClient struct { + GetFn func(ctx context.Context, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error + ListFn func(ctx context.Context, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error + CreateFn func(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error + DeleteFn func(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error + UpdateFn func(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error + PatchFn func(ctx context.Context, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error + DeleteAllofFn func(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.DeleteAllOfOption) error + IsObjectNamespacedFn func(obj runtime.Object) (bool, error) + ctrlclient.StatusClient + ctrlclient.SubResourceClientConstructor +} + +func (m *MockClient) Scheme() *runtime.Scheme { + return nil +} + +func (m *MockClient) RESTMapper() meta.RESTMapper { + return nil +} + +func (m *MockClient) GroupVersionKindFor(obj runtime.Object) (schema.GroupVersionKind, error) { + return schema.GroupVersionKind{}, nil +} + +func (m *MockClient) IsObjectNamespaced(obj runtime.Object) (bool, error) { + return m.IsObjectNamespacedFn(obj) +} + +func (m *MockClient) Get(ctx context.Context, key ctrlclient.ObjectKey, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error { + return m.GetFn(ctx, key, obj, opts...) +} + +func (m *MockClient) List(ctx context.Context, list ctrlclient.ObjectList, opts ...ctrlclient.ListOption) error { + return m.ListFn(ctx, list, opts...) +} + +func (m *MockClient) Create(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.CreateOption) error { + return m.CreateFn(ctx, obj, opts...) +} + +func (m *MockClient) Delete(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.DeleteOption) error { + return m.DeleteFn(ctx, obj, opts...) +} + +func (m *MockClient) Update(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.UpdateOption) error { + return m.UpdateFn(ctx, obj, opts...) +} + +func (m *MockClient) Patch(ctx context.Context, obj ctrlclient.Object, patch ctrlclient.Patch, opts ...ctrlclient.PatchOption) error { + return m.PatchFn(ctx, obj, patch, opts...) +} + +func (m *MockClient) DeleteAllOf(ctx context.Context, obj ctrlclient.Object, opts ...ctrlclient.DeleteAllOfOption) error { + return m.DeleteAllofFn(ctx, obj, opts...) +} From 36591d5ba3305e28522b415d20ff4c7c9d5d64db Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 11 Nov 2023 01:07:54 +0530 Subject: [PATCH 056/203] fix : Add client for Testing (#700) * mock client Signed-off-by: Shubham Gupta * feat: add client Signed-off-by: Shubham Gupta * Add finalizers Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * Add Test Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- controllers/rediscluster_controller.go | 10 +- controllers/redisreplication_controller.go | 10 +- controllers/redissentinel_controller.go | 8 +- k8sutils/finalizer.go | 41 ++--- k8sutils/finalizers_test.go | 191 +++++++++++++++++++++ main.go | 25 +-- 6 files changed, 238 insertions(+), 47 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 91560bb36..634560949 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -27,6 +27,8 @@ import ( "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -34,8 +36,10 @@ import ( // RedisClusterReconciler reconciles a RedisCluster object type RedisClusterReconciler struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme + K8sClient kubernetes.Interface + Dk8sClinet dynamic.Interface + Log logr.Logger + Scheme *runtime.Scheme } // Reconcile is part of the main kubernetes reconciliation loop @@ -61,7 +65,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request followerReplicas := instance.Spec.GetReplicaCounts("follower") totalReplicas := leaderReplicas + followerReplicas - if err = k8sutils.HandleRedisClusterFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisClusterFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 3a0eaae17..193cc3de9 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -10,6 +10,8 @@ import ( "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -17,8 +19,10 @@ import ( // RedisReplicationReconciler reconciles a RedisReplication object type RedisReplicationReconciler struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme + K8sClient kubernetes.Interface + Dk8sClinet dynamic.Interface + Log logr.Logger + Scheme *runtime.Scheme } func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { @@ -44,7 +48,7 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req followerReplicas := instance.Spec.GetReplicationCounts("replication") - leaderReplicas totalReplicas := leaderReplicas + followerReplicas - if err = k8sutils.HandleRedisReplicationFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisReplicationFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { return ctrl.Result{}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 33170cff1..18619a174 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -9,6 +9,8 @@ import ( "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -16,8 +18,10 @@ import ( // RedisSentinelReconciler reconciles a RedisSentinel object type RedisSentinelReconciler struct { client.Client - Log logr.Logger - Scheme *runtime.Scheme + K8sClient kubernetes.Interface + Dk8sClinet dynamic.Interface + Log logr.Logger + Scheme *runtime.Scheme } // Reconcile is part of the main kubernetes reconciliation loop which aims diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index cb68d0c1b..0131b24fa 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -3,10 +3,8 @@ package k8sutils import ( "context" "fmt" - "strconv" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - mockLog "github.com/OT-CONTAINER-KIT/redis-operator/mocks/log" "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -46,15 +44,14 @@ func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interfa } // HandleRedisClusterFinalizer finalize resource if instance is marked to be deleted -func HandleRedisClusterFinalizer(cr *redisv1beta2.RedisCluster, cl client.Client) error { - logger := finalizerLogger(cr.Namespace, RedisClusterFinalizer) +func HandleRedisClusterFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisClusterFinalizer) { - if err := finalizeRedisClusterPVC(cr); err != nil { + if err := finalizeRedisClusterPVC(k8sClient, logger, cr); err != nil { return err } controllerutil.RemoveFinalizer(cr, RedisClusterFinalizer) - if err := cl.Update(context.TODO(), cr); err != nil { + if err := ctrlclient.Update(context.TODO(), cr); err != nil { logger.Error(err, "Could not remove finalizer "+RedisClusterFinalizer) return err } @@ -64,15 +61,14 @@ func HandleRedisClusterFinalizer(cr *redisv1beta2.RedisCluster, cl client.Client } // Handle RedisReplicationFinalizer finalize resource if instance is marked to be deleted -func HandleRedisReplicationFinalizer(cr *redisv1beta2.RedisReplication, cl client.Client) error { - logger := finalizerLogger(cr.Namespace, RedisReplicationFinalizer) +func HandleRedisReplicationFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisReplicationFinalizer) { - if err := finalizeRedisReplicationPVC(cr); err != nil { + if err := finalizeRedisReplicationPVC(k8sClient, logger, cr); err != nil { return err } controllerutil.RemoveFinalizer(cr, RedisReplicationFinalizer) - if err := cl.Update(context.TODO(), cr); err != nil { + if err := ctrlclient.Update(context.TODO(), cr); err != nil { logger.Error(err, "Could not remove finalizer "+RedisReplicationFinalizer) return err } @@ -136,7 +132,7 @@ func AddRedisSentinelFinalizer(cr *redisv1beta2.RedisSentinel, cl client.Client) } // finalizeRedisPVC delete PVC -func finalizeRedisPVC(client kubernetes.Interface, logger mockLog.LoggerInterface, cr *redisv1beta2.Redis) error { +func finalizeRedisPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error { PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { @@ -147,16 +143,10 @@ func finalizeRedisPVC(client kubernetes.Interface, logger mockLog.LoggerInterfac } // finalizeRedisClusterPVC delete PVCs -func finalizeRedisClusterPVC(cr *redisv1beta2.RedisCluster) error { - logger := finalizerLogger(cr.Namespace, RedisClusterFinalizer) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } +func finalizeRedisClusterPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { for _, role := range []string{"leader", "follower"} { for i := 0; i < int(cr.Spec.GetReplicaCounts(role)); i++ { - PVCName := cr.Name + "-" + cr.Name + "-" + role + "-" + strconv.Itoa(i) + PVCName := fmt.Sprintf("%s-%s-%s-%d", cr.Name, cr.Name, role, i) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) @@ -165,7 +155,7 @@ func finalizeRedisClusterPVC(cr *redisv1beta2.RedisCluster) error { } if cr.Spec.Storage.NodeConfVolume { for i := 0; i < int(cr.Spec.GetReplicaCounts(role)); i++ { - PVCName := "node-conf" + cr.Name + "-" + role + "-" + strconv.Itoa(i) + PVCName := fmt.Sprintf("%s-%s-%s-%d", "node-conf", cr.Name, role, i) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) @@ -179,22 +169,15 @@ func finalizeRedisClusterPVC(cr *redisv1beta2.RedisCluster) error { } // finalizeRedisReplicationPVC delete PVCs -func finalizeRedisReplicationPVC(cr *redisv1beta2.RedisReplication) error { - logger := finalizerLogger(cr.Namespace, RedisReplicationFinalizer) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } +func finalizeRedisReplicationPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication) error { for i := 0; i < int(cr.Spec.GetReplicationCounts("replication")); i++ { - PVCName := cr.Name + "-" + cr.Name + "-" + strconv.Itoa(i) + PVCName := fmt.Sprintf("%s-%s-%d", cr.Name, cr.Name, i) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) return err } } - return nil } diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go index 4ab301919..d8175ced9 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizers_test.go @@ -11,7 +11,9 @@ import ( corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" k8sClientFake "k8s.io/client-go/kubernetes/fake" + "k8s.io/utils/pointer" ) // func TestHandleRedisFinalizer(t *testing.T) { @@ -120,3 +122,192 @@ func TestFinalizeRedisPVC(t *testing.T) { }) } } + +func TestFinalizeRedisReplicationPVC(t *testing.T) { + tests := []struct { + name string + existingPVCs []*corev1.PersistentVolumeClaim + redisReplication *v1beta2.RedisReplication + expectError bool + }{ + { + name: "Successful deletion of Redis Replication PVCs", + redisReplication: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "redis", + }, + Spec: v1beta2.RedisReplicationSpec{ + Size: pointer.Int32(3), + }, + }, + existingPVCs: []*corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-0", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-1", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-2", + Namespace: "redis", + }, + }, + }, + expectError: false, + }, + { + name: "PVC does not exist and no error should be returned", + existingPVCs: nil, + redisReplication: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "redis", + }, + Spec: v1beta2.RedisReplicationSpec{ + Size: pointer.Int32(3), + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tc.existingPVCs != nil { + k8sClient = k8sClientFake.NewSimpleClientset(helperToRuntimeObjects(tc.existingPVCs)...) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + err := finalizeRedisReplicationPVC(k8sClient, logger, tc.redisReplication) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + + // Verify PVCs are deleted + if !tc.expectError { + for _, pvc := range tc.existingPVCs { + _, err := k8sClient.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(context.TODO(), pvc.Name, metav1.GetOptions{}) + assert.True(t, k8serrors.IsNotFound(err)) + } + } + }) + } +} + +func TestFinalizeRedisClusterPVC(t *testing.T) { + tests := []struct { + name string + existingPVCs []*corev1.PersistentVolumeClaim + redisCluster *v1beta2.RedisCluster + expectError bool + }{ + { + name: "Successful deletion of Redis Cluster PVCs", + redisCluster: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "redis", + }, + Spec: v1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.ClusterStorage{ + NodeConfVolume: true, + }, + }, + }, + existingPVCs: helperRedisClusterPVCs("redis-cluster", "redis"), + expectError: false, + }, + { + name: "PVC does not exist and no error should be returned", + existingPVCs: nil, + redisCluster: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "redis", + }, + Spec: v1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.ClusterStorage{ + NodeConfVolume: false, + }, + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tc.existingPVCs != nil { + k8sClient = k8sClientFake.NewSimpleClientset(helperToRuntimeObjects(tc.existingPVCs)...) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + err := finalizeRedisClusterPVC(k8sClient, logger, tc.redisCluster) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + + // Verify PVCs are deleted + if !tc.expectError { + for _, pvc := range tc.existingPVCs { + _, err := k8sClient.CoreV1().PersistentVolumeClaims(pvc.Namespace).Get(context.TODO(), pvc.Name, metav1.GetOptions{}) + assert.True(t, k8serrors.IsNotFound(err)) + } + } + }) + } +} + +func helperToRuntimeObjects(pvcs []*corev1.PersistentVolumeClaim) []runtime.Object { + objs := make([]runtime.Object, len(pvcs)) + for i, pvc := range pvcs { + objs[i] = pvc.DeepCopyObject() + } + return objs +} + +func helperRedisClusterPVCs(clusterName string, namespace string) []*corev1.PersistentVolumeClaim { + var pvcs []*corev1.PersistentVolumeClaim + roles := []string{"leader", "follower"} + for _, role := range roles { + for i := 0; i < 3; i++ { + clusterPVCName := fmt.Sprintf("%s-%s-%s-%d", clusterName, clusterName, role, i) + clusterPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterPVCName, + Namespace: namespace, + }, + } + pvcs = append(pvcs, clusterPVC) + nodeConfPVCName := fmt.Sprintf("node-conf-%s-%s-%d", clusterName, role, i) + nodeConfPVC := &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: nodeConfPVCName, + Namespace: namespace, + }, + } + pvcs = append(pvcs, nodeConfPVC) + } + } + return pvcs +} diff --git a/main.go b/main.go index ec277322a..3d22552ee 100644 --- a/main.go +++ b/main.go @@ -124,26 +124,31 @@ func main() { os.Exit(1) } if err = (&controllers.RedisClusterReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("RedisCluster"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + K8sClient: k8sclient, + Dk8sClinet: dk8sClinet, + Log: ctrl.Log.WithName("controllers").WithName("RedisCluster"), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "RedisCluster") os.Exit(1) } if err = (&controllers.RedisReplicationReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("RedisReplication"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + K8sClient: k8sclient, + Dk8sClinet: dk8sClinet, + Log: ctrl.Log.WithName("controllers").WithName("RedisReplication"), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "RedisReplication") os.Exit(1) } - if err = (&controllers.RedisSentinelReconciler{ - Client: mgr.GetClient(), - Log: ctrl.Log.WithName("controllers").WithName("RedisSentinel"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + K8sClient: k8sclient, + Dk8sClinet: dk8sClinet, + Log: ctrl.Log.WithName("controllers").WithName("RedisSentinel"), + Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "RedisSentinel") os.Exit(1) From 58db9ec5a4654a6ba7b6f8662fe3048295dcd01e Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 11 Nov 2023 05:16:27 +0530 Subject: [PATCH 057/203] test: Add secret_test.go (#701) * fix client Signed-off-by: Shubham Gupta * Add secret test Signed-off-by: Shubham Gupta * fix lint Signed-off-by: Shubham Gupta * update CI Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 1 - .golangci.yml | 4 + controllers/rediscluster_controller.go | 32 +- controllers/redisreplication_controller.go | 8 +- controllers/redissentinel_controller.go | 2 +- k8sutils/cluster-scaling.go | 103 +++--- k8sutils/finalizers_test.go | 6 + k8sutils/redis-sentinel.go | 29 +- k8sutils/redis-sentinel_test.go | 3 +- k8sutils/redis.go | 115 +++---- k8sutils/secrets.go | 121 +++---- k8sutils/secrets_test.go | 382 +++++++++++++++++++++ k8sutils/status.go | 4 + tests/testdata/secrets/ca.crt | 19 + tests/testdata/secrets/tls.crt | 17 + tests/testdata/secrets/tls.key | 28 ++ 16 files changed, 637 insertions(+), 237 deletions(-) create mode 100644 k8sutils/secrets_test.go create mode 100644 tests/testdata/secrets/ca.crt create mode 100644 tests/testdata/secrets/tls.crt create mode 100644 tests/testdata/secrets/tls.key diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index f9322b585..f32f67757 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -86,7 +86,6 @@ jobs: uses: golangci/golangci-lint-action@v3 with: version: v1.54.0 - args: --timeout=5m0s ./... --verbose --out-format=github-actions container_quality_dockerfile_lint: needs: [gofmt, govet] diff --git a/.golangci.yml b/.golangci.yml index 48fc1e0d6..a72eb7d4d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,6 +25,10 @@ issues: run: timeout: 5m go-version: "1.21" + output: + format: colored-line-number + sort-results: true + test: false # Exclude third-party packages and go.mod from the lint checks exclude: | diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 634560949..8a43c5840 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -80,21 +80,21 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // check whether the redis is leader or not ? // if not true then make it leader pod - if !(k8sutils.VerifyLeaderPod(ctx, instance)) { + if !(k8sutils.VerifyLeaderPod(ctx, r.K8sClient, r.Log, instance)) { // lastLeaderPod is slaving right now Make it the master Pod // We have to bring a manual failover here to make it a leaderPod // clusterFailover should also include the clusterReplicate since we have to map the followers to new leader - k8sutils.ClusterFailover(ctx, instance) + k8sutils.ClusterFailover(ctx, r.K8sClient, r.Log, instance) } // Step 1 Rehard the Cluster - k8sutils.ReshardRedisCluster(instance) + k8sutils.ReshardRedisCluster(r.K8sClient, r.Log, instance) // Step 2 Remove the Follower Node - k8sutils.RemoveRedisFollowerNodesFromCluster(ctx, instance) + k8sutils.RemoveRedisFollowerNodesFromCluster(ctx, r.K8sClient, r.Log, instance) // Step 3 Remove the Leader Node - k8sutils.RemoveRedisNodeFromCluster(ctx, instance) + k8sutils.RemoveRedisNodeFromCluster(ctx, r.K8sClient, r.Log, instance) // Step 4 Rebalance the cluster - k8sutils.RebalanceRedisCluster(instance) + k8sutils.RebalanceRedisCluster(r.K8sClient, r.Log, instance) return ctrl.Result{RequeueAfter: time.Second * 100}, nil } @@ -185,34 +185,34 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) - if k8sutils.CheckRedisNodeCount(ctx, instance, "") != totalReplicas { - leaderCount := k8sutils.CheckRedisNodeCount(ctx, instance, "leader") + if k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "") != totalReplicas { + leaderCount := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) if leaderCount <= 2 { - k8sutils.ExecuteRedisClusterCommand(ctx, instance) + k8sutils.ExecuteRedisClusterCommand(ctx, r.K8sClient, r.Log, instance) } else { if leaderCount < leaderReplicas { // Scale up the cluster // Step 2 : Add Redis Node - k8sutils.AddRedisNodeToCluster(ctx, instance) + k8sutils.AddRedisNodeToCluster(ctx, r.K8sClient, r.Log, instance) // Step 3 Rebalance the cluster using the empty masters - k8sutils.RebalanceRedisClusterEmptyMasters(instance) + k8sutils.RebalanceRedisClusterEmptyMasters(r.K8sClient, r.Log, instance) } } } else { if followerReplicas > 0 && redisFollowerInfo.Status.ReadyReplicas == followerReplicas { reqLogger.Info("All leader are part of the cluster, adding follower/replicas", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas, "Follower.Replicas", followerReplicas) - k8sutils.ExecuteRedisReplicationCommand(ctx, instance) + k8sutils.ExecuteRedisReplicationCommand(ctx, r.K8sClient, r.Log, instance) } else { reqLogger.Info("no follower/replicas configured, skipping replication configuration", "Leaders.Count", leaderCount, "Leader.Size", leaderReplicas, "Follower.Replicas", followerReplicas) } } } else { reqLogger.Info("Redis leader count is desired") - if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(ctx, instance) >= int(totalReplicas)-1 { + if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(ctx, r.K8sClient, r.Log, instance) >= int(totalReplicas)-1 { reqLogger.Info("Redis leader is not desired, executing failover operation") - err = k8sutils.ExecuteFailoverOperation(ctx, instance) + err = k8sutils.ExecuteFailoverOperation(ctx, r.K8sClient, r.Log, instance) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 10}, err } @@ -221,8 +221,8 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Check If there is No Empty Master Node - if k8sutils.CheckRedisNodeCount(ctx, instance, "") == totalReplicas { - k8sutils.CheckIfEmptyMasters(ctx, instance) + if k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "") == totalReplicas { + k8sutils.CheckIfEmptyMasters(ctx, r.K8sClient, r.Log, instance) } reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 193cc3de9..c424c85d5 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -80,11 +80,11 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) - if len(k8sutils.GetRedisNodesByRole(ctx, instance, "master")) > int(leaderReplicas) { + if len(k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master")) > int(leaderReplicas) { - masterNodes := k8sutils.GetRedisNodesByRole(ctx, instance, "master") - slaveNodes := k8sutils.GetRedisNodesByRole(ctx, instance, "slave") - err := k8sutils.CreateMasterSlaveReplication(ctx, instance, masterNodes, slaveNodes) + masterNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master") + slaveNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "slave") + err := k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, slaveNodes) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 18619a174..3a88dcc74 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -55,7 +55,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Create Redis Sentinel - err = k8sutils.CreateRedisSentinel(ctx, instance) + err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance) if err != nil { return ctrl.Result{}, err } diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index b191b63f5..8304d0060 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -6,15 +6,16 @@ import ( "strings" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr" redis "github.com/redis/go-redis/v9" + "k8s.io/client-go/kubernetes" ) // Reshard the redis Cluster -func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { +func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { ctx := context.TODO() - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) var cmd []string - currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") // Transfer Pod details transferPOD := RedisDetails{ @@ -35,7 +36,7 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -48,17 +49,17 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { //--cluster-from --cluster-to --cluster-slots --cluster-yes // Remove Node - removeNodeID := getRedisNodeID(ctx, cr, removePOD) + removeNodeID := getRedisNodeID(ctx, client, logger, cr, removePOD) cmd = append(cmd, "--cluster-from") cmd = append(cmd, removeNodeID) // Transfer Node - transferNodeID := getRedisNodeID(ctx, cr, transferPOD) + transferNodeID := getRedisNodeID(ctx, client, logger, cr, transferPOD) cmd = append(cmd, "--cluster-to") cmd = append(cmd, transferNodeID) // Cluster Slots - slot := getRedisClusterSlots(ctx, cr, removeNodeID) + slot := getRedisClusterSlots(ctx, client, logger, cr, removeNodeID) cmd = append(cmd, "--cluster-slots") cmd = append(cmd, slot) @@ -73,11 +74,10 @@ func ReshardRedisCluster(cr *redisv1beta2.RedisCluster) { executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") } -func getRedisClusterSlots(ctx context.Context, cr *redisv1beta2.RedisCluster, nodeID string) string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeID string) string { totalSlots := 0 - redisClient := configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() if err != nil { @@ -114,20 +114,18 @@ func getRedisClusterSlots(ctx context.Context, cr *redisv1beta2.RedisCluster, no } // getRedisNodeID would return nodeID of a redis node by passing pod -func getRedisNodeID(ctx context.Context, cr *redisv1beta2.RedisCluster, pod RedisDetails) string { - var client *redis.Client - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - client = configureRedisClient(cr, pod.PodName) - defer client.Close() +func getRedisNodeID(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, pod RedisDetails) string { + redisClient := configureRedisClient(client, logger, cr, pod.PodName) + defer redisClient.Close() - pong, err := client.Ping(ctx).Result() + pong, err := redisClient.Ping(ctx).Result() if err != nil || pong != "PONG" { logger.Error(err, "Failed to ping Redis server") return "" } cmd := redis.NewStringCmd(ctx, "cluster", "myid") - err = client.Process(ctx, cmd) + err = redisClient.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") return "" @@ -143,8 +141,7 @@ func getRedisNodeID(ctx context.Context, cr *redisv1beta2.RedisCluster, pod Redi } // Rebalance the Redis CLuster using the Empty Master Nodes -func RebalanceRedisClusterEmptyMasters(cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { // cmd = redis-cli --cluster rebalance : --cluster-use-empty-masters -a var cmd []string pod := RedisDetails{ @@ -162,7 +159,7 @@ func RebalanceRedisClusterEmptyMasters(cr *redisv1beta2.RedisCluster) { cmd = append(cmd, "--cluster-use-empty-masters") if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -176,29 +173,27 @@ func RebalanceRedisClusterEmptyMasters(cr *redisv1beta2.RedisCluster) { executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") } -func CheckIfEmptyMasters(ctx context.Context, cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - totalRedisLeaderNodes := CheckRedisNodeCount(ctx, cr, "leader") +func CheckIfEmptyMasters(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { + totalRedisLeaderNodes := CheckRedisNodeCount(ctx, client, logger, cr, "leader") for i := 0; i < int(totalRedisLeaderNodes); i++ { pod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i), Namespace: cr.Namespace, } - podNodeID := getRedisNodeID(ctx, cr, pod) - podSlots := getRedisClusterSlots(ctx, cr, podNodeID) + podNodeID := getRedisNodeID(ctx, client, logger, cr, pod) + podSlots := getRedisClusterSlots(ctx, client, logger, cr, podNodeID) if podSlots == "0" || podSlots == "" { logger.V(1).Info("Found Empty Redis Leader Node", "pod", pod) - RebalanceRedisClusterEmptyMasters(cr) + RebalanceRedisClusterEmptyMasters(client, logger, cr) break } } } // Rebalance Redis Cluster Would Rebalance the Redis Cluster without using the empty masters -func RebalanceRedisCluster(cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { // cmd = redis-cli --cluster rebalance : -a var cmd []string pod := RedisDetails{ @@ -214,7 +209,7 @@ func RebalanceRedisCluster(cr *redisv1beta2.RedisCluster) { } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -229,10 +224,9 @@ func RebalanceRedisCluster(cr *redisv1beta2.RedisCluster) { } // Add redis cluster node would add a node to the existing redis cluster using redis-cli -func AddRedisNodeToCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { var cmd []string - activeRedisNode := CheckRedisNodeCount(ctx, cr, "leader") + activeRedisNode := CheckRedisNodeCount(ctx, client, logger, cr, "leader") newPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(activeRedisNode)), @@ -254,7 +248,7 @@ func AddRedisNodeToCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -269,10 +263,8 @@ func AddRedisNodeToCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { } // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader -func getAttachedFollowerNodeIDs(ctx context.Context, cr *redisv1beta2.RedisCluster, masterNodeID string) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - - redisClient := configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") +func getAttachedFollowerNodeIDs(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, masterNodeID string) []string { + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() if err != nil { @@ -299,10 +291,9 @@ func getAttachedFollowerNodeIDs(ctx context.Context, cr *redisv1beta2.RedisClust } // Remove redis follower node would remove all follower nodes of last leader node using redis-cli -func RemoveRedisFollowerNodesFromCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { var cmd []string - currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -316,7 +307,7 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, cr *redisv1beta2.R cmd = []string{"redis-cli"} if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -325,8 +316,8 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, cr *redisv1beta2.R } cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) - lastLeaderPodNodeID := getRedisNodeID(ctx, cr, lastLeaderPod) - followerNodeIDs := getAttachedFollowerNodeIDs(ctx, cr, lastLeaderPodNodeID) + lastLeaderPodNodeID := getRedisNodeID(ctx, client, logger, cr, lastLeaderPod) + followerNodeIDs := getAttachedFollowerNodeIDs(ctx, client, logger, cr, lastLeaderPodNodeID) cmd = append(cmd, "--cluster", "del-node") if *cr.Spec.ClusterVersion == "v7" { @@ -345,10 +336,9 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, cr *redisv1beta2.R } // Remove redis cluster node would remove last node to the existing redis cluster using redis-cli -func RemoveRedisNodeFromCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { var cmd []string - currentRedisCount := CheckRedisNodeCount(ctx, cr, "leader") + currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -367,11 +357,11 @@ func RemoveRedisNodeFromCluster(ctx context.Context, cr *redisv1beta2.RedisClust cmd = append(cmd, getRedisServerIP(existingPod)+":6379") } - removePodNodeID := getRedisNodeID(ctx, cr, removePod) + removePodNodeID := getRedisNodeID(ctx, client, logger, cr, removePod) cmd = append(cmd, removePodNodeID) if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -382,18 +372,17 @@ func RemoveRedisNodeFromCluster(ctx context.Context, cr *redisv1beta2.RedisClust cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster leader remove command is", "Command", cmd) - if getRedisClusterSlots(ctx, cr, removePodNodeID) != "0" { + if getRedisClusterSlots(ctx, client, logger, cr, removePodNodeID) != "0" { logger.V(1).Info("Skipping execution remove leader not empty", "cmd", cmd) } executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // verifyLeaderPod return true if the pod is leader/master -func VerifyLeaderPod(ctx context.Context, cr *redisv1beta2.RedisCluster) bool { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - podName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, cr, "leader"))-1) +func VerifyLeaderPod(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) bool { + podName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, client, logger, cr, "leader"))-1) - redisClient := configureRedisClient(cr, podName) + redisClient := configureRedisClient(client, logger, cr, podName) defer redisClient.Close() info, err := redisClient.Info(ctx, "replication").Result() if err != nil { @@ -412,11 +401,9 @@ func VerifyLeaderPod(ctx context.Context, cr *redisv1beta2.RedisCluster) bool { return false } -func ClusterFailover(ctx context.Context, cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - slavePodName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, cr, "leader"))-1) +func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { + slavePodName := cr.Name + "-leader-" + strconv.Itoa(int(CheckRedisNodeCount(ctx, client, logger, cr, "leader"))-1) // cmd = redis-cli cluster failover -a - var cmd []string pod := RedisDetails{ PodName: slavePodName, @@ -432,7 +419,7 @@ func ClusterFailover(ctx context.Context, cr *redisv1beta2.RedisCluster) { } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go index d8175ced9..ad67c0247 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizers_test.go @@ -5,6 +5,8 @@ import ( "fmt" "testing" + // "time" + "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr/testr" "github.com/stretchr/testify/assert" @@ -12,8 +14,12 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + + // "k8s.io/apimachinery/pkg/types" + // utilruntime "k8s.io/apimachinery/pkg/util/runtime" k8sClientFake "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/pointer" + // ctrlClientFake "sigs.k8s.io/controller-runtime/pkg/client/fake" ) // func TestHandleRedisFinalizer(t *testing.T) { diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 23d9ce509..42e96b38b 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -7,9 +7,11 @@ import ( commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" ) // RedisSentinelSTS is a interface to call Redis Statefulset function @@ -32,7 +34,7 @@ type RedisReplicationObject struct { } // Redis Sentinel Create the Redis Sentinel Setup -func CreateRedisSentinel(ctx context.Context, cr *redisv1beta2.RedisSentinel) error { +func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) error { prop := RedisSentinelSTS{ RedisStateFulType: "sentinel", Affinity: cr.Spec.Affinity, @@ -45,7 +47,7 @@ func CreateRedisSentinel(ctx context.Context, cr *redisv1beta2.RedisSentinel) er prop.ExternalConfig = cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig } - return prop.CreateRedisSentinelSetup(ctx, cr) + return prop.CreateRedisSentinelSetup(ctx, client, logger, cr) } @@ -59,10 +61,8 @@ func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { } // Create Redis Sentinel Cluster Setup -func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr *redisv1beta2.RedisSentinel) error { - +func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType - logger := statefulSetLogger(cr.Namespace, stateFulName) labels := getRedisLabels(stateFulName, sentinel, service.RedisStateFulType, cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) @@ -72,7 +72,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cr generateRedisSentinelParams(cr, service.getSentinelCount(cr), service.ExternalConfig, service.Affinity), redisSentinelAsOwner(cr), generateRedisSentinelInitContainerParams(cr), - generateRedisSentinelContainerParams(ctx, cr, service.ReadinessProbe, service.LivenessProbe), + generateRedisSentinelContainerParams(ctx, client, logger, cr, service.ReadinessProbe, service.LivenessProbe), cr.Spec.Sidecars, ) @@ -141,8 +141,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in } // Create Redis Sentinel Statefulset Container Params -func generateRedisSentinelContainerParams(ctx context.Context, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { - +func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ @@ -151,7 +150,7 @@ func generateRedisSentinelContainerParams(ctx context.Context, cr *redisv1beta2. ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - AdditionalEnvVariable: getSentinelEnvVariable(ctx, cr), + AdditionalEnvVariable: getSentinelEnvVariable(ctx, client, logger, cr), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars @@ -240,8 +239,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. } -func getSentinelEnvVariable(ctx context.Context, cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { - +func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { if cr.Spec.RedisSentinelConfig == nil { return &[]corev1.EnvVar{} } @@ -253,7 +251,7 @@ func getSentinelEnvVariable(ctx context.Context, cr *redisv1beta2.RedisSentinel) }, { Name: "IP", - Value: getRedisReplicationMasterIP(ctx, cr), + Value: getRedisReplicationMasterIP(ctx, client, logger, cr), }, { Name: "PORT", @@ -281,8 +279,7 @@ func getSentinelEnvVariable(ctx context.Context, cr *redisv1beta2.RedisSentinel) } -func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSentinel) string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) string { dClient, err := GenerateK8sDynamicClient(GenerateK8sConfig) if err != nil { logger.Error(err, "Failed to generate dynamic client") @@ -322,7 +319,7 @@ func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSent return "" } - masterPods := GetRedisNodesByRole(ctx, &replicationInstance, "master") + masterPods := GetRedisNodesByRole(ctx, client, logger, &replicationInstance, "master") if len(masterPods) == 0 { realMasterPod = "" @@ -331,7 +328,7 @@ func getRedisReplicationMasterIP(ctx context.Context, cr *redisv1beta2.RedisSent } else if len(masterPods) == 1 { realMasterPod = masterPods[0] } else { - realMasterPod = checkAttachedSlave(ctx, &replicationInstance, masterPods) + realMasterPod = checkAttachedSlave(ctx, client, logger, &replicationInstance, masterPods) } realMasterInfo := RedisDetails{ diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index 883bc78d5..9aedb48b4 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -8,6 +8,7 @@ import ( common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -182,7 +183,7 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { t.Fatalf("Failed to unmarshal file %s: %v", path, err) } - actual := generateRedisSentinelContainerParams(context.TODO(), input, nil, nil) + actual := generateRedisSentinelContainerParams(context.TODO(), nil, logr.Logger{}, input, nil, nil) assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index dda5aabef..a34a7934a 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -14,6 +14,7 @@ import ( redis "github.com/redis/go-redis/v9" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/remotecommand" ) @@ -92,13 +93,12 @@ func CreateMultipleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { } // ExecuteRedisClusterCommand will execute redis cluster creation command -func ExecuteRedisClusterCommand(ctx context.Context, cr *redisv1beta2.RedisCluster) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func ExecuteRedisClusterCommand(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { var cmd []string replicas := cr.Spec.GetReplicaCounts("leader") switch int(replicas) { case 1: - err := executeFailoverCommand(ctx, cr, "leader") + err := executeFailoverCommand(ctx, client, logger, cr, "leader") if err != nil { logger.Error(err, "error executing failover command") } @@ -108,7 +108,7 @@ func ExecuteRedisClusterCommand(ctx context.Context, cr *redisv1beta2.RedisClust } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -133,8 +133,7 @@ func getRedisTLSArgs(tlsConfig *redisv1beta2.TLSConfig, clientHost string) []str } // createRedisReplicationCommand will create redis replication creation command -func createRedisReplicationCommand(cr *redisv1beta2.RedisCluster, leaderPod RedisDetails, followerPod RedisDetails) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, leaderPod RedisDetails, followerPod RedisDetails) []string { cmd := []string{"redis-cli", "--cluster", "add-node"} if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(followerPod, cr, "follower")+":6379") @@ -146,7 +145,7 @@ func createRedisReplicationCommand(cr *redisv1beta2.RedisCluster, leaderPod Redi cmd = append(cmd, "--cluster-slave") if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } @@ -159,14 +158,13 @@ func createRedisReplicationCommand(cr *redisv1beta2.RedisCluster, leaderPod Redi } // ExecuteRedisReplicationCommand will execute the replication command -func ExecuteRedisReplicationCommand(ctx context.Context, cr *redisv1beta2.RedisCluster) { +func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { var podIP string - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) followerCounts := cr.Spec.GetReplicaCounts("follower") leaderCounts := cr.Spec.GetReplicaCounts("leader") followerPerLeader := followerCounts / leaderCounts - nodes := checkRedisCluster(ctx, cr) + nodes := checkRedisCluster(ctx, client, logger, cr) for followerIdx := 0; followerIdx <= int(followerCounts)-1; { for i := 0; i < int(followerPerLeader) && followerIdx <= int(followerCounts)-1; i++ { followerPod := RedisDetails{ @@ -180,8 +178,8 @@ func ExecuteRedisReplicationCommand(ctx context.Context, cr *redisv1beta2.RedisC podIP = getRedisServerIP(followerPod) if !checkRedisNodePresence(cr, nodes, podIP) { logger.V(1).Info("Adding node to cluster.", "Node.IP", podIP, "Follower.Pod", followerPod) - cmd := createRedisReplicationCommand(cr, leaderPod, followerPod) - redisClient := configureRedisClient(cr, followerPod.PodName) + cmd := createRedisReplicationCommand(client, logger, cr, leaderPod, followerPod) + redisClient := configureRedisClient(client, logger, cr, followerPod.PodName) pong, err := redisClient.Ping(ctx).Result() redisClient.Close() if err != nil { @@ -203,13 +201,11 @@ func ExecuteRedisReplicationCommand(ctx context.Context, cr *redisv1beta2.RedisC } // checkRedisCluster will check the redis cluster have sufficient nodes or not -func checkRedisCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) [][]string { - var client *redis.Client - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - client = configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0") - defer client.Close() +func checkRedisCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) [][]string { + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() cmd := redis.NewStringCmd(ctx, "cluster", "nodes") - err := client.Process(ctx, cmd) + err := redisClient.Process(ctx, cmd) if err != nil { logger.Error(err, "Redis command failed with this error") } @@ -231,14 +227,13 @@ func checkRedisCluster(ctx context.Context, cr *redisv1beta2.RedisCluster) [][]s } // ExecuteFailoverOperation will execute redis failover operations -func ExecuteFailoverOperation(ctx context.Context, cr *redisv1beta2.RedisCluster) error { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - err := executeFailoverCommand(ctx, cr, "leader") +func ExecuteFailoverOperation(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { + err := executeFailoverCommand(ctx, client, logger, cr, "leader") if err != nil { logger.Error(err, "Redis command failed for leader nodes") return err } - err = executeFailoverCommand(ctx, cr, "follower") + err = executeFailoverCommand(ctx, client, logger, cr, "follower") if err != nil { logger.Error(err, "Redis command failed for follower nodes") return err @@ -247,13 +242,12 @@ func ExecuteFailoverOperation(ctx context.Context, cr *redisv1beta2.RedisCluster } // executeFailoverCommand will execute failover command -func executeFailoverCommand(ctx context.Context, cr *redisv1beta2.RedisCluster, role string) error { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func executeFailoverCommand(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, role string) error { replicas := cr.Spec.GetReplicaCounts(role) podName := fmt.Sprintf("%s-%s-", cr.ObjectMeta.Name, role) for podCount := 0; podCount <= int(replicas)-1; podCount++ { logger.V(1).Info("Executing redis failover operations", "Redis Node", podName+strconv.Itoa(podCount)) - client := configureRedisClient(cr, podName+strconv.Itoa(podCount)) + client := configureRedisClient(client, logger, cr, podName+strconv.Itoa(podCount)) defer client.Close() cmd := redis.NewStringCmd(ctx, "cluster", "reset") err := client.Process(ctx, cmd) @@ -282,10 +276,9 @@ func executeFailoverCommand(ctx context.Context, cr *redisv1beta2.RedisCluster, } // CheckRedisNodeCount will check the count of redis nodes -func CheckRedisNodeCount(ctx context.Context, cr *redisv1beta2.RedisCluster, nodeType string) int32 { +func CheckRedisNodeCount(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeType string) int32 { var redisNodeType string - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - clusterNodes := checkRedisCluster(ctx, cr) + clusterNodes := checkRedisCluster(ctx, client, logger, cr) count := len(clusterNodes) switch nodeType { @@ -311,11 +304,9 @@ func CheckRedisNodeCount(ctx context.Context, cr *redisv1beta2.RedisCluster, nod } // CheckRedisClusterState will check the redis cluster state -func CheckRedisClusterState(ctx context.Context, cr *redisv1beta2.RedisCluster) int { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - clusterNodes := checkRedisCluster(ctx, cr) +func CheckRedisClusterState(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) int { + clusterNodes := checkRedisCluster(ctx, client, logger, cr) count := 0 - for _, node := range clusterNodes { if strings.Contains(node[2], "fail") || strings.Contains(node[7], "disconnected") { count++ @@ -326,34 +317,33 @@ func CheckRedisClusterState(ctx context.Context, cr *redisv1beta2.RedisCluster) } // configureRedisClient will configure the Redis Client -func configureRedisClient(cr *redisv1beta2.RedisCluster, podName string) *redis.Client { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, podName string) *redis.Client { redisInfo := RedisDetails{ PodName: podName, Namespace: cr.Namespace, } - var client *redis.Client + var redisClient *redis.Client if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } - client = redis.NewClient(&redis.Options{ + redisClient = redis.NewClient(&redis.Options{ Addr: getRedisServerIP(redisInfo) + ":6379", Password: pass, DB: 0, - TLSConfig: getRedisTLSConfig(cr, redisInfo), + TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), }) } else { - client = redis.NewClient(&redis.Options{ + redisClient = redis.NewClient(&redis.Options{ Addr: getRedisServerIP(redisInfo) + ":6379", Password: "", DB: 0, - TLSConfig: getRedisTLSConfig(cr, redisInfo), + TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), }) } - return client + return redisClient } // executeCommand will execute the commands in pod @@ -448,39 +438,37 @@ func generateRedisManagerLogger(namespace, name string) logr.Logger { } // configureRedisClient will configure the Redis Client -func configureRedisReplicationClient(cr *redisv1beta2.RedisReplication, podName string) *redis.Client { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, podName string) *redis.Client { redisInfo := RedisDetails{ PodName: podName, Namespace: cr.Namespace, } - var client *redis.Client + var redisClient *redis.Client if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } - client = redis.NewClient(&redis.Options{ + redisClient = redis.NewClient(&redis.Options{ Addr: getRedisServerIP(redisInfo) + ":6379", Password: pass, DB: 0, - TLSConfig: getRedisReplicationTLSConfig(cr, redisInfo), + TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), }) } else { - client = redis.NewClient(&redis.Options{ + redisClient = redis.NewClient(&redis.Options{ Addr: getRedisServerIP(redisInfo) + ":6379", Password: "", DB: 0, - TLSConfig: getRedisReplicationTLSConfig(cr, redisInfo), + TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), }) } - return client + return redisClient } // Get Redis nodes by it's role i.e. master, slave and sentinel -func GetRedisNodesByRole(ctx context.Context, cr *redisv1beta2.RedisReplication, redisRole string) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func GetRedisNodesByRole(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, redisRole string) []string { statefulset, err := GetStatefulSet(cr.Namespace, cr.Name) if err != nil { logger.Error(err, "Failed to Get the Statefulset of the", "custom resource", cr.Name, "in namespace", cr.Namespace) @@ -492,7 +480,7 @@ func GetRedisNodesByRole(ctx context.Context, cr *redisv1beta2.RedisReplication, for i := 0; i < int(replicas); i++ { podName := statefulset.Name + "-" + strconv.Itoa(i) - podRole := checkRedisServerRole(ctx, cr, podName) + podRole := checkRedisServerRole(ctx, client, logger, cr, podName) if podRole == redisRole { pods = append(pods, podName) } @@ -502,10 +490,8 @@ func GetRedisNodesByRole(ctx context.Context, cr *redisv1beta2.RedisReplication, } // Check the Redis Server Role i.e. master, slave and sentinel -func checkRedisServerRole(ctx context.Context, cr *redisv1beta2.RedisReplication, podName string) string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - - redisClient := configureRedisReplicationClient(cr, podName) +func checkRedisServerRole(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, podName string) string { + redisClient := configureRedisReplicationClient(client, logger, cr, podName) defer redisClient.Close() info, err := redisClient.Info(ctx, "replication").Result() if err != nil { @@ -525,13 +511,10 @@ func checkRedisServerRole(ctx context.Context, cr *redisv1beta2.RedisReplication } // checkAttachedSlave would return redis pod name which has slave -func checkAttachedSlave(ctx context.Context, cr *redisv1beta2.RedisReplication, masterPods []string) string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - +func checkAttachedSlave(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string) string { for _, podName := range masterPods { - connected_slaves := "" - redisClient := configureRedisReplicationClient(cr, podName) + redisClient := configureRedisReplicationClient(client, logger, cr, podName) defer redisClient.Close() info, err := redisClient.Info(ctx, "replication").Result() if err != nil { @@ -558,11 +541,9 @@ func checkAttachedSlave(ctx context.Context, cr *redisv1beta2.RedisReplication, } -func CreateMasterSlaveReplication(ctx context.Context, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - +func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { var realMasterPod string - realMasterPod = checkAttachedSlave(ctx, cr, masterPods) + realMasterPod = checkAttachedSlave(ctx, client, logger, cr, masterPods) if len(slavePods) < 1 { realMasterPod = masterPods[0] @@ -580,7 +561,7 @@ func CreateMasterSlaveReplication(ctx context.Context, cr *redisv1beta2.RedisRep for i := 0; i < len(masterPods); i++ { if masterPods[i] != realMasterPod { - redisClient := configureRedisReplicationClient(cr, masterPods[i]) + redisClient := configureRedisReplicationClient(client, logger, cr, masterPods[i]) defer redisClient.Close() logger.V(1).Info("Setting the", "pod", masterPods[i], "to slave of", realMasterPod) err := redisClient.SlaveOf(ctx, realMasterPodIP, "6379").Err() diff --git a/k8sutils/secrets.go b/k8sutils/secrets.go index 4636b54b0..40f3853fe 100644 --- a/k8sutils/secrets.go +++ b/k8sutils/secrets.go @@ -4,24 +4,20 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "strings" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" logf "sigs.k8s.io/controller-runtime/pkg/log" ) var log = logf.Log.WithName("controller_redis") -// getRedisPassword method will return the redis password -func getRedisPassword(namespace, name, secretKey string) (string, error) { - logger := secretLogger(namespace, name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return "", err - } +// getRedisPassword method will return the redis password from the secret +func getRedisPassword(client kubernetes.Interface, logger logr.Logger, namespace, name, secretKey string) (string, error) { secretName, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { logger.Error(err, "Failed in getting existing secret for redis") @@ -35,110 +31,89 @@ func getRedisPassword(namespace, name, secretKey string) (string, error) { return "", nil } -func secretLogger(namespace string, name string) logr.Logger { - reqLogger := log.WithValues("Request.Secret.Namespace", namespace, "Request.Secret.Name", name) - return reqLogger -} - -func getRedisTLSConfig(cr *redisv1beta2.RedisCluster, redisInfo RedisDetails) *tls.Config { - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - return nil - } +func getRedisTLSConfig(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, redisInfo RedisDetails) *tls.Config { if cr.Spec.TLS != nil { - reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name) - secretName, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) + secret, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) if err != nil { - reqLogger.Error(err, "Failed in getting TLS secret for redis") + logger.Error(err, "Failed in getting TLS secret for redis cluster") + logger.V(1).Error(err, "Failed in getting TLS secret for redis cluster", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisClusterName", cr.Name) + return nil } - var ( - tlsClientCert []byte - tlsClientKey []byte - tlsCaCertificate []byte - tlsCaCertificates *x509.CertPool - tlsClientCertificates []tls.Certificate - ) - for key, value := range secretName.Data { - if key == cr.Spec.TLS.CaKeyFile || key == "ca.crt" { - tlsCaCertificate = value - } else if key == cr.Spec.TLS.CertKeyFile || key == "tls.crt" { - tlsClientCert = value - } else if key == cr.Spec.TLS.KeyFile || key == "tls.key" { - tlsClientKey = value - } + tlsClientCert, certExists := secret.Data["tls.crt"] + tlsClientKey, keyExists := secret.Data["tls.key"] + tlsCaCertificate, caExists := secret.Data["ca.crt"] + + if !certExists || !keyExists || !caExists { + logger.Error(errors.New("required TLS keys are missing in the secret"), "Missing TLS keys in the secret") + return nil } cert, err := tls.X509KeyPair(tlsClientCert, tlsClientKey) if err != nil { - reqLogger.Error(err, "Couldn't load TLS client key pair") + logger.Error(err, "Couldn't load TLS client key pair") + logger.V(1).Error(err, "Couldn't load TLS client key pair", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisClusterName", cr.Name) + return nil } - tlsClientCertificates = append(tlsClientCertificates, cert) - tlsCaCertificates = x509.NewCertPool() + tlsCaCertificates := x509.NewCertPool() ok := tlsCaCertificates.AppendCertsFromPEM(tlsCaCertificate) if !ok { - reqLogger.V(1).Info("Failed to load CA Certificates from Secret") + logger.Error(errors.New("failed to load CA Certificates from secret"), "Invalid CA Certificates") + logger.V(1).Error(err, "Invalid CA Certificates", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisClusterName", cr.Name) + return nil } return &tls.Config{ - Certificates: tlsClientCertificates, + Certificates: []tls.Certificate{cert}, ServerName: redisInfo.PodName, RootCAs: tlsCaCertificates, - MinVersion: 2, - ClientAuth: 0, + MinVersion: tls.VersionTLS12, + ClientAuth: tls.NoClientCert, } } return nil } -func getRedisReplicationTLSConfig(cr *redisv1beta2.RedisReplication, redisInfo RedisDetails) *tls.Config { - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - return nil - } +func getRedisReplicationTLSConfig(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, redisInfo RedisDetails) *tls.Config { if cr.Spec.TLS != nil { - reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name) - secretName, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) + secret, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) if err != nil { - reqLogger.Error(err, "Failed in getting TLS secret for redis") + logger.Error(err, "Failed in getting TLS secret for redis replication") + logger.V(1).Error(err, "Failed in getting TLS secret for redis replication", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisReplicationName", cr.Name) + return nil } - var ( - tlsClientCert []byte - tlsClientKey []byte - tlsCaCertificate []byte - tlsCaCertificates *x509.CertPool - tlsClientCertificates []tls.Certificate - ) - for key, value := range secretName.Data { - if key == cr.Spec.TLS.CaKeyFile || key == "ca.crt" { - tlsCaCertificate = value - } else if key == cr.Spec.TLS.CertKeyFile || key == "tls.crt" { - tlsClientCert = value - } else if key == cr.Spec.TLS.KeyFile || key == "tls.key" { - tlsClientKey = value - } + tlsClientCert, certExists := secret.Data["tls.crt"] + tlsClientKey, keyExists := secret.Data["tls.key"] + tlsCaCertificate, caExists := secret.Data["ca.crt"] + + if !certExists || !keyExists || !caExists { + logger.Error(errors.New("required TLS keys are missing in the secret"), "Missing TLS keys in the secret") + return nil } cert, err := tls.X509KeyPair(tlsClientCert, tlsClientKey) if err != nil { - reqLogger.Error(err, "Couldn't load TLS client key pair") + logger.Error(err, "Couldn't load TLS client key pair") + logger.V(1).Error(err, "Couldn't load TLS client key pair", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisReplicationName", cr.Name) + return nil } - tlsClientCertificates = append(tlsClientCertificates, cert) - tlsCaCertificates = x509.NewCertPool() + tlsCaCertificates := x509.NewCertPool() ok := tlsCaCertificates.AppendCertsFromPEM(tlsCaCertificate) if !ok { - reqLogger.V(1).Info("Failed to load CA Certificates from Secret") + logger.Error(errors.New("failed to load CA Certificates from secret"), "Invalid CA Certificates") + logger.V(1).Error(err, "Invalid CA Certificates", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisReplicationName", cr.Name) + return nil } return &tls.Config{ - Certificates: tlsClientCertificates, + Certificates: []tls.Certificate{cert}, ServerName: redisInfo.PodName, RootCAs: tlsCaCertificates, - MinVersion: 2, - ClientAuth: 0, + MinVersion: tls.VersionTLS12, + ClientAuth: tls.NoClientCert, } } return nil diff --git a/k8sutils/secrets_test.go b/k8sutils/secrets_test.go new file mode 100644 index 000000000..e8ae83fe3 --- /dev/null +++ b/k8sutils/secrets_test.go @@ -0,0 +1,382 @@ +package k8sutils + +import ( + "os" + "path/filepath" + "testing" + + common "github.com/OT-CONTAINER-KIT/redis-operator/api" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr/testr" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sClientFake "k8s.io/client-go/kubernetes/fake" +) + +func Test_getRedisPassword(t *testing.T) { + tests := []struct { + name string + setup func() *k8sClientFake.Clientset + namespace string + secretName string + secretKey string + expected string + expectedErr bool + }{ + { + name: "successful retrieval", + setup: func() *k8sClientFake.Clientset { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "password": []byte("secret-password"), + }, + } + client := k8sClientFake.NewSimpleClientset(secret.DeepCopyObject()) + return client + }, + namespace: "default", + secretName: "redis-secret", + secretKey: "password", + expected: "secret-password", + expectedErr: false, + }, + { + name: "secret not found", + setup: func() *k8sClientFake.Clientset { + client := k8sClientFake.NewSimpleClientset() + return client + }, + namespace: "default", + secretName: "non-existent", + secretKey: "password", + expected: "", + expectedErr: true, + }, + { + name: "secret exists but key is missing", + setup: func() *k8sClientFake.Clientset { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "anotherKey": []byte("some-value"), + }, + } + client := k8sClientFake.NewSimpleClientset(secret.DeepCopyObject()) + return client + }, + namespace: "default", + secretName: "redis-secret", + secretKey: "missingKey", + expected: "", + expectedErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := tt.setup() + logger := testr.New(t) + got, err := getRedisPassword(client, logger, tt.namespace, tt.secretName, tt.secretKey) + + if tt.expectedErr { + require.Error(t, err, "Expected an error but didn't get one") + } else { + require.NoError(t, err, "Expected no error but got one") + assert.Equal(t, tt.expected, got, "Expected and actual values do not match") + } + }) + } +} + +func Test_getRedisTLSConfig(t *testing.T) { + tests := []struct { + name string + setup func() *k8sClientFake.Clientset + redisCluster *redisv1beta2.RedisCluster + redisInfo RedisDetails + expectTLS bool + }{ + { + name: "TLS enabled and successful configuration", + setup: func() *k8sClientFake.Clientset { + tlsSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-tls-secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "ca.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "ca.crt")), + "tls.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "tls.crt")), + "tls.key": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "tls.key")), + }, + } + client := k8sClientFake.NewSimpleClientset(tlsSecret) + return client + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + TLS: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.crt", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-secret", + }, + }, + }, + }, + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectTLS: true, + }, + { + name: "TLS enabled but secret not found", + setup: func() *k8sClientFake.Clientset { + client := k8sClientFake.NewSimpleClientset() + return client + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + TLS: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.crt", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-secret", + }, + }, + }, + }, + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectTLS: false, + }, + { + name: "TLS enabled but incomplete secret", + setup: func() *k8sClientFake.Clientset { + tlsSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-tls-secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "ca.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "ca.crt")), + // Missing tls.crt and tls.key + }, + } + client := k8sClientFake.NewSimpleClientset(tlsSecret) + return client + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + TLS: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.crt", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-secret", + }, + }, + }, + }, + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectTLS: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := tt.setup() + logger := testr.New(t) + tlsConfig := getRedisTLSConfig(client, logger, tt.redisCluster, tt.redisInfo) + + if tt.expectTLS { + require.NotNil(t, tlsConfig, "Expected TLS configuration but got nil") + require.NotEmpty(t, tlsConfig.Certificates, "TLS Certificates should not be empty") + require.NotNil(t, tlsConfig.RootCAs, "Root CAs should not be nil") + } else { + assert.Nil(t, tlsConfig, "Expected no TLS configuration but got one") + } + }) + } +} + +func Test_getRedisReplicationTLSConfig(t *testing.T) { + tests := []struct { + name string + setup func() *k8sClientFake.Clientset + redisReplication *redisv1beta2.RedisReplication + redisInfo RedisDetails + expectTLS bool + }{ + { + name: "TLS enabled and successful configuration", + setup: func() *k8sClientFake.Clientset { + tlsSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-tls-secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "ca.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "ca.crt")), + "tls.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "tls.crt")), + "tls.key": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "tls.key")), + }, + } + client := k8sClientFake.NewSimpleClientset(tlsSecret) + return client + }, + redisReplication: &redisv1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisReplicationSpec{ + TLS: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.crt", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-secret", + }, + }, + }, + }, + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectTLS: true, + }, + { + name: "TLS enabled but secret not found", + setup: func() *k8sClientFake.Clientset { + client := k8sClientFake.NewSimpleClientset() + return client + }, + redisReplication: &redisv1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisReplicationSpec{ + TLS: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.crt", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-secret", + }, + }, + }, + }, + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectTLS: false, + }, + { + name: "TLS enabled but incomplete secret", + setup: func() *k8sClientFake.Clientset { + tlsSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-tls-secret", + Namespace: "default", + }, + Data: map[string][]byte{ + "ca.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "ca.crt")), + // Missing tls.crt and tls.key + }, + } + client := k8sClientFake.NewSimpleClientset(tlsSecret) + return client + }, + redisReplication: &redisv1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisReplicationSpec{ + TLS: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "ca.crt", + CertKeyFile: "tls.crt", + KeyFile: "tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "redis-tls-secret", + }, + }, + }, + }, + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectTLS: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := tt.setup() + logger := testr.New(t) + tlsConfig := getRedisReplicationTLSConfig(client, logger, tt.redisReplication, tt.redisInfo) + + if tt.expectTLS { + require.NotNil(t, tlsConfig, "Expected TLS configuration but got nil") + require.NotEmpty(t, tlsConfig.Certificates, "TLS Certificates should not be empty") + require.NotNil(t, tlsConfig.RootCAs, "Root CAs should not be nil") + } else { + assert.Nil(t, tlsConfig, "Expected no TLS configuration but got one") + } + }) + } +} + +func helperReadFile(filename string) []byte { + data, err := os.ReadFile(filename) + if err != nil { + panic(err) + } + return data +} diff --git a/k8sutils/status.go b/k8sutils/status.go index 3cc32353d..d652ad7c7 100644 --- a/k8sutils/status.go +++ b/k8sutils/status.go @@ -27,6 +27,10 @@ func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.Redis cr.Status.ReadyFollowerReplicas = readyFollowerReplicas client, err := GenerateK8sDynamicClient(GenerateK8sConfig) + if err != nil { + logger.Error(err, "Failed to generate k8s dynamic client") + return err + } gvr := schema.GroupVersionResource{ Group: "redis.redis.opstreelabs.in", Version: "v1beta2", diff --git a/tests/testdata/secrets/ca.crt b/tests/testdata/secrets/ca.crt new file mode 100644 index 000000000..483acebbe --- /dev/null +++ b/tests/testdata/secrets/ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/zCCAeegAwIBAgIULZgkEyKSTUyz9TPluGHMKp3kXMkwDQYJKoZIhvcNAQEL +BQAwDzENMAsGA1UEAwwETXlDQTAeFw0yMzExMTAyMjQzNDdaFw0yNDExMDkyMjQz +NDdaMA8xDTALBgNVBAMMBE15Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCdvMDZNyA9XM7TLcWzV3GfT8obuQgrCPyAEREEngprCMe1JjtilYCAthZD +062FG6KtQYf5Ph+TCpxrm1x8cdbHBOMoogjJ3tOrKgg/sDqDIBJY5qqeoti1Sps5 +UGLlw8fmgAQIJ3Jie9dlgYtk7HkEFSfuHqHhozsInHkrHDhFAyYNKRf/UwNZvkcB +2st8SJJaC56Pxn5SP97kfBUc0K9dwsFIo5l8y/WWJ31M3CLNuIzBP6JgGdIHq8Fe +pvW3YtWOBRptjse5soZrXW3I6k1SqkkWMM6dvSJobmN5uarn2fFfQI+kYpX1Hx67 +I9sUYeDUVDyeVDyE9y5U7q3kLacNAgMBAAGjUzBRMB0GA1UdDgQWBBROkKWbx7zB +6KAGXCmh0SGNsgZeaTAfBgNVHSMEGDAWgBROkKWbx7zB6KAGXCmh0SGNsgZeaTAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBMvROzFeMPm52B8A9f +pinakVzXbLlQnhmYvevnIZ6jXKCxycp0Ompu/TqqyfpKJ0gJChPCVF2nWHkI6suR +FYI9m3ZXKUqafYlienFbJXmJxWt9V+jt4kBbIja+/ETdl8Vmbc7MIQ7eZS6XMJa9 +tkEB4yCOj72p3DmC/bJSa4zp0ng/AoATA7GPmm+l1hEMDLd+mtosMtev0DWDyF0j +acrlBvRv4Eq6kFuBBzcPqKC2DuFWIU/ZCBkwn2tScPEf0UjZUXl74k9Taz37Av9Z +KQByaF94pYf/7kPRIn2Zw0xXRTJ0wD9bi4Q6YfnN/ntrcs1CNKWb4MMbU2gnz0RN +zCjC +-----END CERTIFICATE----- diff --git a/tests/testdata/secrets/tls.crt b/tests/testdata/secrets/tls.crt new file mode 100644 index 000000000..b60b071aa --- /dev/null +++ b/tests/testdata/secrets/tls.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICqTCCAZECFCMWUrMjKUyph+9nVeNaq9ulIuSFMA0GCSqGSIb3DQEBCwUAMA8x +DTALBgNVBAMMBE15Q0EwHhcNMjMxMTEwMjI0NDEyWhcNMjQxMTA5MjI0NDEyWjAT +MREwDwYDVQQDDAhNeVNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBANsG8xaUF22cRbBZaMCjcuC3D8HHFPmmJI6xCF/MVg9+0afVG9uGpjpcOa8Q +wPD9MRHx8+abAUpR2JwWeYzCwLem+oY+gNPpSzshNUimlonrFnhq3d9OKpLHPC56 +5z1SUctBKlEqHvsV+Y+0xto2tXNDfdrjlKm+DaydFfe9G9BUaZGtjqljD2Yq95Qn +7Qf8bL2Sc5TLSztg/BH+zJmSsC8t4O4qs3iolaZ4kpCrDu4vy2X2V9ybqFPNCFyp +wZB1jLq2RzCcdxFUfYm0a83+LDvqgezXRwB29ZGsbTtb/L/HFkwIt+tqNeVWw+hI +HzRZ7lqI5W+8CpiM2xtJ8qpgs20CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEARjOw +dKDN9fIC8pabrZaXUPUFHwaB3jKrv5B/k4IkI+7VMz7t1mQ7fP+Ryuyinws3VpLh +DEeMyZ+a4gzcMvuxz9RL/p6B9gIVpebknfmTNZPqvSCg2kY9HCTUpsh5AawaGInN +iZ2Iw/MKLJEVxOxNRPzeKE6bHqvO6dijUGrB++XugrGVwMQjMZsJuu6bN7CYRgsA +OoRKohDkhaKsW/RkGIYDIxqm+zsPv69PTALlUXJtgnlkvNc6F5Fd5pwuW8TJ/wLe +eyQM56RaW2OInIOO4ehJkgRnLdukkECvYEwlZD3RgGFvUIGZFZXDS7FvpzZaUmdz +XtNWJjYUsc8d8iljTQ== +-----END CERTIFICATE----- diff --git a/tests/testdata/secrets/tls.key b/tests/testdata/secrets/tls.key new file mode 100644 index 000000000..485f0189c --- /dev/null +++ b/tests/testdata/secrets/tls.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbBvMWlBdtnEWw +WWjAo3Lgtw/BxxT5piSOsQhfzFYPftGn1RvbhqY6XDmvEMDw/TER8fPmmwFKUdic +FnmMwsC3pvqGPoDT6Us7ITVIppaJ6xZ4at3fTiqSxzwueuc9UlHLQSpRKh77FfmP +tMbaNrVzQ33a45Spvg2snRX3vRvQVGmRrY6pYw9mKveUJ+0H/Gy9knOUy0s7YPwR +/syZkrAvLeDuKrN4qJWmeJKQqw7uL8tl9lfcm6hTzQhcqcGQdYy6tkcwnHcRVH2J +tGvN/iw76oHs10cAdvWRrG07W/y/xxZMCLfrajXlVsPoSB80We5aiOVvvAqYjNsb +SfKqYLNtAgMBAAECggEAM82ifBIdsm6WKv4SoRFnj8+sWeQoyV0q41bqyKGvLy4L +D1t/ob3ongAHIqlfQQBZdUmZKs85kGboSQ6lxA2iAC3trgeld7mDciJKFHtWOpuQ +Ln30KSc3OY0G5mVqQN4x+1VX2WeReUh6xKr4p07uPqtVXoqaNEV/vXZP5k7jf7Ov +UHYKkyOvv4Zo+W+0JUrgTi9LO64OMPHkArHmZbaYvLensyoGH64yXWr9x16mQhaV +gBuXNzYHJchdVN51FyaF9xmNzFFD9j6kKjm5FiTuUbuw5NMwgNKuj9eRy5Cqf+ao +JkjEUZHq4aXmj/1VwAJ9c9ra0eaxUiVgbN8dZGycXwKBgQDzZe416Jh+pYGaTCyl +aac6uyNiMwTHDvjj5r/faa33leGYmn9rZrcQyNdh7LNkU4NTJnpl5ZlLGtny4wMd +MiKIXT2RwjL/WdRbuGjoYF9MJpWVB9Hu3c+UkeL7F5qppZ3sVk3oPG4dW3gA10pL +we7m+MQfVbJwLL0HxV0isHLxowKBgQDmXf+f8udN72xBtf9MybXs8tMx70KCX43X +b0RK5Qt76DYWQSjen3XVPKvIEOfPMMlcvxDNm+v0byMTif0E8Q4jCFVTY3pEhK4p +nXiL2FgXD6AcS0rWJBI0JHUl4otCfqF+5ouGgXBoYdLNHBM+I+hALn2r2qzbMJEu +QhbS38a3rwKBgG6+sysuIKyHK7gD7tB4iRFs8oWMxyC3TEGNzUGe+PvM42+m5FD+ +1E67w1wX8eu1H+ymdkyEskH8/qvH5LPVCudW3VvDq6aJvdjZyEnrB5FDgQ3lF/0C +SZ/E3Sz4KXQFGhzdi+ceD9AlvS1Mx84+eC/5gmrreBwYDw5JG75b4IDXAoGBAIqT +GtUdqhRQpN92WmfXos8xVuff1DNWxZ1FemBPHbRggECs26fnZltqTq9ftAIHh+l5 +qeL1G2ADhqcXR5O0adubBLDP01nqMlYoOr5s2rislpTOmers8eJZ1/p9J2ZNhFow +1teHf5Xa2pK1g8HKmcgZ71D0jyyfL4YTDWW2ZPRTAoGBAOZeKTvyjpYHDtV4fRbZ +WTwyMda9qjnQvDovPcm5ci1SEjJUCusJKNwoZiU9/xuU1P9t234qmNsmQV5Tpplg +aH139Yw8kz7u9z1o2ajO6rG7rQ5qUgYXHgEhIoRnkCfx4uekeaO5lgdwIDR0zC1I +BfJBeduDgVHEyYxEU78tprfc +-----END PRIVATE KEY----- From 697538ec33e64ed6cd69823f7d2901e428da92ec Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:02:36 +0530 Subject: [PATCH 058/203] test : Add redis_test.go (#702) * Add test Signed-off-by: Shubham Gupta * Add TestCreateMultipleLeaderRedisCommand Signed-off-by: Shubham Gupta * add TestGetRedisTLSArgs Signed-off-by: Shubham Gupta * createRedisReplicationCommand Signed-off-by: Shubham Gupta * Add test Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * add Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- k8sutils/cluster-scaling.go | 30 +-- k8sutils/redis-sentinel.go | 2 +- k8sutils/redis.go | 140 +++++++------ k8sutils/redis_test.go | 407 +++++++++++++++++++++++++++++++++++- mocks/utils/utils.go | 107 ++++++++++ 5 files changed, 603 insertions(+), 83 deletions(-) create mode 100644 mocks/utils/utils.go diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index 8304d0060..b0a384c02 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -32,7 +32,7 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(transferPOD, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(transferPOD)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, transferPOD)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -71,7 +71,7 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re logger.V(1).Info("Skipped the execution of", "Cmd", cmd) return } - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeID string) string { @@ -153,7 +153,7 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") } cmd = append(cmd, "--cluster-use-empty-masters") @@ -170,7 +170,7 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster rebalance command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-1") } func CheckIfEmptyMasters(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { @@ -205,7 +205,7 @@ func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr * if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -220,7 +220,7 @@ func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr * cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster rebalance command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-1") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-1") } // Add redis cluster node would add a node to the existing redis cluster using redis-cli @@ -243,8 +243,8 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log cmd = append(cmd, getRedisHostname(newPod, cr, "leader")+":6379") cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(newPod)+":6379") - cmd = append(cmd, getRedisServerIP(existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, newPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -259,7 +259,7 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster add-node command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader @@ -323,14 +323,14 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") } for _, followerNodeID := range followerNodeIDs { cmd = append(cmd, followerNodeID) logger.V(1).Info("Redis cluster follower remove command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") cmd = cmd[:len(cmd)-1] } } @@ -354,7 +354,7 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") } removePodNodeID := getRedisNodeID(ctx, client, logger, cr, removePod) @@ -375,7 +375,7 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface if getRedisClusterSlots(ctx, client, logger, cr, removePodNodeID) != "0" { logger.V(1).Info("Skipping execution remove leader not empty", "cmd", cmd) } - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } // verifyLeaderPod return true if the pod is leader/master @@ -415,7 +415,7 @@ func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger lo if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -430,5 +430,5 @@ func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger lo cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, slavePodName)...) logger.V(1).Info("Redis cluster failover command is", "Command", cmd) - executeCommand(cr, cmd, slavePodName) + executeCommand(client, logger, cr, cmd, slavePodName) } diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 42e96b38b..9977fa644 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -336,6 +336,6 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac Namespace: replicationNamespace, } - realMasterPodIP := getRedisServerIP(realMasterInfo) + realMasterPodIP := getRedisServerIP(client, logger, realMasterInfo) return realMasterPodIP } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index a34a7934a..51cb0a4e3 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -26,28 +26,31 @@ type RedisDetails struct { } // getRedisServerIP will return the IP of redis service -func getRedisServerIP(redisInfo RedisDetails) string { - logger := generateRedisManagerLogger(redisInfo.Namespace, redisInfo.PodName) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Error in getting k8s client") - return "" - } +func getRedisServerIP(client kubernetes.Interface, logger logr.Logger, redisInfo RedisDetails) string { + logger.V(1).Info("Fetching Redis pod", "namespace", redisInfo.Namespace, "podName", redisInfo.PodName) + redisPod, err := client.CoreV1().Pods(redisInfo.Namespace).Get(context.TODO(), redisInfo.PodName, metav1.GetOptions{}) if err != nil { - logger.Error(err, "Error in getting redis pod IP") + logger.Error(err, "Error in getting Redis pod IP", "namespace", redisInfo.Namespace, "podName", redisInfo.PodName) + return "" } redisIP := redisPod.Status.PodIP - // If we're NOT IPv4, assume were IPv6.. - if redisIP != "" { - if net.ParseIP(redisIP).To4() == nil { - logger.V(1).Info("Redis is IPv6", "ip", redisIP, "ipv6", net.ParseIP(redisIP).To16()) - redisIP = fmt.Sprintf("[%s]", redisIP) - } + logger.V(1).Info("Fetched Redis pod IP", "ip", redisIP) + + // Check if IP is empty + if redisIP == "" { + logger.V(1).Info("Redis pod IP is empty", "namespace", redisInfo.Namespace, "podName", redisInfo.PodName) + return "" + } + + // If we're NOT IPv4, assume we're IPv6.. + if net.ParseIP(redisIP).To4() == nil { + logger.V(1).Info("Redis is using IPv6", "ip", redisIP) + redisIP = fmt.Sprintf("[%s]", redisIP) } - logger.V(1).Info("Successfully got the ip for redis", "ip", redisIP) + logger.V(1).Info("Successfully got the IP for Redis", "ip", redisIP) return redisIP } @@ -58,37 +61,37 @@ func getRedisHostname(redisInfo RedisDetails, cr *redisv1beta2.RedisCluster, rol } // CreateSingleLeaderRedisCommand will create command for single leader cluster creation -func CreateSingleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func CreateSingleLeaderRedisCommand(logger logr.Logger, cr *redisv1beta2.RedisCluster) []string { cmd := []string{"redis-cli", "CLUSTER", "ADDSLOTS"} for i := 0; i < 16384; i++ { cmd = append(cmd, strconv.Itoa(i)) } + logger.V(1).Info("Generating Redis Add Slots command for single node cluster", + "BaseCommand", cmd[:3], + "SlotsRange", "0-16383", + "TotalSlots", 16384) - logger.V(1).Info("Redis Add Slots command for single node cluster is", "Command", cmd) return cmd } // CreateMultipleLeaderRedisCommand will create command for single leader cluster creation -func CreateMultipleLeaderRedisCommand(cr *redisv1beta2.RedisCluster) []string { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) +func CreateMultipleLeaderRedisCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) []string { cmd := []string{"redis-cli", "--cluster", "create"} replicas := cr.Spec.GetReplicaCounts("leader") - for podCount := 0; podCount <= int(replicas)-1; podCount++ { - pod := RedisDetails{ - PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount), - Namespace: cr.Namespace, - } - if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") + for podCount := 0; podCount < int(replicas); podCount++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount) + var address string + if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { + address = getRedisHostname(RedisDetails{PodName: podName, Namespace: cr.Namespace}, cr, "leader") + ":6379" } else { - cmd = append(cmd, getRedisServerIP(pod)+":6379") + address = getRedisServerIP(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}) + ":6379" } + cmd = append(cmd, address) } cmd = append(cmd, "--cluster-yes") - logger.V(1).Info("Redis Add Slots command for single node cluster is", "Command", cmd) + logger.V(1).Info("Redis cluster creation command", "CommandBase", cmd[:3], "Replicas", replicas) return cmd } @@ -102,9 +105,9 @@ func ExecuteRedisClusterCommand(ctx context.Context, client kubernetes.Interface if err != nil { logger.Error(err, "error executing failover command") } - cmd = CreateSingleLeaderRedisCommand(cr) + cmd = CreateSingleLeaderRedisCommand(logger, cr) default: - cmd = CreateMultipleLeaderRedisCommand(cr) + cmd = CreateMultipleLeaderRedisCommand(client, logger, cr) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -117,7 +120,7 @@ func ExecuteRedisClusterCommand(ctx context.Context, client kubernetes.Interface } cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster creation command is", "Command", cmd) - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } func getRedisTLSArgs(tlsConfig *redisv1beta2.TLSConfig, clientHost string) []string { @@ -135,25 +138,32 @@ func getRedisTLSArgs(tlsConfig *redisv1beta2.TLSConfig, clientHost string) []str // createRedisReplicationCommand will create redis replication creation command func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, leaderPod RedisDetails, followerPod RedisDetails) []string { cmd := []string{"redis-cli", "--cluster", "add-node"} - if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(followerPod, cr, "follower")+":6379") - cmd = append(cmd, getRedisHostname(leaderPod, cr, "leader")+":6379") + var followerAddress, leaderAddress string + + if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { + followerAddress = getRedisHostname(followerPod, cr, "follower") + ":6379" + leaderAddress = getRedisHostname(leaderPod, cr, "leader") + ":6379" } else { - cmd = append(cmd, getRedisServerIP(followerPod)+":6379") - cmd = append(cmd, getRedisServerIP(leaderPod)+":6379") + followerAddress = getRedisServerIP(client, logger, followerPod) + ":6379" + leaderAddress = getRedisServerIP(client, logger, leaderPod) + ":6379" } - cmd = append(cmd, "--cluster-slave") + + cmd = append(cmd, followerAddress, leaderAddress, "--cluster-slave") if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { - logger.Error(err, "Error in getting redis password") + logger.Error(err, "Failed to retrieve Redis password", "Secret", *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name) } - cmd = append(cmd, "-a") - cmd = append(cmd, pass) + cmd = append(cmd, "-a", pass) } + cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, leaderPod.PodName)...) - logger.V(2).Info("Redis replication creation command is", "Command", cmd) + + logger.V(1).Info("Generated Redis replication command", + "FollowerAddress", followerAddress, "LeaderAddress", leaderAddress, + "Command", cmd) + return cmd } @@ -175,7 +185,7 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(followerIdx)%int(leaderCounts)), Namespace: cr.Namespace, } - podIP = getRedisServerIP(followerPod) + podIP = getRedisServerIP(client, logger, followerPod) if !checkRedisNodePresence(cr, nodes, podIP) { logger.V(1).Info("Adding node to cluster.", "Node.IP", podIP, "Follower.Pod", followerPod) cmd := createRedisReplicationCommand(client, logger, cr, leaderPod, followerPod) @@ -187,7 +197,7 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter continue } if pong == "PONG" { - executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0") + executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") } else { logger.V(1).Info("Skipping execution of command due to failed Redis ping", "Follower.Pod", followerPod) } @@ -330,14 +340,14 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: pass, DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: "", DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), @@ -347,23 +357,17 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r } // executeCommand will execute the commands in pod -func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) { +func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, cmd []string, podName string) { var ( execOut bytes.Buffer execErr bytes.Buffer ) - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return - } config, err := GenerateK8sConfig() if err != nil { logger.Error(err, "Could not find pod to execute") return } - targetContainer, pod := getContainerID(cr, podName) + targetContainer, pod := getContainerID(client, logger, cr, podName) if targetContainer < 0 { logger.Error(err, "Could not find pod to execute") return @@ -395,26 +399,30 @@ func executeCommand(cr *redisv1beta2.RedisCluster, cmd []string, podName string) } // getContainerID will return the id of container from pod -func getContainerID(cr *redisv1beta2.RedisCluster, podName string) (int, *corev1.Pod) { - logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return -1, nil - } +func getContainerID(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, podName string) (int, *corev1.Pod) { pod, err := client.CoreV1().Pods(cr.Namespace).Get(context.TODO(), podName, metav1.GetOptions{}) if err != nil { - logger.Error(err, "Could not get pod info") + logger.Error(err, "Could not get pod info", "Pod Name", podName, "Namespace", cr.Namespace) + return -1, nil } + logger.Info("Pod info retrieved successfully", "Pod Name", podName, "Namespace", cr.Namespace) + targetContainer := -1 for containerID, tr := range pod.Spec.Containers { - logger.V(1).Info("Pod Counted successfully", "Count", containerID, "Container Name", tr.Name) + logger.V(1).Info("Inspecting container", "Pod Name", podName, "Container ID", containerID, "Container Name", tr.Name) if tr.Name == cr.ObjectMeta.Name+"-leader" { targetContainer = containerID + logger.Info("Leader container found", "Container ID", containerID, "Container Name", tr.Name) break } } + + if targetContainer == -1 { + logger.Info("Leader container not found in pod", "Pod Name", podName) + return -1, nil + } + return targetContainer, pod } @@ -451,14 +459,14 @@ func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Lo logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: pass, DB: 0, TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", Password: "", DB: 0, TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), @@ -556,7 +564,7 @@ func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interfa Namespace: cr.Namespace, } - realMasterPodIP := getRedisServerIP(realMasterInfo) + realMasterPodIP := getRedisServerIP(client, logger, realMasterInfo) for i := 0; i < len(masterPods); i++ { if masterPods[i] != realMasterPod { diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 3028796dd..26628290d 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -1,4 +1,3 @@ -// checkRedisNodePresence package k8sutils import ( @@ -8,6 +7,13 @@ import ( "testing" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + mock_utils "github.com/OT-CONTAINER-KIT/redis-operator/mocks/utils" + "github.com/go-logr/logr/testr" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sClientFake "k8s.io/client-go/kubernetes/fake" + "k8s.io/utils/pointer" ) func TestCheckRedisNodePresence(t *testing.T) { @@ -38,3 +44,402 @@ func TestCheckRedisNodePresence(t *testing.T) { }) } } + +func TestGetRedisServerIP(t *testing.T) { + tests := []struct { + name string + setup func() *k8sClientFake.Clientset + redisInfo RedisDetails + expectedIP string + expectEmpty bool + }{ + { + name: "Successfully retrieve IPv4 address", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "192.168.1.1", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectedIP: "192.168.1.1", + expectEmpty: false, + }, + { + name: "Successfully retrieve IPv6 address", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectedIP: "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", + expectEmpty: false, + }, + { + name: "Error retrieving pod results in empty IP", + setup: func() *k8sClientFake.Clientset { + client := k8sClientFake.NewSimpleClientset() + return client + }, + redisInfo: RedisDetails{ + PodName: "nonexistent-pod", + Namespace: "default", + }, + expectEmpty: true, + }, + { + name: "Empty results in empty IP", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectEmpty: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := tt.setup() + logger := testr.New(t) + redisIP := getRedisServerIP(client, logger, tt.redisInfo) + + if tt.expectEmpty { + assert.Empty(t, redisIP, "Expected an empty IP address") + } else { + assert.Equal(t, tt.expectedIP, redisIP, "Expected and actual IP do not match") + } + }) + } +} + +func TestGetRedisHostname(t *testing.T) { + tests := []struct { + name string + redisInfo RedisDetails + redisCluster *redisv1beta2.RedisCluster + role string + expected string + }{ + { + name: "standard configuration", + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster", + Namespace: "default", + }, + }, + role: "master", + expected: "redis-pod.mycluster-master-headless.default.svc", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + fqdn := getRedisHostname(tt.redisInfo, tt.redisCluster, tt.role) + assert.Equal(t, tt.expected, fqdn, "FQDN should match the expected output") + }) + } +} + +func TestCreateSingleLeaderRedisCommand(t *testing.T) { + logger := testr.New(t) + cr := &redisv1beta2.RedisCluster{} + cmd := CreateSingleLeaderRedisCommand(logger, cr) + + assert.Equal(t, "redis-cli", cmd[0]) + assert.Equal(t, "CLUSTER", cmd[1]) + assert.Equal(t, "ADDSLOTS", cmd[2]) + + expectedLength := 16384 + 3 + + assert.Equal(t, expectedLength, len(cmd)) + assert.Equal(t, "0", cmd[3]) + assert.Equal(t, "16383", cmd[expectedLength-1]) +} + +func TestCreateMultipleLeaderRedisCommand(t *testing.T) { + tests := []struct { + name string + redisCluster *redisv1beta2.RedisCluster + expectedCommands []string + }{ + { + name: "Multiple leaders cluster version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + ClusterVersion: pointer.String("v7"), + }, + }, + expectedCommands: []string{ + "redis-cli", "--cluster", "create", + "mycluster-leader-0.mycluster-leader-headless.default.svc:6379", + "mycluster-leader-1.mycluster-leader-headless.default.svc:6379", + "mycluster-leader-2.mycluster-leader-headless.default.svc:6379", + "--cluster-yes", + }, + }, + { + name: "Multiple leaders cluster without version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mycluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + }, + }, + expectedCommands: []string{ + "redis-cli", "--cluster", "create", + "192.168.1.1:6379", + "192.168.1.2:6379", + "192.168.1.3:6379", + "--cluster-yes", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := mock_utils.CreateFakeClientWithPodIPs_LeaderPods(tt.redisCluster) + logger := testr.New(t) + + cmd := CreateMultipleLeaderRedisCommand(client, logger, tt.redisCluster) + assert.Equal(t, tt.expectedCommands, cmd) + }) + } +} + +func TestGetRedisTLSArgs(t *testing.T) { + tests := []struct { + name string + tlsConfig *redisv1beta2.TLSConfig + clientHost string + expected []string + }{ + { + name: "with TLS configuration", + tlsConfig: &redisv1beta2.TLSConfig{}, + clientHost: "redis-host", + expected: []string{"--tls", "--cacert", "/tls/ca.crt", "-h", "redis-host"}, + }, + { + name: "without TLS configuration", + tlsConfig: nil, + clientHost: "redis-host", + expected: []string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := getRedisTLSArgs(tt.tlsConfig, tt.clientHost) + assert.Equal(t, tt.expected, cmd, "Expected command arguments do not match") + }) + } +} + +func TestCreateRedisReplicationCommand(t *testing.T) { + tests := []struct { + name string + redisCluster *redisv1beta2.RedisCluster + leaderPod RedisDetails + followerPod RedisDetails + expectedCommand []string + }{ + { + name: "Test case with cluster version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + ClusterVersion: pointer.String("v7"), + }, + }, + leaderPod: RedisDetails{ + PodName: "redis-cluster-leader-0", + Namespace: "default", + }, + followerPod: RedisDetails{ + PodName: "redis-cluster-follower-0", + Namespace: "default", + }, + expectedCommand: []string{ + "redis-cli", "--cluster", "add-node", + "redis-cluster-follower-0.redis-cluster-follower-headless.default.svc:6379", + "redis-cluster-leader-0.redis-cluster-leader-headless.default.svc:6379", + "--cluster-slave", + }, + }, + { + name: "Test case without cluster version v7", + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + }, + }, + leaderPod: RedisDetails{ + PodName: "redis-cluster-leader-0", + Namespace: "default", + }, + followerPod: RedisDetails{ + PodName: "redis-cluster-follower-0", + Namespace: "default", + }, + expectedCommand: []string{ + "redis-cli", "--cluster", "add-node", + "192.168.2.1:6379", + "192.168.1.1:6379", + "--cluster-slave", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) + logger := testr.New(t) + + cmd := createRedisReplicationCommand(client, logger, tt.redisCluster, tt.leaderPod, tt.followerPod) + + // Assert the command is as expected using testify + assert.Equal(t, tt.expectedCommand, cmd) + }) + } +} + +func TestGetContainerID(t *testing.T) { + tests := []struct { + name string + setupPod *corev1.Pod + redisCluster *redisv1beta2.RedisCluster + expectedID int + expectError bool + }{ + { + name: "Successful retrieval of leader container", + setupPod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster-leader-0", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "redis-cluster-leader", + }, + { + Name: "another-container", + }, + }, + }, + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + expectedID: 0, + expectError: false, + }, + { + name: "Pod not found", + setupPod: &corev1.Pod{}, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + expectedID: -1, + expectError: true, + }, + { + name: "Leader container not found in the pod", + setupPod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster-leader-0", + Namespace: "default", + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "non-leader-container", + }, + }, + }, + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + expectedID: -1, + expectError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + client := k8sClientFake.NewSimpleClientset(test.setupPod) + logger := testr.New(t) + id, pod := getContainerID(client, logger, test.redisCluster, test.setupPod.Name) + if test.expectError { + assert.Nil(t, pod, "Expected no pod but got one") + assert.Equal(t, test.expectedID, id, "Expected ID does not match") + } else { + assert.NotNil(t, pod, "Expected a pod but got none") + assert.Equal(t, test.expectedID, id, "Expected ID does not match") + assert.Equal(t, test.setupPod.Name, pod.GetName(), "Pod names do not match") + assert.Equal(t, test.setupPod.Namespace, pod.GetNamespace(), "Pod namespaces do not match") + } + }) + } +} diff --git a/mocks/utils/utils.go b/mocks/utils/utils.go new file mode 100644 index 000000000..6f9c33b99 --- /dev/null +++ b/mocks/utils/utils.go @@ -0,0 +1,107 @@ +package utils + +import ( + "fmt" + "strconv" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" +) + +func CreateFakeClientWithPodIPs_LeaderPods(cr *redisv1beta2.RedisCluster) *fake.Clientset { + replicas := cr.Spec.GetReplicaCounts("leader") + pods := make([]runtime.Object, replicas) + + for i := 0; i < int(replicas); i++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) + pods[i] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.1.%d", i+1), + }, + } + } + return fake.NewSimpleClientset(pods...) +} + +func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { + leaderReplicas := cr.Spec.GetReplicaCounts("leader") + followerReplicas := cr.Spec.GetReplicaCounts("follower") + pods := make([]runtime.Object, leaderReplicas+followerReplicas) + + for i := 0; i < int(leaderReplicas); i++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) + pods[i] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.1.%d", i+1), + }, + } + } + for i := 0; i < int(followerReplicas); i++ { + podName := cr.ObjectMeta.Name + "-follower-" + strconv.Itoa(i) + pods[i+int(leaderReplicas)] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.2.%d", i+1), + }, + } + } + + return fake.NewSimpleClientset(pods...) +} + +func CreateFakeClientWithSecrets(cr *redisv1beta2.RedisCluster, secretName, secretKey, secretValue string) *fake.Clientset { + leaderReplicas := cr.Spec.GetReplicaCounts("leader") + followerReplicas := cr.Spec.GetReplicaCounts("follower") + pods := make([]runtime.Object, leaderReplicas+followerReplicas) + + for i := 0; i < int(leaderReplicas); i++ { + podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) + pods[i] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.1.%d", i+1), + }, + } + } + for i := 0; i < int(followerReplicas); i++ { + podName := cr.ObjectMeta.Name + "-follower-" + strconv.Itoa(i) + pods[i+int(leaderReplicas)] = &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: cr.Namespace, + }, + Status: corev1.PodStatus{ + PodIP: fmt.Sprintf("192.168.2.%d", i+1), + }, + } + } + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: cr.Namespace, + }, + Data: map[string][]byte{ + secretKey: []byte(secretValue), + }, + } + + return fake.NewSimpleClientset(append(pods, secret)...) +} From d38c3820585ffbfc51fcf5517b17d582d740dffa Mon Sep 17 00:00:00 2001 From: drivebyer Date: Tue, 14 Nov 2023 22:54:13 +0800 Subject: [PATCH 059/203] fix data pvc finalize Signed-off-by: drivebyer --- k8sutils/finalizer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index 0131b24fa..58fdc680d 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -146,7 +146,7 @@ func finalizeRedisPVC(client kubernetes.Interface, logger logr.Logger, cr *redis func finalizeRedisClusterPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { for _, role := range []string{"leader", "follower"} { for i := 0; i < int(cr.Spec.GetReplicaCounts(role)); i++ { - PVCName := fmt.Sprintf("%s-%s-%s-%d", cr.Name, cr.Name, role, i) + PVCName := fmt.Sprintf("%s-%s-%s-%s-%d", cr.Name, role, cr.Name, role, i) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) From b1e89de1661bd4bb38a64b221dddd57d12cb4441 Mon Sep 17 00:00:00 2001 From: drivebyer Date: Tue, 14 Nov 2023 22:55:37 +0800 Subject: [PATCH 060/203] add e2e Signed-off-by: drivebyer --- .../teardown/redis-cluster/00-install.yaml | 9 + .../teardown/redis-cluster/01-uninstall.yaml | 10 + .../teardown/redis-cluster/cluster.yaml | 47 ++++ .../teardown/redis-cluster/ready-cluster.yaml | 7 + .../teardown/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../teardown/redis-cluster/ready-sts.yaml | 25 +++ .../teardown/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ 7 files changed, 480 insertions(+) create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml new file mode 100644 index 000000000..a4d7ca849 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml @@ -0,0 +1,9 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - cluster.yaml +assert : + - ready-cluster.yaml + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml new file mode 100644 index 000000000..db6a4fc84 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: kubectl delete -f cluster.yaml + namespaced: true +error: + - ready-cluster.yaml + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml new file mode 100644 index 000000000..ecf147104 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml @@ -0,0 +1,47 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file From 3c17b57cf0d70bd01d665fb4c57efe79427ece04 Mon Sep 17 00:00:00 2001 From: drivebyer Date: Tue, 14 Nov 2023 22:58:57 +0800 Subject: [PATCH 061/203] add e2e Signed-off-by: drivebyer --- .../redis-replication/00-install.yaml | 8 ++ .../redis-replication/01-uninstall.yaml | 9 ++ .../teardown/redis-replication/ready-pvc.yaml | 44 +++++++++ .../teardown/redis-replication/ready-sts.yaml | 19 ++++ .../teardown/redis-replication/ready-svc.yaml | 90 +++++++++++++++++ .../redis-replication/replication.yaml | 38 ++++++++ .../teardown/redis-sentinel/00-install.yaml | 7 ++ .../teardown/redis-sentinel/01-uninstall.yaml | 8 ++ .../teardown/redis-sentinel/ready-sts.yaml | 35 +++++++ .../teardown/redis-sentinel/ready-svc.yaml | 96 +++++++++++++++++++ .../teardown/redis-sentinel/sentinel.yaml | 22 +++++ .../teardown/redis-standalone/00-install.yaml | 9 ++ .../redis-standalone/01-uninstall.yaml | 9 ++ .../teardown/redis-standalone/ready-pvc.yaml | 14 +++ .../teardown/redis-standalone/ready-sts.yaml | 11 +++ .../teardown/redis-standalone/ready-svc.yaml | 96 +++++++++++++++++++ .../teardown/redis-standalone/standalone.yaml | 26 +++++ 17 files changed, 541 insertions(+) create mode 100644 tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-replication/replication.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml diff --git a/tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml new file mode 100644 index 000000000..19b92e39d --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml @@ -0,0 +1,8 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: + - replication.yaml +assert: + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml new file mode 100644 index 000000000..c9e2422b7 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml @@ -0,0 +1,9 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: kubectl delete -f replication.yaml + namespaced: true +error: + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml b/tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/replication.yaml b/tests/e2e/v1beta2/teardown/redis-replication/replication.yaml new file mode 100644 index 000000000..8e4ba0705 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-replication/replication.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml new file mode 100644 index 000000000..21253678d --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: + - sentinel.yaml +assert: + - ready-sts.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml new file mode 100644 index 000000000..12984e42a --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml @@ -0,0 +1,8 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: kubectl delete -f sentinel.yaml + namespaced: true +error: + - ready-sts.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml new file mode 100644 index 000000000..c6056ab05 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + selector: + matchLabels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + serviceName: redis-sentinel-sentinel-headless + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml new file mode 100644 index 000000000..4ce66a032 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + clusterIP: None + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml new file mode 100644 index 000000000..d18d07f58 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml new file mode 100644 index 000000000..f6256b4f1 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml @@ -0,0 +1,9 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - standalone.yaml +assert : + # - ready-standalone.yaml + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml new file mode 100644 index 000000000..c9c1a7361 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml @@ -0,0 +1,9 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: kubectl delete -f standalone.yaml + namespaced: true +error: + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml new file mode 100644 index 000000000..777fa3656 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-standalone-v1beta2-redis-standalone-v1beta2-0 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml new file mode 100644 index 000000000..5402de920 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml @@ -0,0 +1,11 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + replicas: 1 + readyReplicas: 1 diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml new file mode 100644 index 000000000..08b416ce2 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2 + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml new file mode 100644 index 000000000..c0cc6ded9 --- /dev/null +++ b/tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml @@ -0,0 +1,26 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone-v1beta2 +spec: + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi From 2036996437efbc7a1f42215e2b498c3a156d4dd0 Mon Sep 17 00:00:00 2001 From: drivebyer Date: Tue, 14 Nov 2023 23:00:55 +0800 Subject: [PATCH 062/203] add case Signed-off-by: drivebyer --- .github/workflows/e2e.yaml | 1 + tests/_config/kuttl-test.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 1672cb4f0..9c1aaa69c 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -16,6 +16,7 @@ jobs: matrix: testpath: - ./tests/e2e/v1beta2/setup + - ./tests/e2e/v1beta2/teardown - ./tests/e2e/v1beta2/ignore-annots steps: diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml index fd45e9604..9630d9f51 100644 --- a/tests/_config/kuttl-test.yaml +++ b/tests/_config/kuttl-test.yaml @@ -6,6 +6,7 @@ parallel: 1 timeout: 300 testDirs: - tests/e2e/v1beta2/setup + - tests/e2e/v1beta2/teardown - tests/e2e/v1beta2/ignore-annots suppress : - events \ No newline at end of file From bdbe6f0a202d9ebd7583bf49e59cff995f5f82ed Mon Sep 17 00:00:00 2001 From: drivebyer Date: Tue, 14 Nov 2023 23:11:58 +0800 Subject: [PATCH 063/203] fix unit test Signed-off-by: drivebyer --- k8sutils/finalizers_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go index ad67c0247..f99a021df 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizers_test.go @@ -297,7 +297,7 @@ func helperRedisClusterPVCs(clusterName string, namespace string) []*corev1.Pers roles := []string{"leader", "follower"} for _, role := range roles { for i := 0; i < 3; i++ { - clusterPVCName := fmt.Sprintf("%s-%s-%s-%d", clusterName, clusterName, role, i) + clusterPVCName := fmt.Sprintf("%s-%s-%s-%s-%d", clusterName, role, clusterName, role, i) clusterPVC := &corev1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ Name: clusterPVCName, From a597c393285552cf1a503a91975f1231f067d685 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 21 Nov 2023 04:21:39 +0800 Subject: [PATCH 064/203] [Fix] : cluster scaling (#704) * add scale e2e yamls Signed-off-by: drivebyer * temp Signed-off-by: drivebyer * fix the cluster scale Signed-off-by: drivebyer * adjust e2e Signed-off-by: drivebyer --------- Signed-off-by: drivebyer Signed-off-by: drivebyer --- .github/workflows/e2e.yaml | 1 + controllers/rediscluster_controller.go | 84 ++++++++++--------- k8sutils/cluster-scaling.go | 22 +++-- k8sutils/redis.go | 6 +- tests/_config/kuttl-test.yaml | 3 +- .../scaling/redis-cluster/00-install.yaml | 7 ++ .../scaling/redis-cluster/01-scale-up.yaml | 7 ++ .../scaling/redis-cluster/02-scale-down.yaml | 7 ++ .../redis-cluster/cluster-scale-up.yaml | 47 +++++++++++ .../scaling/redis-cluster/cluster.yaml | 47 +++++++++++ .../redis-cluster/ready-cluster-scale-up.yaml | 8 ++ .../scaling/redis-cluster/ready-cluster.yaml | 8 ++ .../redis-cluster/ready-sts-scale-up.yaml | 23 +++++ .../scaling/redis-cluster/ready-sts.yaml | 25 ++++++ 14 files changed, 245 insertions(+), 50 deletions(-) create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/cluster.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml create mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 9c1aaa69c..1e82126eb 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -18,6 +18,7 @@ jobs: - ./tests/e2e/v1beta2/setup - ./tests/e2e/v1beta2/teardown - ./tests/e2e/v1beta2/ignore-annots + - ./tests/e2e/v1beta2/scaling steps: - name: Checkout code diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 8a43c5840..9b99bbaba 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -75,27 +75,36 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Check if the cluster is downscaled if leaderReplicas < instance.Status.ReadyLeaderReplicas { - - // Imp if the last index of leader sts is not leader make it then - // check whether the redis is leader or not ? - // if not true then make it leader pod - - if !(k8sutils.VerifyLeaderPod(ctx, r.K8sClient, r.Log, instance)) { - // lastLeaderPod is slaving right now Make it the master Pod - // We have to bring a manual failover here to make it a leaderPod - // clusterFailover should also include the clusterReplicate since we have to map the followers to new leader - k8sutils.ClusterFailover(ctx, r.K8sClient, r.Log, instance) + reqLogger.Info("Redis cluster is downscaling...", "Ready.ReadyLeaderReplicas", instance.Status.ReadyLeaderReplicas, "Expected.ReadyLeaderReplicas", leaderReplicas) + + // loop count times to remove the latest leader/follower pod + count := instance.Status.ReadyLeaderReplicas - leaderReplicas + for i := int32(0); i < count; i++ { + reqLogger.Info("Redis cluster is downscaling", "The times of loop", i) + + // Imp if the last index of leader sts is not leader make it then + // check whether the redis is leader or not ? + // if not true then make it leader pod + if !(k8sutils.VerifyLeaderPod(ctx, r.K8sClient, r.Log, instance)) { + // lastLeaderPod is slaving right now Make it the master Pod + // We have to bring a manual failover here to make it a leaderPod + // clusterFailover should also include the clusterReplicate since we have to map the followers to new leader + k8sutils.ClusterFailover(ctx, r.K8sClient, r.Log, instance) + } + // Step 1 Remove the Follower Node + k8sutils.RemoveRedisFollowerNodesFromCluster(ctx, r.K8sClient, r.Log, instance) + // Step 2 Reshard the Cluster + k8sutils.ReshardRedisCluster(r.K8sClient, r.Log, instance, true) } - - // Step 1 Rehard the Cluster - k8sutils.ReshardRedisCluster(r.K8sClient, r.Log, instance) - // Step 2 Remove the Follower Node - k8sutils.RemoveRedisFollowerNodesFromCluster(ctx, r.K8sClient, r.Log, instance) - // Step 3 Remove the Leader Node - k8sutils.RemoveRedisNodeFromCluster(ctx, r.K8sClient, r.Log, instance) - // Step 4 Rebalance the cluster + reqLogger.Info("Redis cluster is downscaled... Rebalancing the cluster") + // Step 3 Rebalance the cluster k8sutils.RebalanceRedisCluster(r.K8sClient, r.Log, instance) - return ctrl.Result{RequeueAfter: time.Second * 100}, nil + reqLogger.Info("Redis cluster is downscaled... Rebalancing the cluster is done") + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, leaderReplicas) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err + } + return ctrl.Result{RequeueAfter: time.Second * 60}, nil } // Mark the cluster status as initializing if there are no leader or follower nodes @@ -130,7 +139,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } - if int32(redisLeaderInfo.Status.ReadyReplicas) == leaderReplicas { + if redisLeaderInfo.Status.ReadyReplicas == leaderReplicas { // Mark the cluster status as initializing if there are no follower nodes if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { @@ -166,26 +175,24 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if leaderReplicas == 0 { reqLogger.Info("Redis leaders Cannot be 0", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) - return ctrl.Result{RequeueAfter: time.Second * 120}, nil + return ctrl.Result{RequeueAfter: time.Second * 60}, nil } if !(redisLeaderInfo.Status.ReadyReplicas == leaderReplicas && redisFollowerInfo.Status.ReadyReplicas == followerReplicas) { reqLogger.Info("Redis leader and follower nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) - return ctrl.Result{RequeueAfter: time.Second * 120}, nil + return ctrl.Result{RequeueAfter: time.Second * 60}, nil } // Mark the cluster status as bootstrapping if all the leader and follower nodes are ready - if int32(redisLeaderInfo.Status.ReadyReplicas) == leaderReplicas && int32(redisFollowerInfo.Status.ReadyReplicas) == followerReplicas { - if instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == 0 { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas) - if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err - } + if !(instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas) { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err } } reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) - if k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "") != totalReplicas { + if nc := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, ""); nc != totalReplicas { leaderCount := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) @@ -208,16 +215,17 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request reqLogger.Info("no follower/replicas configured, skipping replication configuration", "Leaders.Count", leaderCount, "Leader.Size", leaderReplicas, "Follower.Replicas", followerReplicas) } } - } else { - reqLogger.Info("Redis leader count is desired") - if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(ctx, r.K8sClient, r.Log, instance) >= int(totalReplicas)-1 { - reqLogger.Info("Redis leader is not desired, executing failover operation") - err = k8sutils.ExecuteFailoverOperation(ctx, r.K8sClient, r.Log, instance) - if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err - } + reqLogger.Info("Redis cluster count is not desired", "Current.Count", nc, "Desired.Count", totalReplicas) + return ctrl.Result{RequeueAfter: time.Second * 60}, nil + } + + reqLogger.Info("Redis cluster count is desired") + if int(totalReplicas) > 1 && k8sutils.CheckRedisClusterState(ctx, r.K8sClient, r.Log, instance) >= int(totalReplicas)-1 { + reqLogger.Info("Redis leader is not desired, executing failover operation") + err = k8sutils.ExecuteFailoverOperation(ctx, r.K8sClient, r.Log, instance) + if err != nil { + return ctrl.Result{RequeueAfter: time.Second * 10}, err } - return ctrl.Result{RequeueAfter: time.Second * 120}, nil } // Check If there is No Empty Master Node diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index b0a384c02..395a5c942 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -11,8 +11,10 @@ import ( "k8s.io/client-go/kubernetes" ) -// Reshard the redis Cluster -func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { +// ReshardRedisCluster transfer the slots from the last node to the first node. +// +// NOTE: when all slot been transferred, the node become slave of the first master node. +func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, remove bool) { ctx := context.TODO() var cmd []string currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") @@ -72,6 +74,10 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re return } executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") + + if remove { + RemoveRedisNodeFromCluster(ctx, client, logger, cr, removePOD) + } } func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeID string) string { @@ -336,18 +342,18 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. } // Remove redis cluster node would remove last node to the existing redis cluster using redis-cli -func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { +func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, removePod RedisDetails) { var cmd []string - currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") + //currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", Namespace: cr.Namespace, } - removePod := RedisDetails{ - PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(currentRedisCount)-1), - Namespace: cr.Namespace, - } + //removePod := RedisDetails{ + // PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(currentRedisCount)-1), + // Namespace: cr.Namespace, + //} cmd = []string{"redis-cli", "--cluster", "del-node"} diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 51cb0a4e3..0ec4433e9 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -406,20 +406,20 @@ func getContainerID(client kubernetes.Interface, logger logr.Logger, cr *redisv1 return -1, nil } - logger.Info("Pod info retrieved successfully", "Pod Name", podName, "Namespace", cr.Namespace) + logger.V(1).Info("Pod info retrieved successfully", "Pod Name", podName, "Namespace", cr.Namespace) targetContainer := -1 for containerID, tr := range pod.Spec.Containers { logger.V(1).Info("Inspecting container", "Pod Name", podName, "Container ID", containerID, "Container Name", tr.Name) if tr.Name == cr.ObjectMeta.Name+"-leader" { targetContainer = containerID - logger.Info("Leader container found", "Container ID", containerID, "Container Name", tr.Name) + logger.V(1).Info("Leader container found", "Container ID", containerID, "Container Name", tr.Name) break } } if targetContainer == -1 { - logger.Info("Leader container not found in pod", "Pod Name", podName) + logger.V(1).Info("Leader container not found in pod", "Pod Name", podName) return -1, nil } diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml index 9630d9f51..984bba05e 100644 --- a/tests/_config/kuttl-test.yaml +++ b/tests/_config/kuttl-test.yaml @@ -3,10 +3,11 @@ kind: TestSuite startKIND: false kindConfig: "./kind-config.yaml" parallel: 1 -timeout: 300 +timeout: 1200 testDirs: - tests/e2e/v1beta2/setup - tests/e2e/v1beta2/teardown - tests/e2e/v1beta2/ignore-annots + - tests/e2e/v1beta2/scaling suppress : - events \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml new file mode 100644 index 000000000..7529f3a78 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - cluster.yaml +assert : + - ready-cluster.yaml + - ready-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml new file mode 100644 index 000000000..7272499a2 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - cluster-scale-up.yaml +assert : + - ready-cluster-scale-up.yaml + - ready-sts-scale-up.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml new file mode 100644 index 000000000..60d8821f1 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - cluster.yaml +assert : + - ready-cluster.yaml + - ready-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml new file mode 100644 index 000000000..5f64363e8 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml @@ -0,0 +1,47 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 6 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/cluster.yaml new file mode 100644 index 000000000..ecf147104 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/cluster.yaml @@ -0,0 +1,47 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml new file mode 100644 index 000000000..907e75ccc --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml @@ -0,0 +1,8 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + state: Ready + readyLeaderReplicas: 6 + readyFollowerReplicas: 6 \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..3a08c80b6 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster.yaml @@ -0,0 +1,8 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + state: Ready + readyLeaderReplicas: 3 + readyFollowerReplicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml new file mode 100644 index 000000000..61d865e0f --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 6 + readyReplicas: 6 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 6 + readyReplicas: 6 diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 From 76927086d2dc61d0e86fba5da5c792f14138310e Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 21 Nov 2023 23:17:37 +0800 Subject: [PATCH 065/203] [Fix] : returned both a non-zero result and a non-nil error (#705) Signed-off-by: drivebyer --- controllers/rediscluster_controller.go | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 9b99bbaba..25549e8b2 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -66,11 +66,11 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request totalReplicas := leaderReplicas + followerReplicas if err = k8sutils.HandleRedisClusterFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } if err = k8sutils.AddRedisClusterFinalizer(instance, r.Client); err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } // Check if the cluster is downscaled @@ -102,7 +102,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request reqLogger.Info("Redis cluster is downscaled... Rebalancing the cluster is done") err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, leaderReplicas) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err + return ctrl.Result{}, err } return ctrl.Result{RequeueAfter: time.Second * 60}, nil } @@ -111,24 +111,24 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, 0, 0) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err + return ctrl.Result{}, err } } err = k8sutils.CreateRedisLeader(instance) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } if leaderReplicas != 0 { err = k8sutils.CreateRedisLeaderService(instance) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } } err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } redisLeaderInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-leader") @@ -145,24 +145,24 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, 0) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err + return ctrl.Result{}, err } } err = k8sutils.CreateRedisFollower(instance) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } // if we have followers create their service. if followerReplicas != 0 { err = k8sutils.CreateRedisFollowerService(instance) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } } err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.PodDisruptionBudget) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return ctrl.Result{}, err } } redisFollowerInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-follower") @@ -187,7 +187,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if !(instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas) { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err + return ctrl.Result{}, err } } @@ -224,7 +224,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request reqLogger.Info("Redis leader is not desired, executing failover operation") err = k8sutils.ExecuteFailoverOperation(ctx, r.K8sClient, r.Log, instance) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err + return ctrl.Result{}, err } } @@ -238,7 +238,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 10}, err + return ctrl.Result{}, err } } From 48add7ecbf54f876cc95e9e1e1728354047dce4a Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 7 Dec 2023 15:19:21 +0800 Subject: [PATCH 066/203] fix: specify k8s version which contain darwin arm64 (#719) Signed-off-by: drivebyer --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index aed1dd5da..66849fd86 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ ENVTEST_ASSETS_DIR=$(shell pwd)/testbin test: generate fmt vet manifests mkdir -p ${ENVTEST_ASSETS_DIR} test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh - source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out + source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; ENVTEST_K8S_VERSION=1.24.1 fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out # Build manager binary manager: generate fmt vet From 1e2265831b1b8b769ef615e32b464f1b470f93fe Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Tue, 12 Dec 2023 04:55:29 +0530 Subject: [PATCH 067/203] feat: Add Chainsaw Action in CI (#722) * add chainsaw action Signed-off-by: Shubham Gupta * update Signed-off-by: Shubham Gupta * fix Ci Signed-off-by: Shubham Gupta * Add release Signed-off-by: Shubham Gupta * Ci Signed-off-by: Shubham Gupta * remove build Signed-off-by: Shubham Gupta * test version Signed-off-by: Shubham Gupta * try with 0.0.8 Signed-off-by: Shubham Gupta * try with v0.0.9 Signed-off-by: Shubham Gupta * bump Signed-off-by: Shubham Gupta * try with v0.0.4 Signed-off-by: Shubham Gupta * add : Setup Signed-off-by: Shubham Gupta * only setup Signed-off-by: Shubham Gupta * fix name Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * increase timeout Signed-off-by: Shubham Gupta * more time Signed-off-by: Shubham Gupta * bump timeout Signed-off-by: Shubham Gupta * Add teardown Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * fix delete Signed-off-by: Shubham Gupta * file Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 62 ++++++ tests/_config/chainsaw-configuration.yaml | 14 ++ .../setup/redis-cluster/chainsaw-test.yaml | 19 ++ .../v1beta2/setup/redis-cluster/cluster.yaml | 47 ++++ .../setup/redis-cluster/ready-cluster.yaml | 7 + .../setup/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../setup/redis-cluster/ready-sts.yaml | 25 +++ .../setup/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ .../teardown/redis-cluster/chainsaw-test.yaml | 35 +++ .../teardown/redis-cluster/cluster.yaml | 47 ++++ .../teardown/redis-cluster/ready-cluster.yaml | 7 + .../teardown/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../teardown/redis-cluster/ready-sts.yaml | 25 +++ .../teardown/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ 14 files changed, 1052 insertions(+) create mode 100644 .github/workflows/e2e-chainsaw.yml create mode 100644 tests/_config/chainsaw-configuration.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml new file mode 100644 index 000000000..b61bde8cf --- /dev/null +++ b/.github/workflows/e2e-chainsaw.yml @@ -0,0 +1,62 @@ +name: E2E chainsaw tests + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + test: + name: ${{ matrix.testpath }} + runs-on: ubuntu-latest + strategy: + matrix: + testpath: + - ./tests/e2e-chainsaw/v1beta2/teardown/ + - ./tests/e2e-chainsaw/v1beta2/setup/ + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build Dockerfile + run: docker build . --file Dockerfile --tag redis-operator:e2e + + - name: Install chainsaw + uses: kyverno/chainsaw/.github/actions/install@v0.0.9 + with: + release: v0.0.9 + + - name: Check install + run: chainsaw version + + - name: Install kubectl + run: | + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/ + + - name: Create k8s Kind Cluster + uses: helm/kind-action@v1.5.0 + with: + config: tests/_config/kind-config.yaml + cluster_name: kind + + - name: Load Docker image into Kind + run: | + kubectl cluster-info --context kind-kind + kind load docker-image redis-operator:e2e --name kind + + - name: Install Redis Operator + run: | + make deploy IMG=redis-operator:e2e + + - name: Wait for Redis Operator to be ready + run: | + kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system + + - name: Run chainsaw test + run: chainsaw test --test-dir ${{ matrix.testpath }} --config tests/_config/chainsaw-configuration.yaml diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml new file mode 100644 index 000000000..f2637f495 --- /dev/null +++ b/tests/_config/chainsaw-configuration.yaml @@ -0,0 +1,14 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Configuration +metadata: + name: chainsaw-configuration +spec: + parallel: 1 + delayBeforeCleanup: 10s + timeouts: + apply: 100s + delete: 100s + assert: 900s + error: 900s diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..c1cfc8b9d --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,19 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-setup +spec: + steps: + - try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml new file mode 100644 index 000000000..ecf147104 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml @@ -0,0 +1,47 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..c0f32993d --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-teardown +spec: + steps: + - name: redis-cluster-install + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: redis-cluster-uninstall + try: + - delete: + ref: + name: redis-cluster-v1beta2 + kind: RedisCluster + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-cluster.yaml + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - error: + file: ready-pvc.yaml diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml new file mode 100644 index 000000000..ecf147104 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml @@ -0,0 +1,47 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file From 48b515b19ea9c07a88ec631b5c16882428266b15 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:38:03 +0530 Subject: [PATCH 068/203] test: try Ping cluster (#726) * try Ping cluster Signed-off-by: Shubham Gupta * use script Signed-off-by: Shubham Gupta * PONG Signed-off-by: Shubham Gupta * ping cluster Signed-off-by: Shubham Gupta * remove Signed-off-by: Shubham Gupta * try spacing Signed-off-by: Shubham Gupta * pong Signed-off-by: Shubham Gupta * fix quote Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .../v1beta2/setup/redis-cluster/chainsaw-test.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index c1cfc8b9d..1a020f2ca 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -16,4 +16,11 @@ spec: - assert: file: ready-svc.yaml - assert: - file: ready-pvc.yaml \ No newline at end of file + file: ready-pvc.yaml + - name: Ping Cluster + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true From adca06866e2585abb9e353059d4731019ae5b384 Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 14 Dec 2023 03:25:21 +0800 Subject: [PATCH 069/203] feat: rediscluster support hostnetwork && custom port (#723) * add cr filed, default port to 6379 Signed-off-by: drivebyer * replace with custom port Signed-off-by: drivebyer * service custom port Signed-off-by: drivebyer * make default to 6379 when reconcile old cluster Signed-off-by: drivebyer * add e2e Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/e2e-chainsaw.yml | 4 + .github/workflows/e2e.yaml | 1 + api/v1beta2/rediscluster_default.go | 10 + api/v1beta2/rediscluster_types.go | 3 + api/v1beta2/zz_generated.deepcopy.go | 5 + ...is.redis.opstreelabs.in_redisclusters.yaml | 5 + controllers/rediscluster_controller.go | 1 + k8sutils/cluster-scaling.go | 33 +-- k8sutils/redis-cluster.go | 8 +- k8sutils/redis-replication.go | 6 +- k8sutils/redis-sentinel.go | 6 +- k8sutils/redis-sentinel_test.go | 86 ++++++++ k8sutils/redis-standalone.go | 6 +- k8sutils/redis.go | 16 +- k8sutils/redis_test.go | 4 + k8sutils/services.go | 13 +- k8sutils/services_test.go | 8 +- k8sutils/statefulset.go | 16 +- k8sutils/statefulset_test.go | 6 +- pkg/util/coalesce.go | 9 + tests/_config/chainsaw-configuration.yaml | 8 +- tests/_config/kind-config.yaml | 4 + tests/_config/kuttl-test.yaml | 1 + .../redis-cluster/chainsaw-test.yaml | 45 ++++ .../hostnetwork/redis-cluster/cluster.yaml | 49 +++++ .../redis-cluster/ready-cluster.yaml | 7 + .../hostnetwork/redis-cluster/ready-pod.yaml | 155 ++++++++++++++ .../hostnetwork/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../hostnetwork/redis-cluster/ready-sts.yaml | 25 +++ .../hostnetwork/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ .../hostnetwork/redis-cluster/00-install.yaml | 10 + .../hostnetwork/redis-cluster/cluster.yaml | 49 +++++ .../redis-cluster/ready-cluster.yaml | 7 + .../hostnetwork/redis-cluster/ready-pod.yaml | 155 ++++++++++++++ .../hostnetwork/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../hostnetwork/redis-cluster/ready-sts.yaml | 25 +++ .../hostnetwork/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ 37 files changed, 1499 insertions(+), 51 deletions(-) create mode 100644 api/v1beta2/rediscluster_default.go create mode 100644 pkg/util/coalesce.go create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index b61bde8cf..dcf25b81a 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -17,6 +17,7 @@ jobs: testpath: - ./tests/e2e-chainsaw/v1beta2/teardown/ - ./tests/e2e-chainsaw/v1beta2/setup/ + - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ steps: - name: Checkout code @@ -39,6 +40,9 @@ jobs: chmod +x kubectl sudo mv kubectl /usr/local/bin/ + # - name: Install Redis + # uses: shogo82148/actions-setup-redis@v1 + - name: Create k8s Kind Cluster uses: helm/kind-action@v1.5.0 with: diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 1e82126eb..c9c271f0a 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -19,6 +19,7 @@ jobs: - ./tests/e2e/v1beta2/teardown - ./tests/e2e/v1beta2/ignore-annots - ./tests/e2e/v1beta2/scaling + - ./tests/e2e/v1beta2/hostnetwork steps: - name: Checkout code diff --git a/api/v1beta2/rediscluster_default.go b/api/v1beta2/rediscluster_default.go new file mode 100644 index 000000000..7dbc9ea8f --- /dev/null +++ b/api/v1beta2/rediscluster_default.go @@ -0,0 +1,10 @@ +package v1beta2 + +import "k8s.io/utils/pointer" + +// SetDefault sets default values for the RedisCluster object. +func (r *RedisCluster) SetDefault() { + if r.Spec.Port == nil { + r.Spec.Port = pointer.Int(6379) + } +} diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index 913e4f2a1..b9e629f7a 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -27,6 +27,9 @@ import ( type RedisClusterSpec struct { Size *int32 `json:"clusterSize"` KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` + HostNetwork bool `json:"hostNetwork,omitempty"` + // +kubebuilder:default:=6379 + Port *int `json:"port,omitempty"` // +kubebuilder:default:=v7 ClusterVersion *string `json:"clusterVersion,omitempty"` // +kubebuilder:default:={livenessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}, readinessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}} diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 5e5fe2954..6fc14b16b 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -262,6 +262,11 @@ func (in *RedisClusterSpec) DeepCopyInto(out *RedisClusterSpec) { **out = **in } in.KubernetesConfig.DeepCopyInto(&out.KubernetesConfig) + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int) + **out = **in + } if in.ClusterVersion != nil { in, out := &in.ClusterVersion, &out.ClusterVersion *out = new(string) diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 2b9e3c39e..cdf11fc59 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -5297,6 +5297,8 @@ spec: - name type: object type: array + hostNetwork: + type: boolean initContainer: description: InitContainer for each Redis pods properties: @@ -5792,6 +5794,9 @@ spec: type: string type: object type: object + port: + default: 6379 + type: integer priorityClassName: type: string redisExporter: diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 25549e8b2..0a501170d 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -55,6 +55,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } return ctrl.Result{}, err } + instance.SetDefault() if _, found := instance.ObjectMeta.GetAnnotations()["rediscluster.opstreelabs.in/skip-reconcile"]; found { reqLogger.Info("Found annotations rediscluster.opstreelabs.in/skip-reconcile, so skipping reconcile") diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index 395a5c942..957b74b28 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -2,6 +2,7 @@ package k8sutils import ( "context" + "fmt" "strconv" "strings" @@ -32,9 +33,9 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re cmd = []string{"redis-cli", "--cluster", "reshard"} if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(transferPOD, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(transferPOD, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, transferPOD)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, transferPOD)+fmt.Sprintf(":%d", *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -157,9 +158,9 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. cmd = []string{"redis-cli", "--cluster", "rebalance"} if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(pod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+fmt.Sprintf(":%d", *cr.Spec.Port)) } cmd = append(cmd, "--cluster-use-empty-masters") @@ -209,9 +210,9 @@ func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr * cmd = []string{"redis-cli", "--cluster", "rebalance"} if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(pod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+fmt.Sprintf(":%d", *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -246,11 +247,11 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log cmd = []string{"redis-cli", "--cluster", "add-node"} if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(newPod, cr, "leader")+":6379") - cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(newPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, newPod)+":6379") - cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, newPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -327,9 +328,9 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. cmd = append(cmd, "--cluster", "del-node") if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) } for _, followerNodeID := range followerNodeIDs { @@ -358,9 +359,9 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface cmd = []string{"redis-cli", "--cluster", "del-node"} if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) } removePodNodeID := getRedisNodeID(ctx, client, logger, cr, removePod) @@ -419,9 +420,9 @@ func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger lo cmd = []string{"redis-cli", "cluster", "failover"} if *cr.Spec.ClusterVersion == "v7" { - cmd = append(cmd, getRedisHostname(pod, cr, "leader")+":6379") + cmd = append(cmd, getRedisHostname(pod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, pod)+":6379") + cmd = append(cmd, getRedisServerIP(client, logger, pod)+fmt.Sprintf(":%d", *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index d3a523cc2..b6ae773b3 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -39,6 +39,7 @@ func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, e ServiceAccountName: cr.Spec.ServiceAccountName, UpdateStrategy: cr.Spec.KubernetesConfig.UpdateStrategy, IgnoreAnnotations: cr.Spec.KubernetesConfig.IgnoreAnnotations, + HostNetwork: cr.Spec.HostNetwork, } if cr.Spec.RedisExporter != nil { res.EnableMetrics = cr.Spec.RedisExporter.Enabled @@ -100,6 +101,7 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: securityContext, + Port: cr.Spec.Port, } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars @@ -246,12 +248,12 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re objectMetaInfo := generateObjectMetaInformation(serviceName, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisClusterAsOwner(cr), false, true, "ClusterIP") + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisClusterAsOwner(cr), false, true, "ClusterIP", *cr.Spec.Port) if err != nil { logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole) return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), enableMetrics, false, "ClusterIP") + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), enableMetrics, false, "ClusterIP", *cr.Spec.Port) if err != nil { logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -260,7 +262,7 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), false, false, additionalServiceType) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), false, false, additionalServiceType, *cr.Spec.Port) if err != nil { logger.Error(err, "Cannot create additional service for Redis", "Setup.Type", service.RedisServiceRole) return err diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index df48c5d18..5e5223a3c 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -19,12 +19,12 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisReplicationAsOwner(cr), false, true, "ClusterIP") + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisReplicationAsOwner(cr), false, true, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create replication headless service for Redis") return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisReplicationAsOwner(cr), enableMetrics, false, "ClusterIP") + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisReplicationAsOwner(cr), enableMetrics, false, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create replication service for Redis") return err @@ -33,7 +33,7 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisReplicationAsOwner(cr), false, false, additionalServiceType) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisReplicationAsOwner(cr), false, false, additionalServiceType, redisPort) if err != nil { logger.Error(err, "Cannot create additional service for Redis Replication") return err diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 9977fa644..6eef41716 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -215,12 +215,12 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisSentinelAsOwner(cr), false, true, "ClusterIP") + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisSentinelAsOwner(cr), false, true, "ClusterIP", sentinelPort) if err != nil { logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole) return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisSentinelAsOwner(cr), enableMetrics, false, "ClusterIP") + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisSentinelAsOwner(cr), enableMetrics, false, "ClusterIP", sentinelPort) if err != nil { logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -230,7 +230,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisSentinelAsOwner(cr), false, false, additionalServiceType) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisSentinelAsOwner(cr), false, false, additionalServiceType, sentinelPort) if err != nil { logger.Error(err, "Cannot create additional service for Redis", "Setup.Type", service.RedisServiceRole) return err diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index 9aedb48b4..f30d7a267 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -2,8 +2,10 @@ package k8sutils import ( "context" + "k8s.io/client-go/kubernetes" "os" "path/filepath" + "reflect" "testing" common "github.com/OT-CONTAINER-KIT/redis-operator/api" @@ -246,3 +248,87 @@ func Test_generateRedisSentinelInitContainerParams(t *testing.T) { actual := generateRedisSentinelInitContainerParams(input) assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) } + +func Test_getSentinelEnvVariable(t *testing.T) { + type args struct { + ctx context.Context + client kubernetes.Interface + logger logr.Logger + cr *redisv1beta2.RedisSentinel + } + tests := []struct { + name string + args args + want *[]corev1.EnvVar + }{ + { + name: "When RedisSentinelConfig is nil", + args: args{ + ctx: context.TODO(), + client: nil, + logger: logr.Logger{}, + cr: &redisv1beta2.RedisSentinel{}, + }, + want: &[]corev1.EnvVar{}, + }, + { + name: "When RedisSentinelConfig is not nil", + args: args{ + ctx: context.TODO(), + client: nil, + logger: logr.Logger{}, + cr: &redisv1beta2.RedisSentinel{ + Spec: redisv1beta2.RedisSentinelSpec{ + RedisSentinelConfig: &redisv1beta2.RedisSentinelConfig{ + RedisSentinelConfig: common.RedisSentinelConfig{ + MasterGroupName: "master", + RedisPort: "6379", + Quorum: "2", + DownAfterMilliseconds: "30000", + ParallelSyncs: "1", + FailoverTimeout: "180000", + }, + }, + }, + }, + }, + want: &[]corev1.EnvVar{ + { + Name: "MASTER_GROUP_NAME", + Value: "master", + }, + { + Name: "IP", + Value: "", + }, + { + Name: "PORT", + Value: "6379", + }, + { + Name: "QUORUM", + Value: "2", + }, + { + Name: "DOWN_AFTER_MILLISECONDS", + Value: "30000", + }, + { + Name: "PARALLEL_SYNCS", + Value: "1", + }, + { + Name: "FAILOVER_TIMEOUT", + Value: "180000", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := getSentinelEnvVariable(tt.args.ctx, tt.args.client, tt.args.logger, tt.args.cr); !reflect.DeepEqual(got, tt.want) { + t.Errorf("getSentinelEnvVariable() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index bd535e227..33d2e4c03 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -23,12 +23,12 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisAsOwner(cr), false, true, "ClusterIP") + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisAsOwner(cr), false, true, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create standalone headless service for Redis") return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisAsOwner(cr), enableMetrics, false, "ClusterIP") + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisAsOwner(cr), enableMetrics, false, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create standalone service for Redis") return err @@ -37,7 +37,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisAsOwner(cr), false, false, additionalServiceType) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisAsOwner(cr), false, false, additionalServiceType, redisPort) if err != nil { logger.Error(err, "Cannot create additional service for Redis") return err diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 0ec4433e9..fa1986bd6 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -83,9 +83,9 @@ func CreateMultipleLeaderRedisCommand(client kubernetes.Interface, logger logr.L podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount) var address string if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { - address = getRedisHostname(RedisDetails{PodName: podName, Namespace: cr.Namespace}, cr, "leader") + ":6379" + address = getRedisHostname(RedisDetails{PodName: podName, Namespace: cr.Namespace}, cr, "leader") + fmt.Sprintf(":%d", *cr.Spec.Port) } else { - address = getRedisServerIP(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}) + ":6379" + address = getRedisServerIP(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}) + fmt.Sprintf(":%d", *cr.Spec.Port) } cmd = append(cmd, address) } @@ -141,11 +141,11 @@ func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logg var followerAddress, leaderAddress string if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { - followerAddress = getRedisHostname(followerPod, cr, "follower") + ":6379" - leaderAddress = getRedisHostname(leaderPod, cr, "leader") + ":6379" + followerAddress = getRedisHostname(followerPod, cr, "follower") + fmt.Sprintf(":%d", *cr.Spec.Port) + leaderAddress = getRedisHostname(leaderPod, cr, "leader") + fmt.Sprintf(":%d", *cr.Spec.Port) } else { - followerAddress = getRedisServerIP(client, logger, followerPod) + ":6379" - leaderAddress = getRedisServerIP(client, logger, leaderPod) + ":6379" + followerAddress = getRedisServerIP(client, logger, followerPod) + fmt.Sprintf(":%d", *cr.Spec.Port) + leaderAddress = getRedisServerIP(client, logger, leaderPod) + fmt.Sprintf(":%d", *cr.Spec.Port) } cmd = append(cmd, followerAddress, leaderAddress, "--cluster-slave") @@ -340,14 +340,14 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + fmt.Sprintf(":%d", *cr.Spec.Port), Password: pass, DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", + Addr: getRedisServerIP(client, logger, redisInfo) + fmt.Sprintf(":%d", *cr.Spec.Port), Password: "", DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 26628290d..8dacd2032 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -206,6 +206,7 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { Spec: redisv1beta2.RedisClusterSpec{ Size: pointer.Int32(3), ClusterVersion: pointer.String("v7"), + Port: pointer.Int(6379), }, }, expectedCommands: []string{ @@ -225,6 +226,7 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { }, Spec: redisv1beta2.RedisClusterSpec{ Size: pointer.Int32(3), + Port: pointer.Int(6379), }, }, expectedCommands: []string{ @@ -295,6 +297,7 @@ func TestCreateRedisReplicationCommand(t *testing.T) { Spec: redisv1beta2.RedisClusterSpec{ Size: pointer.Int32(3), ClusterVersion: pointer.String("v7"), + Port: pointer.Int(6379), }, }, leaderPod: RedisDetails{ @@ -321,6 +324,7 @@ func TestCreateRedisReplicationCommand(t *testing.T) { }, Spec: redisv1beta2.RedisClusterSpec{ Size: pointer.Int32(3), + Port: pointer.Int(6379), }, }, leaderPod: RedisDetails{ diff --git a/k8sutils/services.go b/k8sutils/services.go index 0bcf56944..c28e6ba29 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -23,15 +23,12 @@ var ( ) // generateServiceDef generates service definition for Redis -func generateServiceDef(serviceMeta metav1.ObjectMeta, enableMetrics bool, ownerDef metav1.OwnerReference, headless bool, serviceType string) *corev1.Service { +func generateServiceDef(serviceMeta metav1.ObjectMeta, enableMetrics bool, ownerDef metav1.OwnerReference, headless bool, serviceType string, port int) *corev1.Service { var PortName string - var PortNum int32 if serviceMeta.Labels["role"] == "sentinel" { PortName = "sentinel-client" - PortNum = sentinelPort } else { PortName = "redis-client" - PortNum = redisPort } service := &corev1.Service{ TypeMeta: generateMetaInformation("Service", "v1"), @@ -43,8 +40,8 @@ func generateServiceDef(serviceMeta metav1.ObjectMeta, enableMetrics bool, owner Ports: []corev1.ServicePort{ { Name: PortName, - Port: PortNum, - TargetPort: intstr.FromInt(int(PortNum)), + Port: int32(port), + TargetPort: intstr.FromInt(int(port)), Protocol: corev1.ProtocolTCP, }, }, @@ -146,9 +143,9 @@ func serviceLogger(namespace string, name string) logr.Logger { } // CreateOrUpdateService method will create or update Redis service -func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, enableMetrics, headless bool, serviceType string) error { +func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, enableMetrics, headless bool, serviceType string, port int) error { logger := serviceLogger(namespace, serviceMeta.Name) - serviceDef := generateServiceDef(serviceMeta, enableMetrics, ownerDef, headless, serviceType) + serviceDef := generateServiceDef(serviceMeta, enableMetrics, ownerDef, headless, serviceType, port) storedService, err := getService(namespace, serviceMeta.Name) if err != nil { if errors.IsNotFound(err) { diff --git a/k8sutils/services_test.go b/k8sutils/services_test.go index 035583779..cbd012b2f 100644 --- a/k8sutils/services_test.go +++ b/k8sutils/services_test.go @@ -16,6 +16,7 @@ func TestGenerateServiceDef(t *testing.T) { enableMetrics bool headless bool serviceType string + port int expected *corev1.Service }{ { @@ -29,6 +30,7 @@ func TestGenerateServiceDef(t *testing.T) { enableMetrics: false, headless: false, serviceType: "ClusterIP", + port: sentinelPort, expected: &corev1.Service{ TypeMeta: metav1.TypeMeta{ Kind: "Service", @@ -69,6 +71,7 @@ func TestGenerateServiceDef(t *testing.T) { enableMetrics: false, headless: true, serviceType: "ClusterIP", + port: sentinelPort, expected: &corev1.Service{ TypeMeta: metav1.TypeMeta{ Kind: "Service", @@ -109,6 +112,7 @@ func TestGenerateServiceDef(t *testing.T) { enableMetrics: false, headless: false, serviceType: "ClusterIP", + port: redisPort, expected: &corev1.Service{ TypeMeta: metav1.TypeMeta{ Kind: "Service", @@ -149,6 +153,7 @@ func TestGenerateServiceDef(t *testing.T) { enableMetrics: false, headless: true, serviceType: "ClusterIP", + port: redisPort, expected: &corev1.Service{ TypeMeta: metav1.TypeMeta{ Kind: "Service", @@ -189,6 +194,7 @@ func TestGenerateServiceDef(t *testing.T) { enableMetrics: true, headless: false, serviceType: "ClusterIP", + port: redisPort, expected: &corev1.Service{ TypeMeta: metav1.TypeMeta{ Kind: "Service", @@ -223,7 +229,7 @@ func TestGenerateServiceDef(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - actual := generateServiceDef(tt.serviceMeta, tt.enableMetrics, metav1.OwnerReference{}, tt.headless, tt.serviceType) + actual := generateServiceDef(tt.serviceMeta, tt.enableMetrics, metav1.OwnerReference{}, tt.headless, tt.serviceType, tt.port) assert.Equal(t, tt.expected, actual) }) } diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 3be4b54f2..72cbba5f6 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -45,6 +45,7 @@ type statefulSetParameters struct { RecreateStatefulSet bool TerminationGracePeriodSeconds *int64 IgnoreAnnotations []string + HostNetwork bool } // containerParameters will define container input params @@ -70,6 +71,7 @@ type containerParameters struct { AdditionalVolume []corev1.Volume AdditionalMountPath []corev1.VolumeMount EnvVars *[]corev1.EnvVar + Port *int } type initContainerParameters struct { @@ -242,6 +244,7 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame PriorityClassName: params.PriorityClassName, Affinity: params.Affinity, TerminationGracePeriodSeconds: params.TerminationGracePeriodSeconds, + HostNetwork: params.HostNetwork, }, }, }, @@ -353,6 +356,7 @@ func generateContainerDef(name string, containerParams containerParameters, clus containerParams.TLSConfig, containerParams.ACLConfig, containerParams.EnvVars, + containerParams.Port, ), ReadinessProbe: getProbeInfo(containerParams.ReadinessProbe), LivenessProbe: getProbeInfo(containerParams.LivenessProbe), @@ -574,7 +578,7 @@ func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { // getEnvironmentVariables returns all the required Environment Variables func getEnvironmentVariables(role string, enabledPassword *bool, secretName *string, secretKey *string, persistenceEnabled *bool, tlsConfig *redisv1beta2.TLSConfig, - aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar) []corev1.EnvVar { + aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar, port *int) []corev1.EnvVar { envVars := []corev1.EnvVar{ {Name: "SERVER_MODE", Value: role}, {Name: "SETUP_MODE", Value: role}, @@ -583,8 +587,18 @@ func getEnvironmentVariables(role string, enabledPassword *bool, secretName *str var redisHost string if role == "sentinel" { redisHost = "redis://localhost:" + strconv.Itoa(sentinelPort) + if port != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: "SENTINEL_PORT", Value: strconv.Itoa(*port), + }) + } } else { redisHost = "redis://localhost:" + strconv.Itoa(redisPort) + if port != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_PORT", Value: strconv.Itoa(*port), + }) + } } if tlsConfig != nil { diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 09a39ced9..66672b475 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -229,6 +229,7 @@ func TestGetEnvironmentVariables(t *testing.T) { tlsConfig *redisv1beta2.TLSConfig aclConfig *redisv1beta2.ACLConfig envVar *[]corev1.EnvVar + port *int expectedEnvironment []corev1.EnvVar }{ { @@ -287,6 +288,7 @@ func TestGetEnvironmentVariables(t *testing.T) { tlsConfig: nil, aclConfig: nil, envVar: nil, + port: nil, expectedEnvironment: []corev1.EnvVar{ {Name: "REDIS_ADDR", Value: "redis://localhost:6379"}, {Name: "SERVER_MODE", Value: "redis"}, @@ -321,6 +323,7 @@ func TestGetEnvironmentVariables(t *testing.T) { envVar: &[]corev1.EnvVar{ {Name: "TEST_ENV", Value: "test-value"}, }, + port: pointer.Int(6380), expectedEnvironment: []corev1.EnvVar{ {Name: "ACL_MODE", Value: "true"}, {Name: "PERSISTENCE_ENABLED", Value: "true"}, @@ -336,6 +339,7 @@ func TestGetEnvironmentVariables(t *testing.T) { {Name: "SERVER_MODE", Value: "cluster"}, {Name: "SETUP_MODE", Value: "cluster"}, {Name: "TEST_ENV", Value: "test-value"}, + {Name: "REDIS_PORT", Value: "6380"}, }, }, { @@ -359,7 +363,7 @@ func TestGetEnvironmentVariables(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { actualEnvironment := getEnvironmentVariables(tt.role, tt.enabledPassword, tt.secretName, - tt.secretKey, tt.persistenceEnabled, tt.tlsConfig, tt.aclConfig, tt.envVar) + tt.secretKey, tt.persistenceEnabled, tt.tlsConfig, tt.aclConfig, tt.envVar, tt.port) assert.ElementsMatch(t, tt.expectedEnvironment, actualEnvironment) }) diff --git a/pkg/util/coalesce.go b/pkg/util/coalesce.go new file mode 100644 index 000000000..f95293825 --- /dev/null +++ b/pkg/util/coalesce.go @@ -0,0 +1,9 @@ +package util + +func Coalesce[T comparable](val, defaultVal T) T { + var t T + if val == t { + return defaultVal + } + return val +} diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml index f2637f495..1d52cf41b 100644 --- a/tests/_config/chainsaw-configuration.yaml +++ b/tests/_config/chainsaw-configuration.yaml @@ -8,7 +8,7 @@ spec: parallel: 1 delayBeforeCleanup: 10s timeouts: - apply: 100s - delete: 100s - assert: 900s - error: 900s + apply: 5m + delete: 5m + assert: 15m + error: 15m diff --git a/tests/_config/kind-config.yaml b/tests/_config/kind-config.yaml index da75a970a..5553b6587 100644 --- a/tests/_config/kind-config.yaml +++ b/tests/_config/kind-config.yaml @@ -5,3 +5,7 @@ nodes: - role: control-plane - role: worker - role: worker +- role: worker +- role: worker +- role: worker +- role: worker \ No newline at end of file diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml index 984bba05e..8e560ef77 100644 --- a/tests/_config/kuttl-test.yaml +++ b/tests/_config/kuttl-test.yaml @@ -9,5 +9,6 @@ testDirs: - tests/e2e/v1beta2/teardown - tests/e2e/v1beta2/ignore-annots - tests/e2e/v1beta2/scaling + - tests/e2e/v1beta2/hostnetwork suppress : - events \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..e9fc5b562 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,45 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: host-network +spec: + steps: + - name: Setup redis cluster on host network + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: ready-pod.yaml + + - name: Install Redis Cli + try: + - script: + timeout: 5m + content: | + sudo apt install redis-tools -y + + - name: Ping Cluster + try: + - script: + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + + - name: Try saving a key + try: + - script: + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo bar + check: + ($stdout=='OK'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml new file mode 100644 index 000000000..afe493178 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml @@ -0,0 +1,49 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + hostNetwork: true + port: 6380 + clusterSize: 3 + clusterVersion: v6 # hostNetwork only works with v6 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml new file mode 100644 index 000000000..e789ed06f --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml @@ -0,0 +1,155 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-leader-0 +spec: + containers: + - name: redis-cluster-v1beta2-leader + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-leader-1 +spec: + containers: + - name: redis-cluster-v1beta2-leader + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-leader-2 +spec: + containers: + - name: redis-cluster-v1beta2-leader + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-follower-0 +spec: + containers: + - name: redis-cluster-v1beta2-follower + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-follower-1 +spec: + containers: + - name: redis-cluster-v1beta2-follower + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-follower-2 +spec: + containers: + - name: redis-cluster-v1beta2-follower + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..7dd11eb37 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml new file mode 100644 index 000000000..56b451984 --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml @@ -0,0 +1,10 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply : + - cluster.yaml +assert : + - ready-cluster.yaml + - ready-sts.yaml + - ready-pvc.yaml + - ready-svc.yaml + - ready-pod.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml new file mode 100644 index 000000000..afe493178 --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml @@ -0,0 +1,49 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + hostNetwork: true + port: 6380 + clusterSize: 3 + clusterVersion: v6 # hostNetwork only works with v6 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml new file mode 100644 index 000000000..e789ed06f --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml @@ -0,0 +1,155 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-leader-0 +spec: + containers: + - name: redis-cluster-v1beta2-leader + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-leader-1 +spec: + containers: + - name: redis-cluster-v1beta2-leader + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-leader-2 +spec: + containers: + - name: redis-cluster-v1beta2-leader + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-follower-0 +spec: + containers: + - name: redis-cluster-v1beta2-follower + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-follower-1 +spec: + containers: + - name: redis-cluster-v1beta2-follower + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running +--- +apiVersion: v1 +kind: Pod +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + name: redis-cluster-v1beta2-follower-2 +spec: + containers: + - name: redis-cluster-v1beta2-follower + env: + - name: PERSISTENCE_ENABLED + value: "true" + - name: REDIS_ADDR + value: "redis://localhost:6379" + - name: REDIS_PORT + value: "6380" + - name: SERVER_MODE + value: "cluster" + - name: SETUP_MODE + value: "cluster" + - name: redis-exporter + hostNetwork: true +status: + phase: Running \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..7dd11eb37 --- /dev/null +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6380 + protocol: TCP + targetPort: 6380 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file From 692c4acb3a3b9a03144e65421895b022227faf6e Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Thu, 14 Dec 2023 02:56:13 +0530 Subject: [PATCH 070/203] test: Try Saving Key (#727) * try: saving a key Signed-off-by: Shubham Gupta * sleep for 5 min Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * host network Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .../redis-cluster/chainsaw-test.yaml | 77 +++++++++++++++++-- .../setup/redis-cluster/chainsaw-test.yaml | 45 +++++++++++ 2 files changed, 117 insertions(+), 5 deletions(-) diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml index e9fc5b562..c8086a5ff 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml @@ -27,19 +27,86 @@ spec: timeout: 5m content: | sudo apt install redis-tools -y - - - name: Ping Cluster + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Redis Cluster from every node try: - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping check: ($stdout=='PONG'): true - - name: Try saving a key + - name: Try saving a key from every node try: - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo bar + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-5 bar-5 check: ($stdout=='OK'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index 1a020f2ca..c96892cb8 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -17,6 +17,7 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml + - name: Ping Cluster try: - script: @@ -24,3 +25,47 @@ spec: kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping check: ($stdout=='PONG'): true + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Try saving a key + try: + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='OK'): true \ No newline at end of file From 62d79b87d86f6e6d8dbf88f450d987a049903f52 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 18 Dec 2023 01:42:03 +0800 Subject: [PATCH 071/203] feat: support exporter custom port (#728) * support exporter custom port Signed-off-by: drivebyer * add e2e Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- Dockerfile | 1 + api/common_types.go | 4 +- api/v1beta2/rediscluster_default.go | 3 + api/zz_generated.deepcopy.go | 5 ++ .../redis.redis.opstreelabs.in_redis.yaml | 6 ++ ...is.redis.opstreelabs.in_redisclusters.yaml | 6 ++ ...edis.opstreelabs.in_redisreplications.yaml | 6 ++ ...s.redis.opstreelabs.in_redissentinels.yaml | 3 + k8sutils/labels.go | 7 ++- k8sutils/labels_test.go | 2 +- k8sutils/redis-cluster.go | 27 +++++---- k8sutils/redis-replication.go | 26 ++++++--- k8sutils/redis-sentinel.go | 24 ++++---- k8sutils/redis-standalone.go | 32 +++++++---- k8sutils/services.go | 23 +++++--- k8sutils/services_test.go | 56 ++++++++++++++++--- k8sutils/statefulset.go | 22 ++++++-- k8sutils/statefulset_test.go | 25 +++++---- pkg/util/coalesce_test.go | 46 +++++++++++++++ .../redis-cluster/chainsaw-test.yaml | 39 +++++++++++++ .../hostnetwork/redis-cluster/cluster.yaml | 1 + .../hostnetwork/redis-cluster/ready-svc.yaml | 20 +++---- 22 files changed, 298 insertions(+), 86 deletions(-) create mode 100644 pkg/util/coalesce_test.go diff --git a/Dockerfile b/Dockerfile index f953b9f25..1a76f506e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ COPY main.go main.go COPY api/ api/ COPY controllers/ controllers/ COPY k8sutils/ k8sutils/ +COPY pkg/ pkg/ COPY mocks/ mocks/ # Build diff --git a/api/common_types.go b/api/common_types.go index 8d78ad389..40cbd9695 100644 --- a/api/common_types.go +++ b/api/common_types.go @@ -36,7 +36,9 @@ type ExistingPasswordSecret struct { // RedisExporter interface will have the information for redis exporter related stuff // +k8s:deepcopy-gen=true type RedisExporter struct { - Enabled bool `json:"enabled,omitempty"` + Enabled bool `json:"enabled,omitempty"` + // +kubebuilder:default:=9121 + Port *int `json:"port,omitempty"` Image string `json:"image"` Resources *corev1.ResourceRequirements `json:"resources,omitempty"` ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` diff --git a/api/v1beta2/rediscluster_default.go b/api/v1beta2/rediscluster_default.go index 7dbc9ea8f..9b6c16ad1 100644 --- a/api/v1beta2/rediscluster_default.go +++ b/api/v1beta2/rediscluster_default.go @@ -7,4 +7,7 @@ func (r *RedisCluster) SetDefault() { if r.Spec.Port == nil { r.Spec.Port = pointer.Int(6379) } + if r.Spec.RedisExporter != nil && r.Spec.RedisExporter.Port == nil { + r.Spec.RedisExporter.Port = pointer.Int(9121) + } } diff --git a/api/zz_generated.deepcopy.go b/api/zz_generated.deepcopy.go index efeda74c2..499bb939b 100644 --- a/api/zz_generated.deepcopy.go +++ b/api/zz_generated.deepcopy.go @@ -162,6 +162,11 @@ func (in *RedisConfig) DeepCopy() *RedisConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisExporter) DeepCopyInto(out *RedisExporter) { *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int) + **out = **in + } if in.Resources != nil { in, out := &in.Resources, &out.Resources *out = new(v1.ResourceRequirements) diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index 2222d4ed0..fec228a5e 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -1274,6 +1274,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -5615,6 +5618,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index cdf11fc59..e525f917e 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -402,6 +402,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -5920,6 +5923,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index cf9dbd5bf..76856bcfc 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -1276,6 +1276,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -5620,6 +5623,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 91c5b1e5f..e89f42317 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -3316,6 +3316,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. diff --git a/k8sutils/labels.go b/k8sutils/labels.go index b8e780dc9..4d0d4518d 100644 --- a/k8sutils/labels.go +++ b/k8sutils/labels.go @@ -1,6 +1,8 @@ package k8sutils import ( + "strconv" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -111,13 +113,16 @@ func filterAnnotations(anots map[string]string, ignoreAnnots ...string) map[stri } // generateServiceAnots generates and returns service annotations -func generateServiceAnots(stsMeta metav1.ObjectMeta, additionalSvcAnnotations map[string]string) map[string]string { +func generateServiceAnots(stsMeta metav1.ObjectMeta, additionalSvcAnnotations map[string]string, epp exporterPortProvider) map[string]string { anots := map[string]string{ "redis.opstreelabs.in": "true", "redis.opstreelabs.instance": stsMeta.GetName(), "prometheus.io/scrape": "true", "prometheus.io/port": "9121", } + if exporterPort, ok := epp(); ok { + anots["prometheus.io/port"] = strconv.Itoa(exporterPort) + } for k, v := range stsMeta.GetAnnotations() { anots[k] = v } diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go index 10622b513..274f9c1a0 100644 --- a/k8sutils/labels_test.go +++ b/k8sutils/labels_test.go @@ -215,7 +215,7 @@ func TestGenerateServiceAnots(t *testing.T) { "additional-annotation": "additional-value", } - resultAnnotations := generateServiceAnots(stsMeta, additionalSvcAnnotations) + resultAnnotations := generateServiceAnots(stsMeta, additionalSvcAnnotations, defaultExporterPortProvider) if !reflect.DeepEqual(resultAnnotations, expectedAnnotations) { t.Errorf("Expected annotations to be %v but got %v", expectedAnnotations, resultAnnotations) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index b6ae773b3..0962d90ef 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -3,7 +3,9 @@ package k8sutils import ( commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" ) // RedisClusterSTS is a interface to call Redis Statefulset function @@ -124,11 +126,12 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security if cr.Spec.RedisExporter.Resources != nil { containerProp.RedisExporterResources = cr.Spec.RedisExporter.Resources } - if cr.Spec.RedisExporter.EnvVars != nil { containerProp.RedisExporterEnv = cr.Spec.RedisExporter.EnvVars } - + if cr.Spec.RedisExporter.Port != nil { + containerProp.RedisExporterPort = cr.Spec.RedisExporter.Port + } } if readinessProbeDef != nil { containerProp.ReadinessProbe = readinessProbeDef @@ -235,25 +238,29 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) labels := getRedisLabels(serviceName, cluster, service.RedisServiceRole, cr.ObjectMeta.Labels) - annotations := generateServiceAnots(cr.ObjectMeta, nil) - if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { - enableMetrics = true + var epp exporterPortProvider + if cr.Spec.RedisExporter != nil { + epp = func() (port int, enable bool) { + defaultP := pointer.Int(redisExporterPort) + return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled + } } else { - enableMetrics = false + epp = disableMetrics } + annotations := generateServiceAnots(cr.ObjectMeta, nil, epp) additionalServiceAnnotations := map[string]string{} if cr.Spec.KubernetesConfig.Service != nil { additionalServiceAnnotations = cr.Spec.KubernetesConfig.Service.ServiceAnnotations } objectMetaInfo := generateObjectMetaInformation(serviceName, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, annotations) - additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisClusterAsOwner(cr), false, true, "ClusterIP", *cr.Spec.Port) + additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, true, "ClusterIP", *cr.Spec.Port) if err != nil { logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole) return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), enableMetrics, false, "ClusterIP", *cr.Spec.Port) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), epp, false, "ClusterIP", *cr.Spec.Port) if err != nil { logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -262,7 +269,7 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), false, false, additionalServiceType, *cr.Spec.Port) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, additionalServiceType, *cr.Spec.Port) if err != nil { logger.Error(err, "Cannot create additional service for Redis", "Setup.Type", service.RedisServiceRole) return err diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 5e5223a3c..b1452d174 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -1,30 +1,38 @@ package k8sutils -import redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" +import ( + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/utils/pointer" +) // CreateReplicationService method will create replication service for Redis func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) - annotations := generateServiceAnots(cr.ObjectMeta, nil) - if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { - enableMetrics = true + var epp exporterPortProvider + if cr.Spec.RedisExporter != nil { + epp = func() (port int, enable bool) { + defaultP := pointer.Int(redisExporterPort) + return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled + } } else { - enableMetrics = false + epp = disableMetrics } + annotations := generateServiceAnots(cr.ObjectMeta, nil, epp) additionalServiceAnnotations := map[string]string{} if cr.Spec.KubernetesConfig.Service != nil { additionalServiceAnnotations = cr.Spec.KubernetesConfig.Service.ServiceAnnotations } objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, annotations) - additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisReplicationAsOwner(cr), false, true, "ClusterIP", redisPort) + additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisReplicationAsOwner(cr), disableMetrics, true, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create replication headless service for Redis") return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisReplicationAsOwner(cr), enableMetrics, false, "ClusterIP", redisPort) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisReplicationAsOwner(cr), epp, false, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create replication service for Redis") return err @@ -33,7 +41,7 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisReplicationAsOwner(cr), false, false, additionalServiceType, redisPort) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisReplicationAsOwner(cr), disableMetrics, false, additionalServiceType, redisPort) if err != nil { logger.Error(err, "Cannot create additional service for Redis Replication") return err diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 6eef41716..014284772 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -4,6 +4,8 @@ import ( "context" "encoding/json" "errors" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/utils/pointer" commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" @@ -198,14 +200,16 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) labels := getRedisLabels(serviceName, sentinel, service.RedisServiceRole, cr.ObjectMeta.Labels) - annotations := generateServiceAnots(cr.ObjectMeta, nil) - - if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { - enableMetrics = true + var epp exporterPortProvider + if cr.Spec.RedisExporter != nil { + epp = func() (port int, enable bool) { + defaultP := pointer.Int(redisExporterPort) + return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled + } } else { - enableMetrics = false + epp = disableMetrics } - + annotations := generateServiceAnots(cr.ObjectMeta, nil, epp) additionalServiceAnnotations := map[string]string{} if cr.Spec.KubernetesConfig.Service != nil { additionalServiceAnnotations = cr.Spec.KubernetesConfig.Service.ServiceAnnotations @@ -213,14 +217,14 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. objectMetaInfo := generateObjectMetaInformation(serviceName, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, annotations) - additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) + additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisSentinelAsOwner(cr), false, true, "ClusterIP", sentinelPort) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisSentinelAsOwner(cr), disableMetrics, true, "ClusterIP", sentinelPort) if err != nil { logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole) return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisSentinelAsOwner(cr), enableMetrics, false, "ClusterIP", sentinelPort) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisSentinelAsOwner(cr), epp, false, "ClusterIP", sentinelPort) if err != nil { logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -230,7 +234,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisSentinelAsOwner(cr), false, false, additionalServiceType, sentinelPort) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisSentinelAsOwner(cr), disableMetrics, false, additionalServiceType, sentinelPort) if err != nil { logger.Error(err, "Cannot create additional service for Redis", "Setup.Type", service.RedisServiceRole) return err diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 33d2e4c03..dd116b2ba 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -1,34 +1,42 @@ package k8sutils -import redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - -var ( - enableMetrics bool +import ( + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/utils/pointer" ) +//var ( +// enableMetrics bool +//) + // CreateStandaloneService method will create standalone service for Redis func CreateStandaloneService(cr *redisv1beta2.Redis) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) - annotations := generateServiceAnots(cr.ObjectMeta, nil) - if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled { - enableMetrics = true + var epp exporterPortProvider + if cr.Spec.RedisExporter != nil { + epp = func() (port int, enable bool) { + defaultP := pointer.Int(redisExporterPort) + return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled + } } else { - enableMetrics = false + epp = disableMetrics } + annotations := generateServiceAnots(cr.ObjectMeta, nil, epp) additionalServiceAnnotations := map[string]string{} if cr.Spec.KubernetesConfig.Service != nil { additionalServiceAnnotations = cr.Spec.KubernetesConfig.Service.ServiceAnnotations } objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, annotations) - additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisAsOwner(cr), false, true, "ClusterIP", redisPort) + additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisAsOwner(cr), disableMetrics, true, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create standalone headless service for Redis") return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisAsOwner(cr), enableMetrics, false, "ClusterIP", redisPort) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisAsOwner(cr), epp, false, "ClusterIP", redisPort) if err != nil { logger.Error(err, "Cannot create standalone service for Redis") return err @@ -37,7 +45,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisAsOwner(cr), false, false, additionalServiceType, redisPort) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisAsOwner(cr), disableMetrics, false, additionalServiceType, redisPort) if err != nil { logger.Error(err, "Cannot create additional service for Redis") return err diff --git a/k8sutils/services.go b/k8sutils/services.go index c28e6ba29..30a50027b 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -22,8 +22,15 @@ var ( serviceType corev1.ServiceType ) +// exporterPortProvider return the exporter port if bool is true +type exporterPortProvider func() (port int, enable bool) + +var disableMetrics exporterPortProvider = func() (int, bool) { + return 0, false +} + // generateServiceDef generates service definition for Redis -func generateServiceDef(serviceMeta metav1.ObjectMeta, enableMetrics bool, ownerDef metav1.OwnerReference, headless bool, serviceType string, port int) *corev1.Service { +func generateServiceDef(serviceMeta metav1.ObjectMeta, epp exporterPortProvider, ownerDef metav1.OwnerReference, headless bool, serviceType string, port int) *corev1.Service { var PortName string if serviceMeta.Labels["role"] == "sentinel" { PortName = "sentinel-client" @@ -50,8 +57,8 @@ func generateServiceDef(serviceMeta metav1.ObjectMeta, enableMetrics bool, owner if headless { service.Spec.ClusterIP = "None" } - if enableMetrics { - redisExporterService := enableMetricsPort() + if exporterPort, ok := epp(); ok { + redisExporterService := enableMetricsPort(exporterPort) service.Spec.Ports = append(service.Spec.Ports, *redisExporterService) } AddOwnerRefToObject(service, ownerDef) @@ -59,11 +66,11 @@ func generateServiceDef(serviceMeta metav1.ObjectMeta, enableMetrics bool, owner } // enableMetricsPort will enable the metrics for Redis service -func enableMetricsPort() *corev1.ServicePort { +func enableMetricsPort(port int) *corev1.ServicePort { return &corev1.ServicePort{ Name: redisExporterPortName, - Port: redisExporterPort, - TargetPort: intstr.FromInt(int(redisExporterPort)), + Port: int32(port), + TargetPort: intstr.FromInt(port), Protocol: corev1.ProtocolTCP, } } @@ -143,9 +150,9 @@ func serviceLogger(namespace string, name string) logr.Logger { } // CreateOrUpdateService method will create or update Redis service -func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, enableMetrics, headless bool, serviceType string, port int) error { +func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, epp exporterPortProvider, headless bool, serviceType string, port int) error { logger := serviceLogger(namespace, serviceMeta.Name) - serviceDef := generateServiceDef(serviceMeta, enableMetrics, ownerDef, headless, serviceType, port) + serviceDef := generateServiceDef(serviceMeta, epp, ownerDef, headless, serviceType, port) storedService, err := getService(namespace, serviceMeta.Name) if err != nil { if errors.IsNotFound(err) { diff --git a/k8sutils/services_test.go b/k8sutils/services_test.go index cbd012b2f..786783944 100644 --- a/k8sutils/services_test.go +++ b/k8sutils/services_test.go @@ -9,11 +9,15 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" ) +var defaultExporterPortProvider exporterPortProvider = func() (int, bool) { + return redisExporterPort, true +} + func TestGenerateServiceDef(t *testing.T) { tests := []struct { name string serviceMeta metav1.ObjectMeta - enableMetrics bool + enableMetrics exporterPortProvider headless bool serviceType string port int @@ -27,7 +31,7 @@ func TestGenerateServiceDef(t *testing.T) { "role": "sentinel", }, }, - enableMetrics: false, + enableMetrics: disableMetrics, headless: false, serviceType: "ClusterIP", port: sentinelPort, @@ -68,7 +72,7 @@ func TestGenerateServiceDef(t *testing.T) { "role": "sentinel", }, }, - enableMetrics: false, + enableMetrics: disableMetrics, headless: true, serviceType: "ClusterIP", port: sentinelPort, @@ -109,7 +113,7 @@ func TestGenerateServiceDef(t *testing.T) { "role": "redis", }, }, - enableMetrics: false, + enableMetrics: disableMetrics, headless: false, serviceType: "ClusterIP", port: redisPort, @@ -150,7 +154,7 @@ func TestGenerateServiceDef(t *testing.T) { "role": "redis", }, }, - enableMetrics: false, + enableMetrics: disableMetrics, headless: true, serviceType: "ClusterIP", port: redisPort, @@ -191,7 +195,7 @@ func TestGenerateServiceDef(t *testing.T) { "role": "redis", }, }, - enableMetrics: true, + enableMetrics: defaultExporterPortProvider, headless: false, serviceType: "ClusterIP", port: redisPort, @@ -217,7 +221,7 @@ func TestGenerateServiceDef(t *testing.T) { TargetPort: intstr.FromInt(int(redisPort)), Protocol: corev1.ProtocolTCP, }, - *enableMetricsPort(), + *enableMetricsPort(redisExporterPort), }, Selector: map[string]string{"role": "redis"}, ClusterIP: "", @@ -234,3 +238,41 @@ func TestGenerateServiceDef(t *testing.T) { }) } } + +func TestGenerateServiceType(t *testing.T) { + tests := []struct { + name string + serviceType string + expectedType corev1.ServiceType + }{ + { + name: "LoadBalancer service type", + serviceType: "LoadBalancer", + expectedType: corev1.ServiceTypeLoadBalancer, + }, + { + name: "NodePort service type", + serviceType: "NodePort", + expectedType: corev1.ServiceTypeNodePort, + }, + { + name: "ClusterIP service type", + serviceType: "ClusterIP", + expectedType: corev1.ServiceTypeClusterIP, + }, + { + name: "Default service type", + serviceType: "InvalidServiceType", + expectedType: corev1.ServiceTypeClusterIP, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actualType := generateServiceType(tt.serviceType) + if actualType != tt.expectedType { + t.Errorf("Expected service type %v, but got %v", tt.expectedType, actualType) + } + }) + } +} diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 72cbba5f6..750498464 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -8,6 +8,9 @@ import ( "strconv" "strings" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/utils/pointer" + commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/banzaicloud/k8s-objectmatcher/patch" @@ -58,6 +61,7 @@ type containerParameters struct { RedisExporterImagePullPolicy corev1.PullPolicy RedisExporterResources *corev1.ResourceRequirements RedisExporterEnv *[]corev1.EnvVar + RedisExporterPort *int Role string EnabledPassword *bool SecretName *string @@ -468,12 +472,12 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { Name: redisExporterContainer, Image: params.RedisExporterImage, ImagePullPolicy: params.RedisExporterImagePullPolicy, - Env: getExporterEnvironmentVariables(params.TLSConfig, params.RedisExporterEnv), + Env: getExporterEnvironmentVariables(params), VolumeMounts: getVolumeMount("", nil, false, false, nil, params.AdditionalMountPath, params.TLSConfig, params.ACLConfig), // We need/want the tls-certs but we DON'T need the PVC (if one is available) Ports: []corev1.ContainerPort{ { Name: redisExporterPortName, - ContainerPort: redisExporterPort, + ContainerPort: int32(*util.Coalesce(params.RedisExporterPort, pointer.Int(redisExporterPort))), Protocol: corev1.ProtocolTCP, }, }, @@ -484,9 +488,9 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { return exporterDefinition } -func getExporterEnvironmentVariables(tlsConfig *redisv1beta2.TLSConfig, env *[]corev1.EnvVar) []corev1.EnvVar { +func getExporterEnvironmentVariables(params containerParameters) []corev1.EnvVar { var envVars []corev1.EnvVar - if tlsConfig != nil { + if params.TLSConfig != nil { envVars = append(envVars, corev1.EnvVar{ Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", Value: "/tls/tls.key", @@ -504,8 +508,14 @@ func getExporterEnvironmentVariables(tlsConfig *redisv1beta2.TLSConfig, env *[]c Value: "true", }) } - if env != nil { - envVars = append(envVars, *env...) + if params.Port != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_EXPORTER_WEB_LISTEN_ADDRESS", + Value: fmt.Sprintf(":%d", *params.RedisExporterPort), + }) + } + if params.RedisExporterEnv != nil { + envVars = append(envVars, *params.RedisExporterEnv...) } return envVars } diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 66672b475..925c3f1a3 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -373,24 +373,27 @@ func TestGetEnvironmentVariables(t *testing.T) { func Test_getExporterEnvironmentVariables(t *testing.T) { tests := []struct { name string + params containerParameters tlsConfig *redisv1beta2.TLSConfig envVar *[]corev1.EnvVar expectedEnvironment []corev1.EnvVar }{ { name: "Test with tls enabled and env var", - tlsConfig: &redisv1beta2.TLSConfig{ - TLSConfig: common.TLSConfig{ - CaKeyFile: "test_ca.crt", - CertKeyFile: "test_tls.crt", - KeyFile: "test_tls.key", - Secret: corev1.SecretVolumeSource{ - SecretName: "tls-secret", + params: containerParameters{ + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + CaKeyFile: "test_ca.crt", + CertKeyFile: "test_tls.crt", + KeyFile: "test_tls.key", + Secret: corev1.SecretVolumeSource{ + SecretName: "tls-secret", + }, }, }, - }, - envVar: &[]corev1.EnvVar{ - {Name: "TEST_ENV", Value: "test-value"}, + RedisExporterEnv: &[]corev1.EnvVar{ + {Name: "TEST_ENV", Value: "test-value"}, + }, }, expectedEnvironment: []corev1.EnvVar{ {Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", Value: "/tls/tls.key"}, @@ -403,7 +406,7 @@ func Test_getExporterEnvironmentVariables(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - actualEnvironment := getExporterEnvironmentVariables(tt.tlsConfig, tt.envVar) + actualEnvironment := getExporterEnvironmentVariables(tt.params) assert.ElementsMatch(t, tt.expectedEnvironment, actualEnvironment) }) diff --git a/pkg/util/coalesce_test.go b/pkg/util/coalesce_test.go new file mode 100644 index 000000000..1b3dfffd5 --- /dev/null +++ b/pkg/util/coalesce_test.go @@ -0,0 +1,46 @@ +package util + +import "testing" + +func TestCoalesce(t *testing.T) { + tests := []struct { + name string + val int + defaultVal int + expectedVal int + }{ + { + name: "Value is zero, default value is provided", + val: 0, + defaultVal: 10, + expectedVal: 10, + }, + { + name: "Value is non-zero, default value is provided", + val: 5, + defaultVal: 10, + expectedVal: 5, + }, + { + name: "Value is zero, default value is zero", + val: 0, + defaultVal: 0, + expectedVal: 0, + }, + { + name: "Value is non-zero, default value is zero", + val: 5, + defaultVal: 0, + expectedVal: 5, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actualVal := Coalesce(tt.val, tt.defaultVal) + if actualVal != tt.expectedVal { + t.Errorf("Expected value %v, but got %v", tt.expectedVal, actualVal) + } + }) + } +} diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml index c8086a5ff..c17efa8f1 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml @@ -72,6 +72,45 @@ spec: check: ($stdout=='PONG'): true + - name: Curl Exporter from every node + try: + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + check: + ($stdout=='200'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + check: + ($stdout=='200'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + check: + ($stdout=='200'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + check: + ($stdout=='200'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + check: + ($stdout=='200'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + check: + ($stdout=='200'): true + - name: Try saving a key from every node try: - script: diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml index afe493178..687044052 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml @@ -23,6 +23,7 @@ spec: memory: 128Mi redisExporter: enabled: true + port: 9122 image: quay.io/opstree/redis-exporter:v1.44.0 imagePullPolicy: Always resources: diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml index 7dd11eb37..1d248a5d5 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" + prometheus.io/port: "9122" prometheus.io/scrape: "true" redis.opstreelabs.in: "true" redis.opstreelabs.instance: redis-cluster-v1beta2 @@ -34,7 +34,7 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" + prometheus.io/port: "9122" prometheus.io/scrape: "true" redis.opstreelabs.in: "true" redis.opstreelabs.instance: redis-cluster-v1beta2 @@ -55,9 +55,9 @@ spec: protocol: TCP targetPort: 6380 - name: redis-exporter - port: 9121 + port: 9122 protocol: TCP - targetPort: 9121 + targetPort: 9122 selector: app: redis-cluster-v1beta2-leader redis_setup_type: cluster @@ -70,7 +70,7 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" + prometheus.io/port: "9122" prometheus.io/scrape: "true" redis.opstreelabs.in: "true" redis.opstreelabs.instance: redis-cluster-v1beta2 @@ -103,7 +103,7 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" + prometheus.io/port: "9122" prometheus.io/scrape: "true" redis.opstreelabs.in: "true" redis.opstreelabs.instance: redis-cluster-v1beta2 @@ -124,9 +124,9 @@ spec: protocol: TCP targetPort: 6380 - name: redis-exporter - port: 9121 + port: 9122 protocol: TCP - targetPort: 9121 + targetPort: 9122 selector: app: redis-cluster-v1beta2-follower redis_setup_type: cluster @@ -139,7 +139,7 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" + prometheus.io/port: "9122" prometheus.io/scrape: "true" redis.opstreelabs.in: "true" redis.opstreelabs.instance: redis-cluster-v1beta2 @@ -171,7 +171,7 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" + prometheus.io/port: "9122" prometheus.io/scrape: "true" redis.opstreelabs.in: "true" redis.opstreelabs.instance: redis-cluster-v1beta2 From 50a62d185a3fc7edd51798eb5b4251de26347498 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:39:54 +0530 Subject: [PATCH 072/203] test: Add replication to chainsaw setup (#730) Signed-off-by: Shubham Gupta --- .../redis-replication/chainsaw-test.yaml | 18 ++++ .../setup/redis-replication/ready-pvc.yaml | 44 +++++++++ .../setup/redis-replication/ready-sts.yaml | 19 ++++ .../setup/redis-replication/ready-svc.yaml | 90 +++++++++++++++++++ .../setup/redis-replication/replication.yaml | 27 ++++++ 5 files changed, 198 insertions(+) create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml new file mode 100644 index 000000000..b27d60306 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml @@ -0,0 +1,18 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-replication-setup +spec: + steps: + - try: + - apply: + file: replication.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml new file mode 100644 index 000000000..3fb33dcac --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file From 0ed854fc14e3cf519504846c50c5d441f77525c0 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 18 Dec 2023 00:50:48 +0530 Subject: [PATCH 073/203] test: Setting Password on Redis Cluster (#729) * try: Setting Password on Redis Cluster Signed-off-by: Shubham Gupta * add to CI Signed-off-by: Shubham Gupta * fix-name Signed-off-by: Shubham Gupta * add Exporter Signed-off-by: Shubham Gupta * fix stdout Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 1 + .../password/redis-cluster/chainsaw-test.yaml | 184 ++++++++++++++++ .../password/redis-cluster/cluster.yaml | 50 +++++ .../password/redis-cluster/ready-cluster.yaml | 7 + .../password/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../password/redis-cluster/ready-sts.yaml | 25 +++ .../password/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ .../password/redis-cluster/secret.yaml | 8 + .../setup/redis-cluster/chainsaw-test.yaml | 37 +++- 9 files changed, 688 insertions(+), 6 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index dcf25b81a..69b3f9b22 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -18,6 +18,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/teardown/ - ./tests/e2e-chainsaw/v1beta2/setup/ - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ + - ./tests/e2e-chainsaw/v1beta2/password/ steps: - name: Checkout code diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..be3e2642e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,184 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-password +spec: + steps: + - try: + - apply: + file: cluster.yaml + - apply: + file: secret.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: secret.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Cluster With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + + - name: Try saving a key With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-5 bar-5 + check: + ($stdout=='OK'): true + + - name: Ping Cluster Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + + - name: Try saving a key Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='NOAUTH Authentication required.'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml new file mode 100644 index 000000000..257720a64 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml @@ -0,0 +1,50 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml new file mode 100644 index 000000000..cf1cf0a6a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret +data: + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index c96892cb8..9639fac86 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -18,6 +18,11 @@ spec: - assert: file: ready-pvc.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Cluster try: - script: @@ -25,13 +30,33 @@ spec: kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping check: ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Try saving a key + - name: Try saving a key With Password try: - script: timeout: 30s From 25d807ae245be434789862734ede9eb81dd4a442 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 18 Dec 2023 01:52:22 +0530 Subject: [PATCH 074/203] sentinel-setup (#733) Signed-off-by: Shubham Gupta --- .../setup/redis-sentinel/chainsaw-test.yaml | 15 +++ .../setup/redis-sentinel/ready-sts.yaml | 35 +++++++ .../setup/redis-sentinel/ready-svc.yaml | 96 +++++++++++++++++++ .../setup/redis-sentinel/sentinel.yaml | 22 +++++ 4 files changed, 168 insertions(+) create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml new file mode 100644 index 000000000..5e2472bb1 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-sentinel-setup +spec: + steps: + - try: + - apply: + file: sentinel.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml new file mode 100644 index 000000000..c6056ab05 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + selector: + matchLabels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + serviceName: redis-sentinel-sentinel-headless + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml new file mode 100644 index 000000000..4ce66a032 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + clusterIP: None + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml new file mode 100644 index 000000000..7260486a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + # redisSentinelConfig: + # redisReplicationName : redis-replication + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file From d8ad9f9add9b1300cda146bb5b9cb2c457673026 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 18 Dec 2023 02:26:24 +0530 Subject: [PATCH 075/203] test: Try ping and save key on redis replication (#731) * test: Try ping and save key on redis replication Signed-off-by: Shubham Gupta * saving without password Signed-off-by: Shubham Gupta * fix test Signed-off-by: Shubham Gupta * try fix Signed-off-by: Shubham Gupta * try Comment Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .../redis-replication/chainsaw-test.yaml | 110 ++++++++++++++++++ .../password/redis-replication/ready-pvc.yaml | 44 +++++++ .../password/redis-replication/ready-sts.yaml | 19 +++ .../password/redis-replication/ready-svc.yaml | 90 ++++++++++++++ .../redis-replication/replication.yaml | 30 +++++ .../password/redis-replication/secret.yaml | 8 ++ .../redis-replication/chainsaw-test.yaml | 41 +++++++ 7 files changed, 342 insertions(+) create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml new file mode 100644 index 000000000..57ff2e326 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml @@ -0,0 +1,110 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-replication-password +spec: + steps: + - try: + - apply: + file: replication.yaml + - apply: + file: secret.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: secret.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Replicated Cluster With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + + - name: Try saving a key With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree@1234 set foo-0 bar-0 + check: + ($stdout=='OK'): true + # - script: + # timeout: 10s + # content: | + # kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree@1234 set foo-1 bar-1 + # check: + # ($stdout=='READONLY You can't write against a read only replica.'): true + # - script: + # timeout: 10s + # content: | + # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree@1234 set foo-2 bar-2 + # check: + # ($stdout=='READONLY You can't write against a read only replica.'): true + + - name: Ping Replicated Cluster Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + + - name: Try saving a key Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 set foo-1 bar-1 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 set foo-2 bar-2 + check: + ($stdout=='NOAUTH Authentication required.'): true diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml new file mode 100644 index 000000000..7ee034870 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml new file mode 100644 index 000000000..cf1cf0a6a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret +data: + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml index b27d60306..bd117a79b 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml @@ -16,3 +16,44 @@ spec: - assert: file: ready-pvc.yaml + - name: Ping Replicated Cluster + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Try saving a key + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + # - script: + # timeout: 10s + # content: | + # kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 set foo-1 bar-1 + # check: + # ($stdout==`READONLY You can't write against a read only replica.`): true + # - script: + # timeout: 10s + # content: | + # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 set foo-2 bar-2 + # check: + # ($stdout==`READONLY You can't write against a read only replica.`): true \ No newline at end of file From deefc14c2d1ea388fd14890cae4d2fd11dc9c2de Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 18 Dec 2023 06:59:20 +0530 Subject: [PATCH 076/203] test: HA-setup ( Replication and Sentinel ) Unsecured | Partial Secured (#732) * add empty test files Signed-off-by: Shubham Gupta * add replication file Signed-off-by: Shubham Gupta * add to CI Signed-off-by: Shubham Gupta * fix : HA setup Signed-off-by: Shubham Gupta * fix files Signed-off-by: Shubham Gupta * sentinel size 1 Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * ping cluster Signed-off-by: Shubham Gupta * fix svc name Signed-off-by: Shubham Gupta * try saving a key Signed-off-by: Shubham Gupta * fix-bug Signed-off-by: Shubham Gupta * fix port Signed-off-by: Shubham Gupta * don't save key Signed-off-by: Shubham Gupta * fix quorum Signed-off-by: Shubham Gupta * test: partial secured sentinel Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * test: partial secured with redis replication Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta * make max parallel Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 1 + tests/_config/chainsaw-configuration.yaml | 1 - .../ha-setup/secured/fully-secured/random | 0 .../replication-password/chainsaw-test.yaml | 58 +++++++++++ .../replication-password/cli-pod.yaml | 14 +++ .../replication-password/configmap.yaml | 8 ++ .../ready-replication-pvc.yaml | 44 +++++++++ .../ready-replication-sts.yaml | 19 ++++ .../ready-replication-svc.yaml | 90 +++++++++++++++++ .../ready-sentinel-sts.yaml | 35 +++++++ .../ready-sentinel-svc.yaml | 96 +++++++++++++++++++ .../replication-password/replication.yaml | 30 ++++++ .../replication-password/secret.yaml | 8 ++ .../replication-password/sentinel.yaml | 24 +++++ .../sentinel-password/chainsaw-test.yaml | 63 ++++++++++++ .../sentinel-password/cli-pod.yaml | 14 +++ .../ready-replication-pvc.yaml | 44 +++++++++ .../ready-replication-sts.yaml | 19 ++++ .../ready-replication-svc.yaml | 90 +++++++++++++++++ .../sentinel-password/ready-sentinel-sts.yaml | 35 +++++++ .../sentinel-password/ready-sentinel-svc.yaml | 96 +++++++++++++++++++ .../sentinel-password/replication.yaml | 27 ++++++ .../sentinel-password/secret.yaml | 8 ++ .../sentinel-password/sentinel.yaml | 26 +++++ .../ha-setup/unsecured/chainsaw-test.yaml | 50 ++++++++++ .../v1beta2/ha-setup/unsecured/cli-pod.yaml | 14 +++ .../unsecured/ready-replication-pvc.yaml | 44 +++++++++ .../unsecured/ready-replication-sts.yaml | 19 ++++ .../unsecured/ready-replication-svc.yaml | 90 +++++++++++++++++ .../unsecured/ready-sentinel-sts.yaml | 35 +++++++ .../unsecured/ready-sentinel-svc.yaml | 96 +++++++++++++++++++ .../ha-setup/unsecured/replication.yaml | 27 ++++++ .../v1beta2/ha-setup/unsecured/sentinel.yaml | 23 +++++ 33 files changed, 1247 insertions(+), 1 deletion(-) create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/secret.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/secret.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index 69b3f9b22..0bf22ebe2 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -19,6 +19,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/setup/ - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ - ./tests/e2e-chainsaw/v1beta2/password/ + - ./tests/e2e-chainsaw/v1beta2/ha-setup/ steps: - name: Checkout code diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml index 1d52cf41b..828895dbb 100644 --- a/tests/_config/chainsaw-configuration.yaml +++ b/tests/_config/chainsaw-configuration.yaml @@ -5,7 +5,6 @@ kind: Configuration metadata: name: chainsaw-configuration spec: - parallel: 1 delayBeforeCleanup: 10s timeouts: apply: 5m diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random new file mode 100644 index 000000000..e69de29bb diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml new file mode 100644 index 000000000..b8684bd82 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml @@ -0,0 +1,58 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-ha-setup-partial-secured-replication +spec: + steps: + - try: + - create: + file: secret.yaml + - assert: + file: secret.yaml + - apply: + file: replication.yaml + - assert: + file: ready-replication-sts.yaml + - assert: + file: ready-replication-svc.yaml + - assert: + file: ready-replication-pvc.yaml + - create: + file: configmap.yaml + - assert: + file: configmap.yaml + - apply: + file: sentinel.yaml + - assert: + file: ready-sentinel-sts.yaml + - assert: + file: ready-sentinel-svc.yaml + - create: + file: cli-pod.yaml + - assert: + file: cli-pod.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Replicated Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + + - name: Ping Sentinel Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping + check: + ($stdout=='PONG'): true diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml new file mode 100644 index 000000000..e8501253e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis + labels: + app: redis +spec: + containers: + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml new file mode 100644 index 000000000..529906f34 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: sentinel-external-config +data: + redis-sentinel-additional.conf: | + sentinel auth-pass myMaster Opstree@1234 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml new file mode 100644 index 000000000..28ed1dace --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + selector: + matchLabels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + serviceName: redis-sentinel-sentinel-headless + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel +status: + readyReplicas: 1 + replicas: 1 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml new file mode 100644 index 000000000..4ce66a032 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + clusterIP: None + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml new file mode 100644 index 000000000..cde71e67e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + redisSecret: + name: redis-secret + key: password + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/secret.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/secret.yaml new file mode 100644 index 000000000..cf1cf0a6a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret +data: + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml new file mode 100644 index 000000000..ffbe11e1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 1 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + quorum: "1" + additionalSentinelConfig: sentinel-external-config + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml new file mode 100644 index 000000000..834f7caef --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml @@ -0,0 +1,63 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-ha-setup-partial-secured-sentinel +spec: + steps: + - try: + - apply: + file: replication.yaml + - assert: + file: ready-replication-sts.yaml + - assert: + file: ready-replication-svc.yaml + - assert: + file: ready-replication-pvc.yaml + - create: + file: secret.yaml + - assert: + file: secret.yaml + - apply: + file: sentinel.yaml + - assert: + file: ready-sentinel-sts.yaml + - assert: + file: ready-sentinel-svc.yaml + - create: + file: cli-pod.yaml + - assert: + file: cli-pod.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Replicated Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Ping Sentinel Service from Cli Pod With password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + + - name: Ping Sentinel Service from Cli Pod Without password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml new file mode 100644 index 000000000..e8501253e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis + labels: + app: redis +spec: + containers: + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml new file mode 100644 index 000000000..28ed1dace --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + selector: + matchLabels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + serviceName: redis-sentinel-sentinel-headless + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel +status: + readyReplicas: 1 + replicas: 1 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml new file mode 100644 index 000000000..4ce66a032 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + clusterIP: None + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml new file mode 100644 index 000000000..3fb33dcac --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/secret.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/secret.yaml new file mode 100644 index 000000000..cf1cf0a6a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret +data: + password: T3BzdHJlZUAxMjM0Cg== +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml new file mode 100644 index 000000000..bd350a122 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 1 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + quorum: "1" + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + redisSecret: + name: redis-secret + key: password + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml new file mode 100644 index 000000000..897524046 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml @@ -0,0 +1,50 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-ha-setup-unsecured +spec: + steps: + - try: + - apply: + file: replication.yaml + - assert: + file: ready-replication-sts.yaml + - assert: + file: ready-replication-svc.yaml + - assert: + file: ready-replication-pvc.yaml + - apply: + file: sentinel.yaml + - assert: + file: ready-sentinel-sts.yaml + - assert: + file: ready-sentinel-svc.yaml + - create: + file: cli-pod.yaml + - assert: + file: cli-pod.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Replicated Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Ping Sentinel Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping + check: + ($stdout=='PONG'): true diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml new file mode 100644 index 000000000..e8501253e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis + labels: + app: redis +spec: + containers: + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml new file mode 100644 index 000000000..28ed1dace --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml @@ -0,0 +1,35 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + selector: + matchLabels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + serviceName: redis-sentinel-sentinel-headless + template: + metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel +status: + readyReplicas: 1 + replicas: 1 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml new file mode 100644 index 000000000..4ce66a032 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-sentinel + labels: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + name: redis-sentinel-sentinel-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisSentinel + name: redis-sentinel +spec: + clusterIP: None + ports: + - name: sentinel-client + port: 26379 + protocol: TCP + targetPort: 26379 + selector: + app: redis-sentinel-sentinel + redis_setup_type: sentinel + role: sentinel + type: ClusterIP +status: + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml new file mode 100644 index 000000000..3fb33dcac --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml new file mode 100644 index 000000000..955066544 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 1 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + quorum: "1" + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file From 8e8ded98acd13d3660d155bf0c510096121b669a Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 18 Dec 2023 15:18:18 +0530 Subject: [PATCH 077/203] feat: Redis AUTH password (#734) * make-codegen Signed-off-by: Shubham Gupta * fix codegen Signed-off-by: Shubham Gupta * fix test Signed-off-by: Shubham Gupta * fix naming Signed-off-by: Shubham Gupta * fix test file Signed-off-by: Shubham Gupta * fix secret issues Signed-off-by: Shubham Gupta * fix Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- api/common_types.go | 5 +- api/zz_generated.deepcopy.go | 5 + ...s.redis.opstreelabs.in_redissentinels.yaml | 162 ++++++++++++++++++ k8sutils/redis-sentinel.go | 7 + .../replication-password/chainsaw-test.yaml | 4 +- .../replication-password/configmap.yaml | 8 - .../replication-password/password.yaml | 8 + .../replication-password/ready-secret.yaml | 6 + .../replication-password/sentinel.yaml | 8 +- 9 files changed, 198 insertions(+), 15 deletions(-) delete mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml diff --git a/api/common_types.go b/api/common_types.go index 40cbd9695..a67722406 100644 --- a/api/common_types.go +++ b/api/common_types.go @@ -145,8 +145,9 @@ type RedisPodDisruptionBudget struct { // +k8s:deepcopy-gen=true type RedisSentinelConfig struct { - AdditionalSentinelConfig *string `json:"additionalSentinelConfig,omitempty"` - RedisReplicationName string `json:"redisReplicationName"` + AdditionalSentinelConfig *string `json:"additionalSentinelConfig,omitempty"` + RedisReplicationName string `json:"redisReplicationName"` + RedisReplicationPassword *corev1.EnvVarSource `json:"redisReplicationPassword,omitempty"` // +kubebuilder:default:=myMaster MasterGroupName string `json:"masterGroupName,omitempty"` // +kubebuilder:default:="6379" diff --git a/api/zz_generated.deepcopy.go b/api/zz_generated.deepcopy.go index 499bb939b..975b24a1b 100644 --- a/api/zz_generated.deepcopy.go +++ b/api/zz_generated.deepcopy.go @@ -354,6 +354,11 @@ func (in *RedisSentinelConfig) DeepCopyInto(out *RedisSentinelConfig) { *out = new(string) **out = **in } + if in.RedisReplicationPassword != nil { + in, out := &in.RedisReplicationPassword, &out.RedisReplicationPassword + *out = new(v1.EnvVarSource) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisSentinelConfig. diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index e89f42317..d0ce64fbe 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -1187,6 +1187,87 @@ spec: type: string redisReplicationName: type: string + redisReplicationPassword: + description: EnvVarSource represents a source for the value of + an EnvVar. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only resources + limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, + requests.cpu, requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object required: - redisReplicationName type: object @@ -3396,6 +3477,87 @@ spec: type: string redisReplicationName: type: string + redisReplicationPassword: + description: EnvVarSource represents a source for the value of + an EnvVar. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only resources + limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, + requests.cpu, requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object required: - redisReplicationName type: object diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 014284772..fdb3dcb84 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "k8s.io/utils/pointer" @@ -279,6 +280,12 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, lo }, } + if cr.Spec.RedisSentinelConfig != nil && cr.Spec.RedisSentinelConfig.RedisReplicationPassword != nil { + *envVar = append(*envVar, corev1.EnvVar{ + Name: "MASTER_PASSWORD", + ValueFrom: cr.Spec.RedisSentinelConfig.RedisReplicationPassword, + }) + } return envVar } diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml index b8684bd82..29a5487a2 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml @@ -20,9 +20,7 @@ spec: - assert: file: ready-replication-pvc.yaml - create: - file: configmap.yaml - - assert: - file: configmap.yaml + file: password.yaml - apply: file: sentinel.yaml - assert: diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml deleted file mode 100644 index 529906f34..000000000 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/configmap.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: sentinel-external-config -data: - redis-sentinel-additional.conf: | - sentinel auth-pass myMaster Opstree@1234 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml new file mode 100644 index 000000000..346addd89 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-replication-secret +stringData: + redis-replication-password: "Opstree@1234" +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml new file mode 100644 index 000000000..de09d2654 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-replication-secret +type: Opaque \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml index ffbe11e1a..2cc5040c6 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml @@ -1,4 +1,5 @@ ---- +# yaml-language-server: $schema=../../../../../../../../config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml + apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisSentinel metadata: @@ -11,7 +12,10 @@ spec: redisSentinelConfig: redisReplicationName : redis-replication quorum: "1" - additionalSentinelConfig: sentinel-external-config + redisReplicationPassword: + secretKeyRef: + name: redis-replication-secret + key: redis-replication-password kubernetesConfig: image: quay.io/opstree/redis-sentinel:latest imagePullPolicy: Always From 8f789aa070f4431b7bfca46971cd959a73556b27 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 25 Dec 2023 15:02:49 +0800 Subject: [PATCH 078/203] fix: exporter connect to custom redis port (#736) * fix port check Signed-off-by: drivebyer * test redis_up Signed-off-by: drivebyer * fix exporter env Signed-off-by: drivebyer * fix url Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/statefulset.go | 8 +++++- .../redis-cluster/chainsaw-test.yaml | 25 ++++++++++--------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 750498464..9b0efd894 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -508,12 +508,18 @@ func getExporterEnvironmentVariables(params containerParameters) []corev1.EnvVar Value: "true", }) } - if params.Port != nil { + if params.RedisExporterPort != nil { envVars = append(envVars, corev1.EnvVar{ Name: "REDIS_EXPORTER_WEB_LISTEN_ADDRESS", Value: fmt.Sprintf(":%d", *params.RedisExporterPort), }) } + if params.Port != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_ADDR", + Value: fmt.Sprintf("redis://localhost:%d", *params.Port), + }) + } if params.RedisExporterEnv != nil { envVars = append(envVars, *params.RedisExporterEnv...) } diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml index c17efa8f1..92f2d2793 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml @@ -77,39 +77,40 @@ spec: - script: timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + # + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' check: - ($stdout=='200'): true + ($stdout=='1'): true - script: timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' check: - ($stdout=='200'): true + ($stdout=='1'): true - script: timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' check: - ($stdout=='200'): true + ($stdout=='1'): true - script: timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' check: - ($stdout=='200'): true + ($stdout=='1'): true - script: timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' check: - ($stdout=='200'): true + ($stdout=='1'): true - script: timeout: 30s content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} curl -s -o /dev/null -w '%{http_code}' http://{}:9122 + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' check: - ($stdout=='200'): true + ($stdout=='1'): true - name: Try saving a key from every node try: From c8fd3bd33cfbe820700b5393375f65da38c440f5 Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 28 Dec 2023 03:46:27 +0800 Subject: [PATCH 079/203] feat: support create redis cluster by nodeport service (#738) * copy e2e test from setup Signed-off-by: drivebyer * support nodeport cluster Signed-off-by: drivebyer * setup test check cluster Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix ip Signed-off-by: drivebyer * fix check string Signed-off-by: drivebyer * enable nodeport e2e test Signed-off-by: drivebyer * test: add nodeport service check Signed-off-by: drivebyer * test: test with redis 6 Signed-off-by: drivebyer * test: change version && add REDIS_MAJOR_VERSION env Signed-off-by: drivebyer * test: fix check syntax Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/e2e-chainsaw.yml | 1 + controllers/rediscluster_controller.go | 17 +- k8sutils/redis-cluster.go | 92 ++++- k8sutils/redis-cluster_test.go | 4 +- k8sutils/services.go | 10 +- k8sutils/statefulset.go | 14 +- k8sutils/statefulset_test.go | 6 +- .../hostnetwork/redis-cluster/ready-pod.yaml | 12 + .../nodeport/redis-cluster/chainsaw-test.yaml | 130 ++++++ .../nodeport/redis-cluster/cluster.yaml | 49 +++ .../nodeport/redis-cluster/ready-cluster.yaml | 7 + .../nodeport/redis-cluster/ready-pvc.yaml | 181 +++++++++ .../nodeport/redis-cluster/ready-sts.yaml | 25 ++ .../nodeport/redis-cluster/ready-svc.yaml | 369 ++++++++++++++++++ .../setup/redis-cluster/chainsaw-test.yaml | 34 ++ .../hostnetwork/redis-cluster/ready-pod.yaml | 12 + 16 files changed, 944 insertions(+), 19 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index 0bf22ebe2..595ceddb0 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -20,6 +20,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ - ./tests/e2e-chainsaw/v1beta2/password/ - ./tests/e2e-chainsaw/v1beta2/ha-setup/ + - ./tests/e2e-chainsaw/v1beta2/nodeport/ steps: - name: Checkout code diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 0a501170d..d49230b51 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -116,16 +116,16 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } } - err = k8sutils.CreateRedisLeader(instance) - if err != nil { - return ctrl.Result{}, err - } if leaderReplicas != 0 { err = k8sutils.CreateRedisLeaderService(instance) if err != nil { return ctrl.Result{}, err } } + err = k8sutils.CreateRedisLeader(instance) + if err != nil { + return ctrl.Result{}, err + } err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget) if err != nil { @@ -149,11 +149,6 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } } - - err = k8sutils.CreateRedisFollower(instance) - if err != nil { - return ctrl.Result{}, err - } // if we have followers create their service. if followerReplicas != 0 { err = k8sutils.CreateRedisFollowerService(instance) @@ -161,6 +156,10 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } } + err = k8sutils.CreateRedisFollower(instance) + if err != nil { + return ctrl.Result{}, err + } err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.PodDisruptionBudget) if err != nil { return ctrl.Result{}, err diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 0962d90ef..92bd9f64c 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -1,6 +1,11 @@ package k8sutils import ( + "strconv" + "strings" + + "k8s.io/apimachinery/pkg/util/intstr" + commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" @@ -31,6 +36,7 @@ func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, e res := statefulSetParameters{ Replicas: &replicas, ClusterMode: true, + ClusterVersion: cr.Spec.ClusterVersion, NodeConfVolume: cr.Spec.Storage.NodeConfVolume, NodeSelector: params.NodeSelector, PodSecurityContext: cr.Spec.PodSecurityContext, @@ -94,7 +100,7 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init } // generateRedisClusterContainerParams generates Redis container information -func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { +func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, role string) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ @@ -108,6 +114,50 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars } + if cr.Spec.KubernetesConfig.Service != nil && cr.Spec.KubernetesConfig.Service.ServiceType == "NodePort" { + envVars := util.Coalesce(containerProp.EnvVars, &[]corev1.EnvVar{}) + *envVars = append(*envVars, corev1.EnvVar{ + Name: "NODEPORT", + Value: "true", + }) + *envVars = append(*envVars, corev1.EnvVar{ + Name: "HOST_IP", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "status.hostIP", + }, + }, + }) + + type ports struct { + announcePort int + announceBusPort int + } + nps := map[string]ports{} // pod name to ports + replicas := cr.Spec.GetReplicaCounts(role) + for i := 0; i < int(replicas); i++ { + svc, err := getService(cr.Namespace, cr.ObjectMeta.Name+"-"+role+"-"+strconv.Itoa(i)) + if err != nil { + log.Error(err, "Cannot get service for Redis", "Setup.Type", role) + } else { + nps[svc.Name] = ports{ + announcePort: int(svc.Spec.Ports[0].NodePort), + announceBusPort: int(svc.Spec.Ports[1].NodePort), + } + } + } + for name, np := range nps { + *envVars = append(*envVars, corev1.EnvVar{ + Name: "announce_port_" + strings.ReplaceAll(name, "-", "_"), + Value: strconv.Itoa(np.announcePort), + }) + *envVars = append(*envVars, corev1.EnvVar{ + Name: "announce_bus_port_" + strings.ReplaceAll(name, "-", "_"), + Value: strconv.Itoa(np.announceBusPort), + }) + } + containerProp.EnvVars = envVars + } if cr.Spec.Storage != nil { containerProp.AdditionalVolume = cr.Spec.Storage.VolumeMount.Volume containerProp.AdditionalMountPath = cr.Spec.Storage.VolumeMount.MountPath @@ -223,7 +273,7 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu generateRedisClusterParams(cr, service.getReplicaCount(cr), service.ExternalConfig, service), redisClusterAsOwner(cr), generateRedisClusterInitContainerParams(cr), - generateRedisClusterContainerParams(cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe), + generateRedisClusterContainerParams(cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType), cr.Spec.Sidecars, ) if err != nil { @@ -268,6 +318,15 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re additionalServiceType := "ClusterIP" if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType + if additionalServiceType == "NodePort" { + // If NodePort is enabled, we need to create a service for every redis pod. + // Then use --cluster-announce-ip --cluster-announce-port --cluster-announce-bus-port to make cluster. + err = service.createOrUpdateClusterNodePortService(cr) + if err != nil { + logger.Error(err, "Cannot create nodeport service for Redis", "Setup.Type", service.RedisServiceRole) + return err + } + } } err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, additionalServiceType, *cr.Spec.Port) if err != nil { @@ -276,3 +335,32 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re } return nil } + +func (service RedisClusterService) createOrUpdateClusterNodePortService(cr *redisv1beta2.RedisCluster) error { + replicas := cr.Spec.GetReplicaCounts(service.RedisServiceRole) + + for i := 0; i < int(replicas); i++ { + serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole + "-" + strconv.Itoa(i) + logger := serviceLogger(cr.Namespace, serviceName) + labels := getRedisLabels(cr.ObjectMeta.Name+"-"+service.RedisServiceRole, cluster, service.RedisServiceRole, map[string]string{ + "statefulset.kubernetes.io/pod-name": serviceName, + }) + annotations := generateServiceAnots(cr.ObjectMeta, nil, disableMetrics) + objectMetaInfo := generateObjectMetaInformation(serviceName, cr.Namespace, labels, annotations) + busPort := corev1.ServicePort{ + Name: "redis-bus", + Port: int32(*cr.Spec.Port + 10000), + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.IntOrString{ + Type: intstr.Int, + IntVal: int32(*cr.Spec.Port + 10000), + }, + } + err := CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, "NodePort", *cr.Spec.Port, busPort) + if err != nil { + logger.Error(err, "Cannot create nodeport service for Redis", "Setup.Type", service.RedisServiceRole) + return err + } + } + return nil +} diff --git a/k8sutils/redis-cluster_test.go b/k8sutils/redis-cluster_test.go index 2e1d1ddb3..e2692951d 100644 --- a/k8sutils/redis-cluster_test.go +++ b/k8sutils/redis-cluster_test.go @@ -427,10 +427,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { t.Fatalf("Failed to unmarshal file %s: %v", path, err) } - actualLeaderContainer := generateRedisClusterContainerParams(input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe) + actualLeaderContainer := generateRedisClusterContainerParams(input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader") assert.EqualValues(t, expectedLeaderContainer, actualLeaderContainer, "Expected %+v, got %+v", expectedLeaderContainer, actualLeaderContainer) - actualFollowerContainer := generateRedisClusterContainerParams(input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe) + actualFollowerContainer := generateRedisClusterContainerParams(input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower") assert.EqualValues(t, expectedFollowerContainer, actualFollowerContainer, "Expected %+v, got %+v", expectedFollowerContainer, actualFollowerContainer) } diff --git a/k8sutils/services.go b/k8sutils/services.go index 30a50027b..c00e2c0a5 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -30,7 +30,7 @@ var disableMetrics exporterPortProvider = func() (int, bool) { } // generateServiceDef generates service definition for Redis -func generateServiceDef(serviceMeta metav1.ObjectMeta, epp exporterPortProvider, ownerDef metav1.OwnerReference, headless bool, serviceType string, port int) *corev1.Service { +func generateServiceDef(serviceMeta metav1.ObjectMeta, epp exporterPortProvider, ownerDef metav1.OwnerReference, headless bool, serviceType string, port int, extra ...corev1.ServicePort) *corev1.Service { var PortName string if serviceMeta.Labels["role"] == "sentinel" { PortName = "sentinel-client" @@ -61,6 +61,10 @@ func generateServiceDef(serviceMeta metav1.ObjectMeta, epp exporterPortProvider, redisExporterService := enableMetricsPort(exporterPort) service.Spec.Ports = append(service.Spec.Ports, *redisExporterService) } + if len(extra) > 0 { + service.Spec.Ports = append(service.Spec.Ports, extra...) + } + AddOwnerRefToObject(service, ownerDef) return service } @@ -150,9 +154,9 @@ func serviceLogger(namespace string, name string) logr.Logger { } // CreateOrUpdateService method will create or update Redis service -func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, epp exporterPortProvider, headless bool, serviceType string, port int) error { +func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, epp exporterPortProvider, headless bool, serviceType string, port int, extra ...corev1.ServicePort) error { logger := serviceLogger(namespace, serviceMeta.Name) - serviceDef := generateServiceDef(serviceMeta, epp, ownerDef, headless, serviceType, port) + serviceDef := generateServiceDef(serviceMeta, epp, ownerDef, headless, serviceType, port, extra...) storedService, err := getService(namespace, serviceMeta.Name) if err != nil { if errors.IsNotFound(err) { diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 9b0efd894..9ac058311 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -32,6 +32,7 @@ const ( type statefulSetParameters struct { Replicas *int32 ClusterMode bool + ClusterVersion *string NodeConfVolume bool NodeSelector map[string]string PodSecurityContext *corev1.PodSecurityContext @@ -240,6 +241,7 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame params.NodeConfVolume, params.EnableMetrics, params.ExternalConfig, + params.ClusterVersion, containerParams.AdditionalMountPath, sidecars, ), @@ -344,7 +346,7 @@ func createPVCTemplate(volumeName string, stsMeta metav1.ObjectMeta, storageSpec } // generateContainerDef generates container definition for Redis -func generateContainerDef(name string, containerParams containerParameters, clusterMode, nodeConfVolume, enableMetrics bool, externalConfig *string, mountpath []corev1.VolumeMount, sidecars []redisv1beta2.Sidecar) []corev1.Container { +func generateContainerDef(name string, containerParams containerParameters, clusterMode, nodeConfVolume, enableMetrics bool, externalConfig, clusterVersion *string, mountpath []corev1.VolumeMount, sidecars []redisv1beta2.Sidecar) []corev1.Container { containerDefinition := []corev1.Container{ { Name: name, @@ -361,6 +363,7 @@ func generateContainerDef(name string, containerParams containerParameters, clus containerParams.ACLConfig, containerParams.EnvVars, containerParams.Port, + clusterVersion, ), ReadinessProbe: getProbeInfo(containerParams.ReadinessProbe), LivenessProbe: getProbeInfo(containerParams.LivenessProbe), @@ -594,12 +597,19 @@ func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { // getEnvironmentVariables returns all the required Environment Variables func getEnvironmentVariables(role string, enabledPassword *bool, secretName *string, secretKey *string, persistenceEnabled *bool, tlsConfig *redisv1beta2.TLSConfig, - aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar, port *int) []corev1.EnvVar { + aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar, port *int, clusterVersion *string) []corev1.EnvVar { envVars := []corev1.EnvVar{ {Name: "SERVER_MODE", Value: role}, {Name: "SETUP_MODE", Value: role}, } + if clusterVersion != nil { + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_MAJOR_VERSION", + Value: *clusterVersion, + }) + } + var redisHost string if role == "sentinel" { redisHost = "redis://localhost:" + strconv.Itoa(sentinelPort) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 925c3f1a3..879c3242e 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -230,6 +230,7 @@ func TestGetEnvironmentVariables(t *testing.T) { aclConfig *redisv1beta2.ACLConfig envVar *[]corev1.EnvVar port *int + clusterVersion *string expectedEnvironment []corev1.EnvVar }{ { @@ -257,6 +258,7 @@ func TestGetEnvironmentVariables(t *testing.T) { envVar: &[]corev1.EnvVar{ {Name: "TEST_ENV", Value: "test-value"}, }, + clusterVersion: pointer.String("v6"), expectedEnvironment: []corev1.EnvVar{ {Name: "ACL_MODE", Value: "true"}, {Name: "PERSISTENCE_ENABLED", Value: "true"}, @@ -276,6 +278,7 @@ func TestGetEnvironmentVariables(t *testing.T) { {Name: "SERVER_MODE", Value: "sentinel"}, {Name: "SETUP_MODE", Value: "sentinel"}, {Name: "TEST_ENV", Value: "test-value"}, + {Name: "REDIS_MAJOR_VERSION", Value: "v6"}, }, }, { @@ -289,6 +292,7 @@ func TestGetEnvironmentVariables(t *testing.T) { aclConfig: nil, envVar: nil, port: nil, + clusterVersion: nil, expectedEnvironment: []corev1.EnvVar{ {Name: "REDIS_ADDR", Value: "redis://localhost:6379"}, {Name: "SERVER_MODE", Value: "redis"}, @@ -363,7 +367,7 @@ func TestGetEnvironmentVariables(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { actualEnvironment := getEnvironmentVariables(tt.role, tt.enabledPassword, tt.secretName, - tt.secretKey, tt.persistenceEnabled, tt.tlsConfig, tt.aclConfig, tt.envVar, tt.port) + tt.secretKey, tt.persistenceEnabled, tt.tlsConfig, tt.aclConfig, tt.envVar, tt.port, tt.clusterVersion) assert.ElementsMatch(t, tt.expectedEnvironment, actualEnvironment) }) diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml index e789ed06f..b26382e6d 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml @@ -13,6 +13,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -39,6 +41,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -65,6 +69,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -91,6 +97,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -117,6 +125,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -143,6 +153,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..2ed8bbb82 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,130 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-nodeport +spec: + steps: + - name: Setup redis cluster use nodeport + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Cluster + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Check Cluster + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + + - name: Try saving a key With Password + try: + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='OK'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml new file mode 100644 index 000000000..805d02a3c --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml @@ -0,0 +1,49 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v6 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + service: + serviceType: NodePort + image: quay.io/opstree/redis:v6.2.14 + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..c56a06bd7 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml @@ -0,0 +1,369 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-leader-0 + name: redis-cluster-v1beta2-leader-0 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-bus + port: 16379 + protocol: TCP + targetPort: 16379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-leader-0 + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-leader-1 + name: redis-cluster-v1beta2-leader-1 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-bus + port: 16379 + protocol: TCP + targetPort: 16379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-leader-1 + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-leader-2 + name: redis-cluster-v1beta2-leader-2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-bus + port: 16379 + protocol: TCP + targetPort: 16379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-leader-2 + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-follower-0 + name: redis-cluster-v1beta2-follower-0 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-bus + port: 16379 + protocol: TCP + targetPort: 16379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-follower-0 + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-follower-1 + name: redis-cluster-v1beta2-follower-1 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-bus + port: 16379 + protocol: TCP + targetPort: 16379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-follower-1 + type: NodePort +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-follower-2 + name: redis-cluster-v1beta2-follower-2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-bus + port: 16379 + protocol: TCP + targetPort: 16379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + statefulset.kubernetes.io/pod-name: redis-cluster-v1beta2-follower-2 + type: NodePort +status: + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index 9639fac86..f9f8b5130 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -56,6 +56,40 @@ spec: check: ($stdout=='PONG'): true + - name: Check Cluster + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + + - name: Try saving a key With Password try: - script: diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml index e789ed06f..b26382e6d 100644 --- a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml +++ b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml @@ -13,6 +13,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -39,6 +41,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -65,6 +69,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -91,6 +97,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -117,6 +125,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE @@ -143,6 +153,8 @@ spec: value: "true" - name: REDIS_ADDR value: "redis://localhost:6379" + - name: REDIS_MAJOR_VERSION + value: "v6" - name: REDIS_PORT value: "6380" - name: SERVER_MODE From f07f596a6183b08b437b8d42053a77ce9e5a93cb Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 10 Jan 2024 17:12:48 +0800 Subject: [PATCH 080/203] fix: exporter no auth to redis (#743) * fix exporter no auth Signed-off-by: drivebyer * add e2e Signed-off-by: drivebyer * fix unit test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/redis-replication.go | 1 + k8sutils/redis-replication_test.go | 1 + k8sutils/redis-standalone.go | 1 + k8sutils/redis-standalone_test.go | 1 + k8sutils/statefulset.go | 17 +++ .../password/redis-cluster/chainsaw-test.yaml | 65 +++++++++--- .../password/redis-cluster/secret.yaml | 2 +- .../redis-replication/chainsaw-test.yaml | 12 +-- .../password/redis-replication/secret.yaml | 2 +- .../redis-standalone/chainsaw-test.yaml | 53 ++++++++++ .../password/redis-standalone/ready-pvc.yaml | 14 +++ .../password/redis-standalone/ready-sts.yaml | 11 ++ .../password/redis-standalone/ready-svc.yaml | 100 ++++++++++++++++++ .../password/redis-standalone/secret.yaml | 8 ++ .../password/redis-standalone/standalone.yaml | 40 +++++++ 15 files changed, 307 insertions(+), 21 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-standalone/secret.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index b1452d174..a0f0c7fd9 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -117,6 +117,7 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, + Port: pointer.Int(6379), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars diff --git a/k8sutils/redis-replication_test.go b/k8sutils/redis-replication_test.go index 8b4a2e7f9..509f863e7 100644 --- a/k8sutils/redis-replication_test.go +++ b/k8sutils/redis-replication_test.go @@ -94,6 +94,7 @@ func Test_generateRedisReplicationContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") expected := containerParameters{ Image: "quay.io/opstree/redis:v7.0.12", + Port: pointer.Int(6379), ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), Resources: &corev1.ResourceRequirements{ Requests: corev1.ResourceList{ diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index dd116b2ba..4addf77be 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -122,6 +122,7 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, + Port: pointer.Int(6379), } if cr.Spec.EnvVars != nil { diff --git a/k8sutils/redis-standalone_test.go b/k8sutils/redis-standalone_test.go index 394f03845..81d13e537 100644 --- a/k8sutils/redis-standalone_test.go +++ b/k8sutils/redis-standalone_test.go @@ -102,6 +102,7 @@ func Test_generateRedisStandaloneContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") expected := containerParameters{ Image: "quay.io/opstree/redis:v7.0.12", + Port: pointer.Int(6379), ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), Resources: &corev1.ResourceRequirements{ Requests: corev1.ResourceList{ diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 9ac058311..8011f20a6 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -523,9 +523,26 @@ func getExporterEnvironmentVariables(params containerParameters) []corev1.EnvVar Value: fmt.Sprintf("redis://localhost:%d", *params.Port), }) } + if params.EnabledPassword != nil && *params.EnabledPassword { + envVars = append(envVars, corev1.EnvVar{ + Name: "REDIS_PASSWORD", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: *params.SecretName, + }, + Key: *params.SecretKey, + }, + }, + }) + } if params.RedisExporterEnv != nil { envVars = append(envVars, *params.RedisExporterEnv...) } + + sort.SliceStable(envVars, func(i, j int) bool { + return envVars[i].Name < envVars[j].Name + }) return envVars } diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml index be3e2642e..1d76bce27 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml @@ -32,37 +32,37 @@ spec: - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true @@ -71,37 +71,37 @@ spec: - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-0 bar-0 + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree1234 set foo-0 bar-0 check: ($stdout=='OK'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-1 bar-1 + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree1234 set foo-1 bar-1 check: ($stdout=='OK'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-2 bar-2 + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree1234 set foo-2 bar-2 check: ($stdout=='OK'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-3 bar-3 + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree1234 set foo-3 bar-3 check: ($stdout=='OK'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-4 bar-4 + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree1234 set foo-4 bar-4 check: ($stdout=='OK'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree@1234 set foo-5 bar-5 + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree1234 set foo-5 bar-5 check: ($stdout=='OK'): true @@ -181,4 +181,43 @@ spec: content: | kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 check: - ($stdout=='NOAUTH Authentication required.'): true \ No newline at end of file + ($stdout=='NOAUTH Authentication required.'): true + + - name: Test Redis Exporter + try: + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml index cf1cf0a6a..345a60fde 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/secret.yaml @@ -4,5 +4,5 @@ kind: Secret metadata: name: redis-secret data: - password: T3BzdHJlZUAxMjM0Cg== + password: T3BzdHJlZTEyMzQ= type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml index 57ff2e326..f15f063ad 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml @@ -30,19 +30,19 @@ spec: - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree@1234 ping + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree1234 ping check: ($stdout=='PONG'): true @@ -51,19 +51,19 @@ spec: - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree@1234 set foo-0 bar-0 + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree1234 set foo-0 bar-0 check: ($stdout=='OK'): true # - script: # timeout: 10s # content: | - # kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree@1234 set foo-1 bar-1 + # kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree1234 set foo-1 bar-1 # check: # ($stdout=='READONLY You can't write against a read only replica.'): true # - script: # timeout: 10s # content: | - # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree@1234 set foo-2 bar-2 + # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree1234 set foo-2 bar-2 # check: # ($stdout=='READONLY You can't write against a read only replica.'): true diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml index cf1cf0a6a..345a60fde 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/secret.yaml @@ -4,5 +4,5 @@ kind: Secret metadata: name: redis-secret data: - password: T3BzdHJlZUAxMjM0Cg== + password: T3BzdHJlZTEyMzQ= type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml new file mode 100644 index 000000000..f6c0c723e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml @@ -0,0 +1,53 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-replication-password +spec: + steps: + - try: + - apply: + file: standalone.yaml + - apply: + file: secret.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: secret.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Try saving a key With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- redis-cli -p 6379 -a Opstree1234 set foo-0 bar-0 + check: + ($stdout=='OK'): true + + - name: Try saving a key Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- redis-cli -p 6379 set foo-0 bar-0 + check: + ($stdout=='NOAUTH Authentication required.'): true + + - name: Test Redis Exporter + try: + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml new file mode 100644 index 000000000..777fa3656 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-standalone-v1beta2-redis-standalone-v1beta2-0 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml new file mode 100644 index 000000000..5402de920 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml @@ -0,0 +1,11 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + replicas: 1 + readyReplicas: 1 diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml new file mode 100644 index 000000000..275aae8cd --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml @@ -0,0 +1,100 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2 + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/secret.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/secret.yaml new file mode 100644 index 000000000..345a60fde --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: redis-secret +data: + password: T3BzdHJlZTEyMzQ= +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml new file mode 100644 index 000000000..ad7eed929 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml @@ -0,0 +1,40 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone-v1beta2 +spec: + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisSecret: + name: redis-secret + key: password + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi From ef99c4d600c72aacd2366341cb511dcf77c9520e Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 10 Jan 2024 17:13:42 +0800 Subject: [PATCH 081/203] feat: add environment to customize data pvc prefix (#742) * support customize pvc template name Signed-off-by: drivebyer * add test case Signed-off-by: drivebyer * kubectl Signed-off-by: drivebyer * wait operator ready Signed-off-by: drivebyer * fix sleep Signed-off-by: drivebyer * fix sleep Signed-off-by: drivebyer * remove debug Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/e2e-chainsaw.yml | 1 + k8sutils/const.go | 4 + k8sutils/finalizer.go | 10 +- k8sutils/statefulset.go | 8 +- tests/_config/chainsaw-configuration.yaml | 4 +- .../pvc-name/redis-cluster/chainsaw-test.yaml | 50 +++++ .../pvc-name/redis-cluster/cluster.yaml | 47 ++++ .../pvc-name/redis-cluster/ready-cluster.yaml | 7 + .../pvc-name/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../pvc-name/redis-cluster/ready-sts.yaml | 25 +++ .../pvc-name/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ 11 files changed, 530 insertions(+), 8 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index 595ceddb0..e3708c5f9 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -21,6 +21,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/password/ - ./tests/e2e-chainsaw/v1beta2/ha-setup/ - ./tests/e2e-chainsaw/v1beta2/nodeport/ + - ./tests/e2e-chainsaw/v1beta2/pvc-name/ steps: - name: Checkout code diff --git a/k8sutils/const.go b/k8sutils/const.go index 3a3da6603..b0377c3be 100644 --- a/k8sutils/const.go +++ b/k8sutils/const.go @@ -3,3 +3,7 @@ package k8sutils const ( AnnotationKeyRecreateStatefulset = "redis.opstreelabs.in/recreate-statefulset" ) + +const ( + EnvOperatorSTSPVCTemplateName = "OPERATOR_STS_PVC_TEMPLATE_NAME" +) diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index 58fdc680d..b85ef3c51 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -3,6 +3,7 @@ package k8sutils import ( "context" "fmt" + "k8s.io/utils/env" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" @@ -133,7 +134,8 @@ func AddRedisSentinelFinalizer(cr *redisv1beta2.RedisSentinel, cl client.Client) // finalizeRedisPVC delete PVC func finalizeRedisPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error { - PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) + pvcTemplateName := env.GetString(EnvOperatorSTSPVCTemplateName, cr.Name) + PVCName := fmt.Sprintf("%s-%s-0", pvcTemplateName, cr.Name) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim", "PVCName", PVCName) @@ -146,7 +148,8 @@ func finalizeRedisPVC(client kubernetes.Interface, logger logr.Logger, cr *redis func finalizeRedisClusterPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { for _, role := range []string{"leader", "follower"} { for i := 0; i < int(cr.Spec.GetReplicaCounts(role)); i++ { - PVCName := fmt.Sprintf("%s-%s-%s-%s-%d", cr.Name, role, cr.Name, role, i) + pvcTemplateName := env.GetString(EnvOperatorSTSPVCTemplateName, cr.Name+"-"+role) + PVCName := fmt.Sprintf("%s-%s-%s-%d", pvcTemplateName, cr.Name, role, i) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) @@ -171,7 +174,8 @@ func finalizeRedisClusterPVC(client kubernetes.Interface, logger logr.Logger, cr // finalizeRedisReplicationPVC delete PVCs func finalizeRedisReplicationPVC(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication) error { for i := 0; i < int(cr.Spec.GetReplicationCounts("replication")); i++ { - PVCName := fmt.Sprintf("%s-%s-%d", cr.Name, cr.Name, i) + pvcTemplateName := env.GetString(EnvOperatorSTSPVCTemplateName, cr.Name) + PVCName := fmt.Sprintf("%s-%s-%d", pvcTemplateName, cr.Name, i) err := client.CoreV1().PersistentVolumeClaims(cr.Namespace).Delete(context.TODO(), PVCName, metav1.DeleteOptions{}) if err != nil && !errors.IsNotFound(err) { logger.Error(err, "Could not delete Persistent Volume Claim "+PVCName) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 8011f20a6..f1caa2891 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -3,6 +3,7 @@ package k8sutils import ( "context" "fmt" + "k8s.io/utils/env" "path" "sort" "strconv" @@ -269,7 +270,8 @@ func generateStatefulSetsDef(stsMeta metav1.ObjectMeta, params statefulSetParame statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, createPVCTemplate("node-conf", stsMeta, params.NodeConfPersistentVolumeClaim)) } if containerParams.PersistenceEnabled != nil && *containerParams.PersistenceEnabled { - statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, createPVCTemplate(stsMeta.GetName(), stsMeta, params.PersistentVolumeClaim)) + pvcTplName := env.GetString(EnvOperatorSTSPVCTemplateName, stsMeta.GetName()) + statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, createPVCTemplate(pvcTplName, stsMeta, params.PersistentVolumeClaim)) } if params.ExternalConfig != nil { statefulset.Spec.Template.Spec.Volumes = getExternalConfig(*params.ExternalConfig) @@ -328,7 +330,7 @@ func createPVCTemplate(volumeName string, stsMeta metav1.ObjectMeta, storageSpec pvcTemplate.CreationTimestamp = metav1.Time{} pvcTemplate.Name = volumeName pvcTemplate.Labels = stsMeta.GetLabels() - // We want the same annoations as the StatefulSet here + // We want the same annotation as the StatefulSet here pvcTemplate.Annotations = generateStatefulSetsAnots(stsMeta, nil) if storageSpec.Spec.AccessModes == nil { pvcTemplate.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce} @@ -559,7 +561,7 @@ func getVolumeMount(name string, persistenceEnabled *bool, clusterMode bool, nod if persistenceEnabled != nil && *persistenceEnabled { VolumeMounts = append(VolumeMounts, corev1.VolumeMount{ - Name: name, + Name: env.GetString(EnvOperatorSTSPVCTemplateName, name), MountPath: "/data", }) } diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml index 828895dbb..3e2daf4bb 100644 --- a/tests/_config/chainsaw-configuration.yaml +++ b/tests/_config/chainsaw-configuration.yaml @@ -9,5 +9,5 @@ spec: timeouts: apply: 5m delete: 5m - assert: 15m - error: 15m + assert: 10m + error: 10m diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..a022f9537 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,50 @@ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: pvc-name +spec: + steps: + - name: Add PVC name environment + try: + - script: + content: | + kubectl patch deployment redis-operator-redis-operator --namespace redis-operator-system --type json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/env/-", "value": {"name": "OPERATOR_STS_PVC_TEMPLATE_NAME", "value": "data"}}]' + - sleep: + duration: 1m + + - name: redis-cluster-install + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: redis-cluster-uninstall + try: + - delete: + ref: + name: redis-cluster-v1beta2 + kind: RedisCluster + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-cluster.yaml + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - error: + file: ready-pvc.yaml + + - name: Remove PVC name environment + try: + - script: + content: | + kubectl patch deployment redis-operator-redis-operator --namespace redis-operator-system --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/env/1"}]' + kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml new file mode 100644 index 000000000..ecf147104 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml @@ -0,0 +1,47 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..2511fa8d5 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: data-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file From e57531acce2285ae1720faafcd74c5709fa1fd50 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Thu, 11 Jan 2024 09:34:53 +0100 Subject: [PATCH 082/203] docs: add namespace creation (#746) * Remove trailing whitespaces Signed-off-by: Mathieu Cesbron * Add namespace creation on doc Signed-off-by: Mathieu Cesbron --------- Signed-off-by: Mathieu Cesbron --- CONTRIBUTING.md | 11 ++++++----- README.md | 3 ++- docs/content/en/docs/Contribute/_index.md | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index efb2f47d7..6cb1cf5ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ ## Local Kubernetes Cluster -For development and testing of operator on local system, we need to set up a [Minikube](https://minikube.sigs.k8s.io/docs/start/) or local Kubernetes cluster. +For development and testing of operator on local system, we need to set up a [Minikube](https://minikube.sigs.k8s.io/docs/start/) or local Kubernetes cluster. Minikube is a single node Kubernetes cluster that generally gets used for the development and testing on Kubernetes. For creating a Minkube cluster we need to simply run: @@ -28,7 +28,7 @@ $ minikube start --vm-driver virtualbox ⌛ Waiting for image downloads to complete ... ✨ Preparing Kubernetes environment ... 🚜 Pulling images required by Kubernetes v1.14.1 ... -🚀 Launching Kubernetes v1.14.1 using kubeadm ... +🚀 Launching Kubernetes v1.14.1 using kubeadm ... ⌛ Waiting for pods: apiserver proxy etcd scheduler controller dns 🔑 Configuring cluster permissions ... 🤔 Verifying component health ..... @@ -146,7 +146,8 @@ The operator deployment can be done via `helm` cli, we just need to define the c ```shell $ helm upgrade redis-operator ot-helm/redis-operator \ - --install --namespace ot-operators --set redisOperator.imageName= \ + --install --create-namespace --namespace ot-operators \ + --set redisOperator.imageName= \ --set redisOperator.imageTag= ``` @@ -155,8 +156,8 @@ $ helm upgrade redis-operator ot-helm/redis-operator \ $ helm upgrade redis ot-helm/redis --namespace ot-operators # For deploying cluster redis -$ helm upgrade redis-cluster ot-helm/redis-cluster \n - --set redisCluster.clusterSize=3 --install --namespace ot-operators \ +$ helm upgrade redis-cluster ot-helm/redis-cluster \n + --set redisCluster.clusterSize=3 --install --namespace ot-operators \ --set pdb.enabled=false --set redisCluster.tag=v7.0.5-beta ``` diff --git a/README.md b/README.md index 18a916b7a..a5e4b7fa0 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,8 @@ $ helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/ ```shell # Deploy the redis-operator -$ helm upgrade redis-operator ot-helm/redis-operator --install --namespace ot-operators +$ helm upgrade redis-operator ot-helm/redis-operator \ + --install --create-namespace --namespace ot-operators ``` After deployment, verify the installation of operator diff --git a/docs/content/en/docs/Contribute/_index.md b/docs/content/en/docs/Contribute/_index.md index a0639bd17..d4104bc7d 100644 --- a/docs/content/en/docs/Contribute/_index.md +++ b/docs/content/en/docs/Contribute/_index.md @@ -153,7 +153,8 @@ The operator deployment can be done via `helm` cli, we just need to define the c ```shell $ helm upgrade redis-operator ot-helm/redis-operator \ - --install --namespace ot-operators --set redisOperator.imageName= \ + --install --create-namespace --namespace ot-operators \ + --set redisOperator.imageName= \ --set redisOperator.imageTag= ``` From 7665d4aff32aa41ded080b804ed3ec408b822992 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Sun, 14 Jan 2024 08:23:43 +0100 Subject: [PATCH 083/203] feat: generate k8s client only once (#750) Signed-off-by: Mathieu Cesbron --- controllers/redis_controller.go | 4 +- controllers/rediscluster_controller.go | 16 +++--- controllers/redisreplication_controller.go | 6 +- controllers/redissentinel_controller.go | 6 +- k8sutils/poddisruption.go | 65 ++++++++-------------- k8sutils/redis-cluster.go | 40 ++++++------- k8sutils/redis-cluster_test.go | 6 +- k8sutils/redis-replication.go | 12 ++-- k8sutils/redis-sentinel.go | 19 ++++--- k8sutils/redis-standalone.go | 12 ++-- k8sutils/redis.go | 6 +- k8sutils/services.go | 40 +++++-------- k8sutils/statefulset.go | 55 ++++++------------ tests/readme.md | 2 +- 14 files changed, 123 insertions(+), 166 deletions(-) diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index ee7224ade..a73eb287f 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -65,11 +65,11 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl return ctrl.Result{}, err } - err = k8sutils.CreateStandaloneRedis(instance) + err = k8sutils.CreateStandaloneRedis(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } - err = k8sutils.CreateStandaloneService(instance) + err = k8sutils.CreateStandaloneService(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index d49230b51..a3a65c04e 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -117,22 +117,22 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } if leaderReplicas != 0 { - err = k8sutils.CreateRedisLeaderService(instance) + err = k8sutils.CreateRedisLeaderService(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } } - err = k8sutils.CreateRedisLeader(instance) + err = k8sutils.CreateRedisLeader(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } - err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget) + err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget, r.K8sClient) if err != nil { return ctrl.Result{}, err } - redisLeaderInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-leader") + redisLeaderInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-leader", r.K8sClient) if err != nil { if errors.IsNotFound(err) { return ctrl.Result{RequeueAfter: time.Second * 60}, nil @@ -151,21 +151,21 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // if we have followers create their service. if followerReplicas != 0 { - err = k8sutils.CreateRedisFollowerService(instance) + err = k8sutils.CreateRedisFollowerService(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } } - err = k8sutils.CreateRedisFollower(instance) + err = k8sutils.CreateRedisFollower(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } - err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.PodDisruptionBudget) + err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.PodDisruptionBudget, r.K8sClient) if err != nil { return ctrl.Result{}, err } } - redisFollowerInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-follower") + redisFollowerInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-follower", r.K8sClient) if err != nil { if errors.IsNotFound(err) { return ctrl.Result{RequeueAfter: time.Second * 60}, nil diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index c424c85d5..a23cb8b3e 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -56,18 +56,18 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, err } - err = k8sutils.CreateReplicationRedis(instance) + err = k8sutils.CreateReplicationRedis(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } - err = k8sutils.CreateReplicationService(instance) + err = k8sutils.CreateReplicationService(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } // Set Pod distruptiuon Budget Later - redisReplicationInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name) + redisReplicationInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name, r.K8sClient) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 3a88dcc74..03e686544 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -55,18 +55,18 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Create Redis Sentinel - err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance) + err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } - err = k8sutils.ReconcileSentinelPodDisruptionBudget(instance, instance.Spec.PodDisruptionBudget) + err = k8sutils.ReconcileSentinelPodDisruptionBudget(instance, instance.Spec.PodDisruptionBudget, r.K8sClient) if err != nil { return ctrl.Result{}, err } // Create the Service for Redis Sentinel - err = k8sutils.CreateRedisSentinelService(instance) + err = k8sutils.CreateRedisSentinelService(instance, r.K8sClient) if err != nil { return ctrl.Result{}, err } diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 2886f7ccb..77412673f 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -12,10 +12,11 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" ) // CreateRedisLeaderPodDisruptionBudget check and create a PodDisruptionBudget for Leaders -func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role string, pdbParams *commonapi.RedisPodDisruptionBudget) error { +func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role string, pdbParams *commonapi.RedisPodDisruptionBudget, cl kubernetes.Interface) error { pdbName := cr.ObjectMeta.Name + "-" + role logger := pdbLogger(cr.Namespace, pdbName) if pdbParams != nil && pdbParams.Enabled { @@ -23,12 +24,12 @@ func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role strin annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) pdbDef := generatePodDisruptionBudgetDef(cr, role, pdbMeta, cr.Spec.RedisLeader.PodDisruptionBudget) - return CreateOrUpdatePodDisruptionBudget(pdbDef) + return CreateOrUpdatePodDisruptionBudget(pdbDef, cl) } else { // Check if one exists, and delete it. - _, err := GetPodDisruptionBudget(cr.Namespace, pdbName) + _, err := GetPodDisruptionBudget(cr.Namespace, pdbName, cl) if err == nil { - return deletePodDisruptionBudget(cr.Namespace, pdbName) + return deletePodDisruptionBudget(cr.Namespace, pdbName, cl) } else if err != nil && errors.IsNotFound(err) { logger.V(1).Info("Reconciliation Successful, no PodDisruptionBudget Found.") // Its ok if its not found, as we're deleting anyway @@ -38,7 +39,7 @@ func ReconcileRedisPodDisruptionBudget(cr *redisv1beta2.RedisCluster, role strin } } -func ReconcileSentinelPodDisruptionBudget(cr *redisv1beta2.RedisSentinel, pdbParams *commonapi.RedisPodDisruptionBudget) error { +func ReconcileSentinelPodDisruptionBudget(cr *redisv1beta2.RedisSentinel, pdbParams *commonapi.RedisPodDisruptionBudget, cl kubernetes.Interface) error { pdbName := cr.ObjectMeta.Name + "-sentinel" logger := pdbLogger(cr.Namespace, pdbName) if pdbParams != nil && pdbParams.Enabled { @@ -46,12 +47,12 @@ func ReconcileSentinelPodDisruptionBudget(cr *redisv1beta2.RedisSentinel, pdbPar annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) pdbMeta := generateObjectMetaInformation(pdbName, cr.Namespace, labels, annotations) pdbDef := generateSentinelPodDisruptionBudgetDef(cr, "sentinel", pdbMeta, pdbParams) - return CreateOrUpdatePodDisruptionBudget(pdbDef) + return CreateOrUpdatePodDisruptionBudget(pdbDef, cl) } else { // Check if one exists, and delete it. - _, err := GetPodDisruptionBudget(cr.Namespace, pdbName) + _, err := GetPodDisruptionBudget(cr.Namespace, pdbName, cl) if err == nil { - return deletePodDisruptionBudget(cr.Namespace, pdbName) + return deletePodDisruptionBudget(cr.Namespace, pdbName, cl) } else if err != nil && errors.IsNotFound(err) { logger.V(1).Info("Reconciliation Successful, no PodDisruptionBudget Found.") // Its ok if its not found, as we're deleting anyway @@ -116,24 +117,24 @@ func generateSentinelPodDisruptionBudgetDef(cr *redisv1beta2.RedisSentinel, role } // CreateOrUpdateService method will create or update Redis service -func CreateOrUpdatePodDisruptionBudget(pdbDef *policyv1.PodDisruptionBudget) error { +func CreateOrUpdatePodDisruptionBudget(pdbDef *policyv1.PodDisruptionBudget, cl kubernetes.Interface) error { logger := pdbLogger(pdbDef.Namespace, pdbDef.Name) - storedPDB, err := GetPodDisruptionBudget(pdbDef.Namespace, pdbDef.Name) + storedPDB, err := GetPodDisruptionBudget(pdbDef.Namespace, pdbDef.Name, cl) if err != nil { if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(pdbDef); err != nil { //nolint logger.Error(err, "Unable to patch redis PodDisruptionBudget with comparison object") return err } if errors.IsNotFound(err) { - return createPodDisruptionBudget(pdbDef.Namespace, pdbDef) + return createPodDisruptionBudget(pdbDef.Namespace, pdbDef, cl) } return err } - return patchPodDisruptionBudget(storedPDB, pdbDef, pdbDef.Namespace) + return patchPodDisruptionBudget(storedPDB, pdbDef, pdbDef.Namespace, cl) } // patchPodDisruptionBudget will patch Redis Kubernetes PodDisruptionBudgets -func patchPodDisruptionBudget(storedPdb *policyv1.PodDisruptionBudget, newPdb *policyv1.PodDisruptionBudget, namespace string) error { +func patchPodDisruptionBudget(storedPdb *policyv1.PodDisruptionBudget, newPdb *policyv1.PodDisruptionBudget, namespace string, cl kubernetes.Interface) error { logger := pdbLogger(namespace, storedPdb.Name) // We want to try and keep this atomic as possible. newPdb.ResourceVersion = storedPdb.ResourceVersion @@ -169,20 +170,15 @@ func patchPodDisruptionBudget(storedPdb *policyv1.PodDisruptionBudget, newPdb *p logger.Error(err, "Unable to patch redis PodDisruptionBudget with comparison object") return err } - return updatePodDisruptionBudget(namespace, newPdb) + return updatePodDisruptionBudget(namespace, newPdb, cl) } return nil } // createPodDisruptionBudget is a method to create PodDisruptionBudgets in Kubernetes -func createPodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudget) error { +func createPodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudget, cl kubernetes.Interface) error { logger := pdbLogger(namespace, pdb.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - _, err = client.PolicyV1().PodDisruptionBudgets(namespace).Create(context.TODO(), pdb, metav1.CreateOptions{}) + _, err := cl.PolicyV1().PodDisruptionBudgets(namespace).Create(context.TODO(), pdb, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis PodDisruptionBudget creation failed") return err @@ -192,14 +188,9 @@ func createPodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudg } // updatePodDisruptionBudget is a method to update PodDisruptionBudgets in Kubernetes -func updatePodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudget) error { +func updatePodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudget, cl kubernetes.Interface) error { logger := pdbLogger(namespace, pdb.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - _, err = client.PolicyV1().PodDisruptionBudgets(namespace).Update(context.TODO(), pdb, metav1.UpdateOptions{}) + _, err := cl.PolicyV1().PodDisruptionBudgets(namespace).Update(context.TODO(), pdb, metav1.UpdateOptions{}) if err != nil { logger.Error(err, "Redis PodDisruptionBudget update failed") return err @@ -209,14 +200,9 @@ func updatePodDisruptionBudget(namespace string, pdb *policyv1.PodDisruptionBudg } // deletePodDisruptionBudget is a method to delete PodDisruptionBudgets in Kubernetes -func deletePodDisruptionBudget(namespace string, pdbName string) error { +func deletePodDisruptionBudget(namespace string, pdbName string, cl kubernetes.Interface) error { logger := pdbLogger(namespace, pdbName) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - err = client.PolicyV1().PodDisruptionBudgets(namespace).Delete(context.TODO(), pdbName, metav1.DeleteOptions{}) + err := cl.PolicyV1().PodDisruptionBudgets(namespace).Delete(context.TODO(), pdbName, metav1.DeleteOptions{}) if err != nil { logger.Error(err, "Redis PodDisruption deletion failed") return err @@ -226,17 +212,12 @@ func deletePodDisruptionBudget(namespace string, pdbName string) error { } // GetPodDisruptionBudget is a method to get PodDisruptionBudgets in Kubernetes -func GetPodDisruptionBudget(namespace string, pdb string) (*policyv1.PodDisruptionBudget, error) { +func GetPodDisruptionBudget(namespace string, pdb string, cl kubernetes.Interface) (*policyv1.PodDisruptionBudget, error) { logger := pdbLogger(namespace, pdb) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return nil, err - } getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("PodDisruptionBudget", "policy/v1"), } - pdbInfo, err := client.PolicyV1().PodDisruptionBudgets(namespace).Get(context.TODO(), pdb, getOpts) + pdbInfo, err := cl.PolicyV1().PodDisruptionBudgets(namespace).Get(context.TODO(), pdb, getOpts) if err != nil { logger.V(1).Info("Redis PodDisruptionBudget get action failed") return nil, err diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 92bd9f64c..cfa2748d2 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -5,6 +5,7 @@ import ( "strings" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" @@ -100,7 +101,7 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init } // generateRedisClusterContainerParams generates Redis container information -func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, role string) containerParameters { +func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, role string, cl kubernetes.Interface) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ @@ -136,7 +137,7 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security nps := map[string]ports{} // pod name to ports replicas := cr.Spec.GetReplicaCounts(role) for i := 0; i < int(replicas); i++ { - svc, err := getService(cr.Namespace, cr.ObjectMeta.Name+"-"+role+"-"+strconv.Itoa(i)) + svc, err := getService(cr.Namespace, cr.ObjectMeta.Name+"-"+role+"-"+strconv.Itoa(i), cl) if err != nil { log.Error(err, "Cannot get service for Redis", "Setup.Type", role) } else { @@ -205,7 +206,7 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security } // CreateRedisLeader will create a leader redis setup -func CreateRedisLeader(cr *redisv1beta2.RedisCluster) error { +func CreateRedisLeader(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { prop := RedisClusterSTS{ RedisStateFulType: "leader", SecurityContext: cr.Spec.RedisLeader.SecurityContext, @@ -219,11 +220,11 @@ func CreateRedisLeader(cr *redisv1beta2.RedisCluster) error { if cr.Spec.RedisLeader.RedisConfig != nil { prop.ExternalConfig = cr.Spec.RedisLeader.RedisConfig.AdditionalRedisConfig } - return prop.CreateRedisClusterSetup(cr) + return prop.CreateRedisClusterSetup(cr, cl) } // CreateRedisFollower will create a follower redis setup -func CreateRedisFollower(cr *redisv1beta2.RedisCluster) error { +func CreateRedisFollower(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { prop := RedisClusterSTS{ RedisStateFulType: "follower", SecurityContext: cr.Spec.RedisFollower.SecurityContext, @@ -237,23 +238,23 @@ func CreateRedisFollower(cr *redisv1beta2.RedisCluster) error { if cr.Spec.RedisFollower.RedisConfig != nil { prop.ExternalConfig = cr.Spec.RedisFollower.RedisConfig.AdditionalRedisConfig } - return prop.CreateRedisClusterSetup(cr) + return prop.CreateRedisClusterSetup(cr, cl) } // CreateRedisLeaderService method will create service for Redis Leader -func CreateRedisLeaderService(cr *redisv1beta2.RedisCluster) error { +func CreateRedisLeaderService(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { prop := RedisClusterService{ RedisServiceRole: "leader", } - return prop.CreateRedisClusterService(cr) + return prop.CreateRedisClusterService(cr, cl) } // CreateRedisFollowerService method will create service for Redis Follower -func CreateRedisFollowerService(cr *redisv1beta2.RedisCluster) error { +func CreateRedisFollowerService(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { prop := RedisClusterService{ RedisServiceRole: "follower", } - return prop.CreateRedisClusterService(cr) + return prop.CreateRedisClusterService(cr, cl) } func (service RedisClusterSTS) getReplicaCount(cr *redisv1beta2.RedisCluster) int32 { @@ -261,7 +262,7 @@ func (service RedisClusterSTS) getReplicaCount(cr *redisv1beta2.RedisCluster) in } // CreateRedisClusterSetup will create Redis Setup for leader and follower -func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisCluster) error { +func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType logger := statefulSetLogger(cr.Namespace, stateFulName) labels := getRedisLabels(stateFulName, cluster, service.RedisStateFulType, cr.ObjectMeta.Labels) @@ -273,8 +274,9 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu generateRedisClusterParams(cr, service.getReplicaCount(cr), service.ExternalConfig, service), redisClusterAsOwner(cr), generateRedisClusterInitContainerParams(cr), - generateRedisClusterContainerParams(cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType), + generateRedisClusterContainerParams(cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType, cl), cr.Spec.Sidecars, + cl, ) if err != nil { logger.Error(err, "Cannot create statefulset for Redis", "Setup.Type", service.RedisStateFulType) @@ -284,7 +286,7 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu } // CreateRedisClusterService method will create service for Redis -func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.RedisCluster) error { +func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) labels := getRedisLabels(serviceName, cluster, service.RedisServiceRole, cr.ObjectMeta.Labels) @@ -305,12 +307,12 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re objectMetaInfo := generateObjectMetaInformation(serviceName, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, true, "ClusterIP", *cr.Spec.Port) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, true, "ClusterIP", *cr.Spec.Port, cl) if err != nil { logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole) return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), epp, false, "ClusterIP", *cr.Spec.Port) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), epp, false, "ClusterIP", *cr.Spec.Port, cl) if err != nil { logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -321,14 +323,14 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re if additionalServiceType == "NodePort" { // If NodePort is enabled, we need to create a service for every redis pod. // Then use --cluster-announce-ip --cluster-announce-port --cluster-announce-bus-port to make cluster. - err = service.createOrUpdateClusterNodePortService(cr) + err = service.createOrUpdateClusterNodePortService(cr, cl) if err != nil { logger.Error(err, "Cannot create nodeport service for Redis", "Setup.Type", service.RedisServiceRole) return err } } } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, additionalServiceType, *cr.Spec.Port) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, additionalServiceType, *cr.Spec.Port, cl) if err != nil { logger.Error(err, "Cannot create additional service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -336,7 +338,7 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re return nil } -func (service RedisClusterService) createOrUpdateClusterNodePortService(cr *redisv1beta2.RedisCluster) error { +func (service RedisClusterService) createOrUpdateClusterNodePortService(cr *redisv1beta2.RedisCluster, cl kubernetes.Interface) error { replicas := cr.Spec.GetReplicaCounts(service.RedisServiceRole) for i := 0; i < int(replicas); i++ { @@ -356,7 +358,7 @@ func (service RedisClusterService) createOrUpdateClusterNodePortService(cr *redi IntVal: int32(*cr.Spec.Port + 10000), }, } - err := CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, "NodePort", *cr.Spec.Port, busPort) + err := CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisClusterAsOwner(cr), disableMetrics, false, "NodePort", *cr.Spec.Port, cl, busPort) if err != nil { logger.Error(err, "Cannot create nodeport service for Redis", "Setup.Type", service.RedisServiceRole) return err diff --git a/k8sutils/redis-cluster_test.go b/k8sutils/redis-cluster_test.go index e2692951d..bdaac7a61 100644 --- a/k8sutils/redis-cluster_test.go +++ b/k8sutils/redis-cluster_test.go @@ -5,6 +5,8 @@ import ( "path/filepath" "testing" + "k8s.io/client-go/kubernetes/fake" + common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/stretchr/testify/assert" @@ -427,10 +429,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { t.Fatalf("Failed to unmarshal file %s: %v", path, err) } - actualLeaderContainer := generateRedisClusterContainerParams(input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader") + actualLeaderContainer := generateRedisClusterContainerParams(input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader", fake.NewSimpleClientset()) assert.EqualValues(t, expectedLeaderContainer, actualLeaderContainer, "Expected %+v, got %+v", expectedLeaderContainer, actualLeaderContainer) - actualFollowerContainer := generateRedisClusterContainerParams(input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower") + actualFollowerContainer := generateRedisClusterContainerParams(input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower", fake.NewSimpleClientset()) assert.EqualValues(t, expectedFollowerContainer, actualFollowerContainer, "Expected %+v, got %+v", expectedFollowerContainer, actualFollowerContainer) } diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index a0f0c7fd9..81803b10a 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -3,11 +3,12 @@ package k8sutils import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" ) // CreateReplicationService method will create replication service for Redis -func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { +func CreateReplicationService(cr *redisv1beta2.RedisReplication, cl kubernetes.Interface) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) var epp exporterPortProvider @@ -27,12 +28,12 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisReplicationAsOwner(cr), disableMetrics, true, "ClusterIP", redisPort) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisReplicationAsOwner(cr), disableMetrics, true, "ClusterIP", redisPort, cl) if err != nil { logger.Error(err, "Cannot create replication headless service for Redis") return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisReplicationAsOwner(cr), epp, false, "ClusterIP", redisPort) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisReplicationAsOwner(cr), epp, false, "ClusterIP", redisPort, cl) if err != nil { logger.Error(err, "Cannot create replication service for Redis") return err @@ -41,7 +42,7 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisReplicationAsOwner(cr), disableMetrics, false, additionalServiceType, redisPort) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisReplicationAsOwner(cr), disableMetrics, false, additionalServiceType, redisPort, cl) if err != nil { logger.Error(err, "Cannot create additional service for Redis Replication") return err @@ -50,7 +51,7 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication) error { } // CreateReplicationRedis will create a replication redis setup -func CreateReplicationRedis(cr *redisv1beta2.RedisReplication) error { +func CreateReplicationRedis(cr *redisv1beta2.RedisReplication, cl kubernetes.Interface) error { stateFulName := cr.ObjectMeta.Name logger := statefulSetLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) @@ -63,6 +64,7 @@ func CreateReplicationRedis(cr *redisv1beta2.RedisReplication) error { generateRedisReplicationInitContainerParams(cr), generateRedisReplicationContainerParams(cr), cr.Spec.Sidecars, + cl, ) if err != nil { logger.Error(err, "Cannot create replication statefulset for Redis") diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index fdb3dcb84..5ae9dbef1 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -37,7 +37,7 @@ type RedisReplicationObject struct { } // Redis Sentinel Create the Redis Sentinel Setup -func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) error { +func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { prop := RedisSentinelSTS{ RedisStateFulType: "sentinel", Affinity: cr.Spec.Affinity, @@ -50,21 +50,21 @@ func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logge prop.ExternalConfig = cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig } - return prop.CreateRedisSentinelSetup(ctx, client, logger, cr) + return prop.CreateRedisSentinelSetup(ctx, client, logger, cr, cl) } // Create RedisSentinel Service -func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { +func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { prop := RedisSentinelService{ RedisServiceRole: "sentinel", } - return prop.CreateRedisSentinelService(cr) + return prop.CreateRedisSentinelService(cr, cl) } // Create Redis Sentinel Cluster Setup -func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) error { +func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType labels := getRedisLabels(stateFulName, sentinel, service.RedisStateFulType, cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) @@ -77,6 +77,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cl generateRedisSentinelInitContainerParams(cr), generateRedisSentinelContainerParams(ctx, client, logger, cr, service.ReadinessProbe, service.LivenessProbe), cr.Spec.Sidecars, + cl, ) if err != nil { @@ -197,7 +198,7 @@ func (service RedisSentinelSTS) getSentinelCount(cr *redisv1beta2.RedisSentinel) } // Create the Service for redis sentinel -func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel) error { +func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole logger := serviceLogger(cr.Namespace, serviceName) labels := getRedisLabels(serviceName, sentinel, service.RedisServiceRole, cr.ObjectMeta.Labels) @@ -220,12 +221,12 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(serviceName+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisSentinelAsOwner(cr), disableMetrics, true, "ClusterIP", sentinelPort) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisSentinelAsOwner(cr), disableMetrics, true, "ClusterIP", sentinelPort, cl) if err != nil { logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole) return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisSentinelAsOwner(cr), epp, false, "ClusterIP", sentinelPort) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisSentinelAsOwner(cr), epp, false, "ClusterIP", sentinelPort, cl) if err != nil { logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole) return err @@ -235,7 +236,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisSentinelAsOwner(cr), disableMetrics, false, additionalServiceType, sentinelPort) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisSentinelAsOwner(cr), disableMetrics, false, additionalServiceType, sentinelPort, cl) if err != nil { logger.Error(err, "Cannot create additional service for Redis", "Setup.Type", service.RedisServiceRole) return err diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 4addf77be..c47e6a934 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -3,6 +3,7 @@ package k8sutils import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" ) @@ -11,7 +12,7 @@ import ( //) // CreateStandaloneService method will create standalone service for Redis -func CreateStandaloneService(cr *redisv1beta2.Redis) error { +func CreateStandaloneService(cr *redisv1beta2.Redis, cl kubernetes.Interface) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) var epp exporterPortProvider @@ -31,12 +32,12 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, annotations) additionalObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-additional", cr.Namespace, labels, generateServiceAnots(cr.ObjectMeta, additionalServiceAnnotations, epp)) - err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisAsOwner(cr), disableMetrics, true, "ClusterIP", redisPort) + err := CreateOrUpdateService(cr.Namespace, headlessObjectMetaInfo, redisAsOwner(cr), disableMetrics, true, "ClusterIP", redisPort, cl) if err != nil { logger.Error(err, "Cannot create standalone headless service for Redis") return err } - err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisAsOwner(cr), epp, false, "ClusterIP", redisPort) + err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, redisAsOwner(cr), epp, false, "ClusterIP", redisPort, cl) if err != nil { logger.Error(err, "Cannot create standalone service for Redis") return err @@ -45,7 +46,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { if cr.Spec.KubernetesConfig.Service != nil { additionalServiceType = cr.Spec.KubernetesConfig.Service.ServiceType } - err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisAsOwner(cr), disableMetrics, false, additionalServiceType, redisPort) + err = CreateOrUpdateService(cr.Namespace, additionalObjectMetaInfo, redisAsOwner(cr), disableMetrics, false, additionalServiceType, redisPort, cl) if err != nil { logger.Error(err, "Cannot create additional service for Redis") return err @@ -54,7 +55,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis) error { } // CreateStandaloneRedis will create a standalone redis setup -func CreateStandaloneRedis(cr *redisv1beta2.Redis) error { +func CreateStandaloneRedis(cr *redisv1beta2.Redis, cl kubernetes.Interface) error { logger := statefulSetLogger(cr.Namespace, cr.ObjectMeta.Name) labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) @@ -66,6 +67,7 @@ func CreateStandaloneRedis(cr *redisv1beta2.Redis) error { generateRedisStandaloneInitContainerParams(cr), generateRedisStandaloneContainerParams(cr), cr.Spec.Sidecars, + cl, ) if err != nil { logger.Error(err, "Cannot create standalone statefulset for Redis") diff --git a/k8sutils/redis.go b/k8sutils/redis.go index fa1986bd6..221917c13 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -476,8 +476,8 @@ func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Lo } // Get Redis nodes by it's role i.e. master, slave and sentinel -func GetRedisNodesByRole(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, redisRole string) []string { - statefulset, err := GetStatefulSet(cr.Namespace, cr.Name) +func GetRedisNodesByRole(ctx context.Context, cl kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, redisRole string) []string { + statefulset, err := GetStatefulSet(cr.Namespace, cr.Name, cl) if err != nil { logger.Error(err, "Failed to Get the Statefulset of the", "custom resource", cr.Name, "in namespace", cr.Namespace) } @@ -488,7 +488,7 @@ func GetRedisNodesByRole(ctx context.Context, client kubernetes.Interface, logge for i := 0; i < int(replicas); i++ { podName := statefulset.Name + "-" + strconv.Itoa(i) - podRole := checkRedisServerRole(ctx, client, logger, cr, podName) + podRole := checkRedisServerRole(ctx, cl, logger, cr, podName) if podRole == redisRole { pods = append(pods, podName) } diff --git a/k8sutils/services.go b/k8sutils/services.go index c00e2c0a5..353e68f58 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -9,6 +9,7 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" ) const ( @@ -95,14 +96,9 @@ func generateServiceType(k8sServiceType string) corev1.ServiceType { } // createService is a method to create service is Kubernetes -func createService(namespace string, service *corev1.Service) error { +func createService(namespace string, service *corev1.Service, cl kubernetes.Interface) error { logger := serviceLogger(namespace, service.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - _, err = client.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) + _, err := cl.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis service creation is failed") return err @@ -112,14 +108,9 @@ func createService(namespace string, service *corev1.Service) error { } // updateService is a method to update service is Kubernetes -func updateService(namespace string, service *corev1.Service) error { +func updateService(namespace string, service *corev1.Service, cl kubernetes.Interface) error { logger := serviceLogger(namespace, service.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - _, err = client.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) + _, err := cl.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) if err != nil { logger.Error(err, "Redis service update failed") return err @@ -129,17 +120,12 @@ func updateService(namespace string, service *corev1.Service) error { } // getService is a method to get service is Kubernetes -func getService(namespace string, service string) (*corev1.Service, error) { +func getService(namespace string, service string, cl kubernetes.Interface) (*corev1.Service, error) { logger := serviceLogger(namespace, service) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return nil, err - } getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("Service", "v1"), } - serviceInfo, err := client.CoreV1().Services(namespace).Get(context.TODO(), service, getOpts) + serviceInfo, err := cl.CoreV1().Services(namespace).Get(context.TODO(), service, getOpts) if err != nil { logger.V(1).Info("Redis service get action is failed") return nil, err @@ -154,24 +140,24 @@ func serviceLogger(namespace string, name string) logr.Logger { } // CreateOrUpdateService method will create or update Redis service -func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, epp exporterPortProvider, headless bool, serviceType string, port int, extra ...corev1.ServicePort) error { +func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, epp exporterPortProvider, headless bool, serviceType string, port int, cl kubernetes.Interface, extra ...corev1.ServicePort) error { logger := serviceLogger(namespace, serviceMeta.Name) serviceDef := generateServiceDef(serviceMeta, epp, ownerDef, headless, serviceType, port, extra...) - storedService, err := getService(namespace, serviceMeta.Name) + storedService, err := getService(namespace, serviceMeta.Name, cl) if err != nil { if errors.IsNotFound(err) { if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil { //nolint logger.Error(err, "Unable to patch redis service with compare annotations") } - return createService(namespace, serviceDef) + return createService(namespace, serviceDef, cl) } return err } - return patchService(storedService, serviceDef, namespace) + return patchService(storedService, serviceDef, namespace, cl) } // patchService will patch Redis Kubernetes service -func patchService(storedService *corev1.Service, newService *corev1.Service, namespace string) error { +func patchService(storedService *corev1.Service, newService *corev1.Service, namespace string, cl kubernetes.Interface) error { logger := serviceLogger(namespace, storedService.Name) // We want to try and keep this atomic as possible. newService.ResourceVersion = storedService.ResourceVersion @@ -204,7 +190,7 @@ func patchService(storedService *corev1.Service, newService *corev1.Service, nam return err } logger.V(1).Info("Syncing Redis service with defined properties") - return updateService(namespace, newService) + return updateService(namespace, newService, cl) } logger.V(1).Info("Redis service is already in-sync") return nil diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index f1caa2891..67f394a6e 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -3,13 +3,14 @@ package k8sutils import ( "context" "fmt" - "k8s.io/utils/env" "path" "sort" "strconv" "strings" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "k8s.io/client-go/kubernetes" + "k8s.io/utils/env" "k8s.io/utils/pointer" commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" @@ -95,9 +96,9 @@ type initContainerParameters struct { } // CreateOrUpdateStateFul method will create or update Redis service -func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params statefulSetParameters, ownerDef metav1.OwnerReference, initcontainerParams initContainerParameters, containerParams containerParameters, sidecars *[]redisv1beta2.Sidecar) error { +func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params statefulSetParameters, ownerDef metav1.OwnerReference, initcontainerParams initContainerParameters, containerParams containerParameters, sidecars *[]redisv1beta2.Sidecar, cl kubernetes.Interface) error { logger := statefulSetLogger(namespace, stsMeta.Name) - storedStateful, err := GetStatefulSet(namespace, stsMeta.Name) + storedStateful, err := GetStatefulSet(namespace, stsMeta.Name, cl) statefulSetDef := generateStatefulSetsDef(stsMeta, params, ownerDef, initcontainerParams, containerParams, getSidecars(sidecars)) if err != nil { if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil { //nolint @@ -105,21 +106,16 @@ func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params return err } if apierrors.IsNotFound(err) { - return createStatefulSet(namespace, statefulSetDef) + return createStatefulSet(namespace, statefulSetDef, cl) } return err } - return patchStatefulSet(storedStateful, statefulSetDef, namespace, params.RecreateStatefulSet) + return patchStatefulSet(storedStateful, statefulSetDef, namespace, params.RecreateStatefulSet, cl) } // patchStateFulSet will patch Redis Kubernetes StateFulSet -func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.StatefulSet, namespace string, recreateStateFulSet bool) error { +func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.StatefulSet, namespace string, recreateStateFulSet bool, cl kubernetes.Interface) error { logger := statefulSetLogger(namespace, storedStateful.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } // We want to try and keep this atomic as possible. newStateful.ResourceVersion = storedStateful.ResourceVersion newStateful.CreationTimestamp = storedStateful.CreationTimestamp @@ -167,7 +163,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St }, ), } - pvcs, err := client.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).List(context.Background(), listOpt) + pvcs, err := cl.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).List(context.Background(), listOpt) if err != nil { return err } @@ -178,7 +174,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St if realCapacity != stateCapacity { realUpdate = true pvc.Spec.Resources.Requests = newStateful.Spec.VolumeClaimTemplates[0].Spec.Resources.Requests - _, err = client.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).Update(context.Background(), &pvc, metav1.UpdateOptions{}) + _, err = cl.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).Update(context.Background(), &pvc, metav1.UpdateOptions{}) if err != nil { if !updateFailed { updateFailed = true @@ -213,7 +209,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St logger.Error(err, "Unable to patch redis statefulset with comparison object") return err } - return updateStatefulSet(namespace, newStateful, recreateStateFulSet) + return updateStatefulSet(namespace, newStateful, recreateStateFulSet, cl) } logger.V(1).Info("Reconciliation Complete, no Changes required.") return nil @@ -690,14 +686,9 @@ func getEnvironmentVariables(role string, enabledPassword *bool, secretName *str } // createStatefulSet is a method to create statefulset in Kubernetes -func createStatefulSet(namespace string, stateful *appsv1.StatefulSet) error { - logger := statefulSetLogger(namespace, stateful.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - _, err = client.AppsV1().StatefulSets(namespace).Create(context.TODO(), stateful, metav1.CreateOptions{}) +func createStatefulSet(namespace string, stateful *appsv1.StatefulSet, cl kubernetes.Interface) error { + logger := statefulSetLogger(stateful.Namespace, stateful.Name) + _, err := cl.AppsV1().StatefulSets(namespace).Create(context.TODO(), stateful, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis stateful creation failed") return err @@ -707,14 +698,9 @@ func createStatefulSet(namespace string, stateful *appsv1.StatefulSet) error { } // updateStatefulSet is a method to update statefulset in Kubernetes -func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool) error { +func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool, cl kubernetes.Interface) error { logger := statefulSetLogger(namespace, stateful.Name) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return err - } - _, err = client.AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{}) + _, err := cl.AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{}) if recreateStateFulSet { sErr, ok := err.(*apierrors.StatusError) if ok && sErr.ErrStatus.Code == 422 && sErr.ErrStatus.Reason == metav1.StatusReasonInvalid { @@ -724,7 +710,7 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS } logger.V(1).Info("recreating StatefulSet because the update operation wasn't possible", "reason", strings.Join(failMsg, ", ")) propagationPolicy := metav1.DeletePropagationForeground - if err := client.AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { //nolint + if err := cl.AppsV1().StatefulSets(namespace).Delete(context.TODO(), stateful.GetName(), metav1.DeleteOptions{PropagationPolicy: &propagationPolicy}); err != nil { //nolint return errors.Wrap(err, "failed to delete StatefulSet to avoid forbidden action") } } @@ -738,17 +724,12 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS } // GetStateFulSet is a method to get statefulset in Kubernetes -func GetStatefulSet(namespace string, stateful string) (*appsv1.StatefulSet, error) { +func GetStatefulSet(namespace string, stateful string, cl kubernetes.Interface) (*appsv1.StatefulSet, error) { logger := statefulSetLogger(namespace, stateful) - client, err := GenerateK8sClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Could not generate kubernetes client") - return nil, err - } getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("StatefulSet", "apps/v1"), } - statefulInfo, err := client.AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, getOpts) + statefulInfo, err := cl.AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, getOpts) if err != nil { logger.V(1).Info("Redis statefulset get action failed") return nil, err diff --git a/tests/readme.md b/tests/readme.md index f4057b698..c4c91cd86 100644 --- a/tests/readme.md +++ b/tests/readme.md @@ -35,7 +35,7 @@ Please refer to the repository's README for detailed instructions on installing Execute the kuttl test using the following command: -To run all default tests ( _config/kuttl-test.yaml is the default config file ) +To run all default tests ( \_config/kuttl-test.yaml is the default config file ) ```bash kubectl kuttl test --config tests/_config/kuttl-test.yaml From cd1e810c4f29f89e557d949f81c100b14c78c2c6 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Mon, 15 Jan 2024 06:35:37 +0100 Subject: [PATCH 084/203] test: add envtest for redis standalone (#748) Signed-off-by: Mathieu Cesbron --- .github/workflows/operator-ci.yaml | 39 +++---- Makefile | 6 +- controllers/redis_controller_test.go | 147 +++++++++++++++++++++++++++ controllers/suite_test.go | 76 +++++++++----- go.mod | 7 +- go.sum | 25 ++--- hack/integrationSetup.sh | 40 ++++++++ 7 files changed, 274 insertions(+), 66 deletions(-) create mode 100644 controllers/redis_controller_test.go create mode 100755 hack/integrationSetup.sh diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index f32f67757..8d055d1bd 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -13,7 +13,7 @@ env: DockerImagName: docker.io/opstree/redis-operator BuildDocs: true AppVersion: "v0.15.2" - DOCKERFILE_PATH: '**/Dockerfile' + DOCKERFILE_PATH: "**/Dockerfile" jobs: gofmt: @@ -54,6 +54,8 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ env.GOLANG_VERSION }} + - name: Install integration test dependencies + run: make integration-test-setup - name: Run Go Tests with coverage run: go test ./... -coverprofile=coverage.txt -covermode=atomic - name: Upload coverage to Codecov @@ -62,7 +64,7 @@ jobs: file: ./coverage.txt fail_ci_if_error: false verbose: true - + code_quality_golang_ci_lint: needs: [gofmt, govet] runs-on: ubuntu-latest @@ -72,16 +74,16 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ env.GOLANG_VERSION }} - + - name: Download Go modules run: go mod download - + - name: Check disk space run: df -h - + - name: List Go module cache run: ls -la $(go env GOPATH)/pkg/mod - + - name: Run GolangCI-Lint uses: golangci/golangci-lint-action@v3 with: @@ -105,7 +107,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - arch: ['amd64', 'arm64'] + arch: ["amd64", "arm64"] steps: - name: Checkout Code uses: actions/checkout@v2 @@ -125,19 +127,19 @@ jobs: needs: [container_quality_dockerfile_lint] runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 - - name: Build multi-arch image - uses: docker/build-push-action@v2 - with: - context: . - platforms: linux/arm64,linux/amd64 - push: false - tags: ${{ env.DockerImagName }}:latest + - name: Build multi-arch image + uses: docker/build-push-action@v2 + with: + context: . + platforms: linux/arm64,linux/amd64 + push: false + tags: ${{ env.DockerImagName }}:latest gosec_scan: needs: [build_go_binary] @@ -152,4 +154,3 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOSEC_OUTPUT: "junit-xml:/github/workspace/gosec-results.xml" - diff --git a/Makefile b/Makefile index 66849fd86..49695e5cc 100644 --- a/Makefile +++ b/Makefile @@ -148,4 +148,8 @@ e2e-kind-setup: .PHONY: e2e-test e2e-test: e2e-kind-setup install-kuttl - $(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml \ No newline at end of file + $(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml + +.PHONY: integration-test-setup +integration-test-setup: + ./hack/integrationSetup.sh \ No newline at end of file diff --git a/controllers/redis_controller_test.go b/controllers/redis_controller_test.go new file mode 100644 index 000000000..3b9ff9870 --- /dev/null +++ b/controllers/redis_controller_test.go @@ -0,0 +1,147 @@ +package controllers + +import ( + "context" + "fmt" + "time" + + appsv1 "k8s.io/api/apps/v1" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +const ( + ns = "default" + + timeout = time.Second * 5 + interval = time.Millisecond * 250 +) + +var _ = Describe("Redis standalone test", func() { + var ( + redisCR redisv1beta2.Redis + redisCRName string + // Used to create unique name for each test + testCount int + ) + + JustBeforeEach(func() { + redisCR = redisv1beta2.Redis{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redisv1beta2/apiVersion", + Kind: "Redis", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: redisCRName, + Namespace: ns, + }, + } + Expect(k8sClient.Create(context.TODO(), &redisCR)).Should(Succeed()) + testCount++ + }) + + BeforeEach(func() { + redisCRName = fmt.Sprintf("redis-%d", testCount) + }) + + Context("When creating a redis standalone CR", func() { + It("should create a statefulset", func() { + var sts *appsv1.StatefulSet + Eventually(func() error { + sts = &appsv1.StatefulSet{} + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisCRName, + Namespace: ns, + }, sts) + }, timeout, interval).Should(BeNil()) + + Expect(sts.Labels).To(Equal(map[string]string{ + "app": redisCRName, + "redis_setup_type": "standalone", + "role": "standalone", + })) + + Expect(*sts.Spec.Replicas).To(BeEquivalentTo(1)) + Expect(sts.Spec.ServiceName).To(Equal(redisCRName + "-headless")) + }) + + It("should create a service", func() { + var svc *corev1.Service + Eventually(func() error { + svc = &corev1.Service{} + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisCR.Name, + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisCRName, + "redis_setup_type": "standalone", + "role": "standalone", + })) + }) + + It("should create a headless service", func() { + var svc *corev1.Service + Eventually(func() error { + svc = &corev1.Service{} + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisCR.Name + "-headless", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisCRName, + "redis_setup_type": "standalone", + "role": "standalone", + })) + }) + + It("should create additional service", func() { + var svc *corev1.Service + Eventually(func() error { + svc = &corev1.Service{} + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisCR.Name + "-additional", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisCRName, + "redis_setup_type": "standalone", + "role": "standalone", + })) + }) + + Context("then deleting the redis standalone CR", func() { + It("should delete the statefulset", func() { + redisCR := &redisv1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: redisCRName, + Namespace: ns, + }, + } + Expect(k8sClient.Delete(context.TODO(), redisCR)).To(BeNil()) + + Eventually(func() bool { + sts := &appsv1.StatefulSet{} + err := k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisCRName, + Namespace: ns, + }, sts) + return errors.IsNotFound(err) + }, timeout, interval).Should(BeTrue()) + }) + }) + }) +}) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 88aea5083..3bc2b13c7 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -18,13 +18,19 @@ package controllers import ( "path/filepath" + "testing" + "time" + // redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - . "github.com/onsi/ginkgo" + + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/onsi/gomega/gexec" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" - // "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -32,49 +38,67 @@ import ( // +kubebuilder:scaffold:imports ) -// These tests use Ginkgo (BDD-style Go testing framework). Refer to -// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -// var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment -// func TestAPIs(t *testing.T) { -// RegisterFailHandler(Fail) +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) -// RunSpecsWithDefaultAndCustomReporters(t, -// "Controller Suite", -// []Reporter{printer.NewlineReporter{}}) -// } + RunSpecs(t, "Controller suite") +} var _ = BeforeSuite(func() { logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: true, + CRDInstallOptions: envtest.CRDInstallOptions{ + MaxTime: 60 * time.Second, + }, } cfg, err := testEnv.Start() - Expect(err).NotTo(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) + Expect(err).ToNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) - err = redisv1beta2.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) + // err = redisv1beta1.AddToScheme(scheme.Scheme) + // Expect(err).ToNot(HaveOccurred()) err = redisv1beta2.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) + Expect(err).ToNot(HaveOccurred()) // +kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) - Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) - -}, 60) + Expect(err).ToNot(HaveOccurred()) + Expect(k8sClient).ToNot(BeNil()) + + k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme.Scheme, + }) + Expect(err).ToNot(HaveOccurred()) + + k8sClient, err := kubernetes.NewForConfig(cfg) + Expect(err).ToNot(HaveOccurred()) + + err = (&RedisReconciler{ + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + + go func() { + defer GinkgoRecover() + err = k8sManager.Start(ctrl.SetupSignalHandler()) + Expect(err).ToNot(HaveOccurred(), "failed to run manager") + gexec.KillAndWait(4 * time.Second) + + // Teardown the test environment once controller is fnished. + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) + }() -var _ = AfterSuite(func() { - By("tearing down the test environment") - err := testEnv.Stop() - Expect(err).NotTo(HaveOccurred()) }) diff --git a/go.mod b/go.mod index b8210b8c2..eff13a616 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( github.com/banzaicloud/k8s-objectmatcher v1.7.0 github.com/go-logr/logr v1.2.4 - github.com/onsi/ginkgo v1.16.5 + github.com/onsi/ginkgo/v2 v2.11.0 github.com/onsi/gomega v1.27.10 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.2.1 @@ -31,12 +31,14 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -47,7 +49,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nxadm/tail v1.4.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect @@ -63,11 +64,11 @@ require ( golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.9.3 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.28.0 // indirect diff --git a/go.sum b/go.sum index cbee05b11..0aec70c41 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,9 @@ github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -63,7 +66,6 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -110,6 +112,7 @@ github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3i github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -150,21 +153,13 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -193,7 +188,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -226,6 +221,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -236,7 +233,6 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -256,14 +252,12 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -288,7 +282,6 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= @@ -330,11 +323,9 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/hack/integrationSetup.sh b/hack/integrationSetup.sh new file mode 100755 index 000000000..666a71b5e --- /dev/null +++ b/hack/integrationSetup.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +K8S_VERSION="${K8S_VERSION:="1.28.x"}" +KUBEBUILDER_ASSETS="/usr/local/kubebuilder/bin" + +main() { + tools + kubebuilder +} + +tools() { + go install github.com/google/go-licenses@latest + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + go install github.com/google/ko@latest + go install github.com/mikefarah/yq/v4@latest + go install github.com/norwoodj/helm-docs/cmd/helm-docs@latest + go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest + go install sigs.k8s.io/controller-tools/cmd/controller-gen@latest + go install github.com/sigstore/cosign/v2/cmd/cosign@latest + go install -tags extended github.com/gohugoio/hugo@v0.110.0 + go install golang.org/x/vuln/cmd/govulncheck@latest + go install github.com/onsi/ginkgo/v2/ginkgo@latest + go install github.com/rhysd/actionlint/cmd/actionlint@latest + go install github.com/mattn/goveralls@latest + + if ! echo "$PATH" | grep -q "${GOPATH:-undefined}/bin\|$HOME/go/bin"; then + echo "Go workspace's \"bin\" directory is not in PATH. Run 'export PATH=\"\$PATH:\${GOPATH:-\$HOME/go}/bin\"'." + fi +} + +kubebuilder() { + sudo mkdir -p ${KUBEBUILDER_ASSETS} + sudo chown "${USER}" ${KUBEBUILDER_ASSETS} + arch=$(go env GOARCH) + ln -sf $(setup-envtest use -p path "${K8S_VERSION}" --arch="${arch}" --bin-dir="${KUBEBUILDER_ASSETS}")/* ${KUBEBUILDER_ASSETS} + find $KUBEBUILDER_ASSETS +} + +main "$@" \ No newline at end of file From 169194a69f89a1fd512fd5be86dfd70df1536a67 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Tue, 16 Jan 2024 03:09:23 +0100 Subject: [PATCH 085/203] chore: fix clinet typo (#751) Signed-off-by: Mathieu Cesbron --- controllers/redis_controller.go | 2 +- controllers/rediscluster_controller.go | 2 +- controllers/redisreplication_controller.go | 2 +- controllers/redissentinel_controller.go | 2 +- main.go | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index a73eb287f..e14bf8cd5 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -35,7 +35,7 @@ import ( type RedisReconciler struct { client.Client K8sClient kubernetes.Interface - Dk8sClinet dynamic.Interface + Dk8sClient dynamic.Interface Log logr.Logger Scheme *runtime.Scheme } diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index a3a65c04e..d9a123c2a 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -37,7 +37,7 @@ import ( type RedisClusterReconciler struct { client.Client K8sClient kubernetes.Interface - Dk8sClinet dynamic.Interface + Dk8sClient dynamic.Interface Log logr.Logger Scheme *runtime.Scheme } diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index a23cb8b3e..defc3e6d2 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -20,7 +20,7 @@ import ( type RedisReplicationReconciler struct { client.Client K8sClient kubernetes.Interface - Dk8sClinet dynamic.Interface + Dk8sClient dynamic.Interface Log logr.Logger Scheme *runtime.Scheme } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 03e686544..016135770 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -19,7 +19,7 @@ import ( type RedisSentinelReconciler struct { client.Client K8sClient kubernetes.Interface - Dk8sClinet dynamic.Interface + Dk8sClient dynamic.Interface Log logr.Logger Scheme *runtime.Scheme } diff --git a/main.go b/main.go index 3d22552ee..5f552bb35 100644 --- a/main.go +++ b/main.go @@ -107,7 +107,7 @@ func main() { os.Exit(1) } - dk8sClinet, err := k8sutils.GenerateK8sDynamicClient(k8sutils.GenerateK8sConfig) + dk8sClient, err := k8sutils.GenerateK8sDynamicClient(k8sutils.GenerateK8sConfig) if err != nil { setupLog.Error(err, "unable to create k8s dynamic client") os.Exit(1) @@ -116,7 +116,7 @@ func main() { if err = (&controllers.RedisReconciler{ Client: mgr.GetClient(), K8sClient: k8sclient, - Dk8sClinet: dk8sClinet, + Dk8sClient: dk8sClient, Log: ctrl.Log.WithName("controllers").WithName("Redis"), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { @@ -126,7 +126,7 @@ func main() { if err = (&controllers.RedisClusterReconciler{ Client: mgr.GetClient(), K8sClient: k8sclient, - Dk8sClinet: dk8sClinet, + Dk8sClient: dk8sClient, Log: ctrl.Log.WithName("controllers").WithName("RedisCluster"), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { @@ -136,7 +136,7 @@ func main() { if err = (&controllers.RedisReplicationReconciler{ Client: mgr.GetClient(), K8sClient: k8sclient, - Dk8sClinet: dk8sClinet, + Dk8sClient: dk8sClient, Log: ctrl.Log.WithName("controllers").WithName("RedisReplication"), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { @@ -146,7 +146,7 @@ func main() { if err = (&controllers.RedisSentinelReconciler{ Client: mgr.GetClient(), K8sClient: k8sclient, - Dk8sClinet: dk8sClinet, + Dk8sClient: dk8sClient, Log: ctrl.Log.WithName("controllers").WithName("RedisSentinel"), Scheme: mgr.GetScheme(), }).SetupWithManager(mgr); err != nil { From 629c2dfe12b3e7ea00a7f19b3aeeefaf79561941 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Thu, 18 Jan 2024 03:18:47 +0100 Subject: [PATCH 086/203] fix: generate dynamic k8s client only once (#752) Signed-off-by: Mathieu Cesbron --- controllers/rediscluster_controller.go | 10 ++++----- controllers/redissentinel_controller.go | 2 +- k8sutils/redis-sentinel.go | 27 ++++++++++--------------- k8sutils/redis-sentinel_test.go | 9 ++++++--- k8sutils/status.go | 10 +++------ 5 files changed, 26 insertions(+), 32 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index d9a123c2a..7b10eee15 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -101,7 +101,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Step 3 Rebalance the cluster k8sutils.RebalanceRedisCluster(r.K8sClient, r.Log, instance) reqLogger.Info("Redis cluster is downscaled... Rebalancing the cluster is done") - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, leaderReplicas) + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, leaderReplicas, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } @@ -110,7 +110,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Mark the cluster status as initializing if there are no leader or follower nodes if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, 0, 0) + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, 0, 0, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } @@ -144,7 +144,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Mark the cluster status as initializing if there are no follower nodes if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, 0) + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, 0, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } @@ -185,7 +185,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Mark the cluster status as bootstrapping if all the leader and follower nodes are ready if !(instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas) { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas) + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } @@ -236,7 +236,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Mark the cluster status as ready if all the leader and follower nodes are ready if instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas) + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 016135770..42b117672 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -55,7 +55,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques } // Create Redis Sentinel - err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance, r.K8sClient) + err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance, r.K8sClient, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 5ae9dbef1..698a19980 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -14,6 +14,7 @@ import ( corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" ) @@ -37,7 +38,7 @@ type RedisReplicationObject struct { } // Redis Sentinel Create the Redis Sentinel Setup -func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { +func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface, dcl dynamic.Interface) error { prop := RedisSentinelSTS{ RedisStateFulType: "sentinel", Affinity: cr.Spec.Affinity, @@ -50,7 +51,7 @@ func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logge prop.ExternalConfig = cr.Spec.RedisSentinelConfig.AdditionalSentinelConfig } - return prop.CreateRedisSentinelSetup(ctx, client, logger, cr, cl) + return prop.CreateRedisSentinelSetup(ctx, client, logger, cr, cl, dcl) } @@ -64,7 +65,7 @@ func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel, cl kubernetes.In } // Create Redis Sentinel Cluster Setup -func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { +func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface, dcl dynamic.Interface) error { stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType labels := getRedisLabels(stateFulName, sentinel, service.RedisStateFulType, cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) @@ -75,7 +76,7 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cl generateRedisSentinelParams(cr, service.getSentinelCount(cr), service.ExternalConfig, service.Affinity), redisSentinelAsOwner(cr), generateRedisSentinelInitContainerParams(cr), - generateRedisSentinelContainerParams(ctx, client, logger, cr, service.ReadinessProbe, service.LivenessProbe), + generateRedisSentinelContainerParams(ctx, client, logger, cr, service.ReadinessProbe, service.LivenessProbe, dcl), cr.Spec.Sidecars, cl, ) @@ -145,7 +146,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in } // Create Redis Sentinel Statefulset Container Params -func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe) containerParameters { +func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, dcl dynamic.Interface) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ @@ -154,7 +155,7 @@ func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - AdditionalEnvVariable: getSentinelEnvVariable(ctx, client, logger, cr), + AdditionalEnvVariable: getSentinelEnvVariable(ctx, client, logger, cr, dcl), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars @@ -245,7 +246,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. } -func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) *[]corev1.EnvVar { +func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) *[]corev1.EnvVar { if cr.Spec.RedisSentinelConfig == nil { return &[]corev1.EnvVar{} } @@ -257,7 +258,7 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, lo }, { Name: "IP", - Value: getRedisReplicationMasterIP(ctx, client, logger, cr), + Value: getRedisReplicationMasterIP(ctx, client, logger, cr, dcl), }, { Name: "PORT", @@ -291,13 +292,7 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, lo } -func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel) string { - dClient, err := GenerateK8sDynamicClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Failed to generate dynamic client") - return "" - } - +func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) string { replicationName := cr.Spec.RedisSentinelConfig.RedisReplicationName replicationNamespace := cr.Namespace @@ -305,7 +300,7 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac var realMasterPod string // Get Request on Dynamic Client - customObject, err := dClient.Resource(schema.GroupVersionResource{ + customObject, err := dcl.Resource(schema.GroupVersionResource{ Group: "redis.redis.opstreelabs.in", Version: "v1beta2", Resource: "redisreplications", diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index f30d7a267..85260d5b1 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -2,18 +2,21 @@ package k8sutils import ( "context" - "k8s.io/client-go/kubernetes" "os" "path/filepath" "reflect" "testing" + "k8s.io/client-go/dynamic/fake" + "k8s.io/client-go/kubernetes" + common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/utils/pointer" ) @@ -185,7 +188,7 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { t.Fatalf("Failed to unmarshal file %s: %v", path, err) } - actual := generateRedisSentinelContainerParams(context.TODO(), nil, logr.Logger{}, input, nil, nil) + actual := generateRedisSentinelContainerParams(context.TODO(), nil, logr.Logger{}, input, nil, nil, nil) assert.EqualValues(t, expected, actual, "Expected %+v, got %+v", expected, actual) } @@ -326,7 +329,7 @@ func Test_getSentinelEnvVariable(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := getSentinelEnvVariable(tt.args.ctx, tt.args.client, tt.args.logger, tt.args.cr); !reflect.DeepEqual(got, tt.want) { + if got := getSentinelEnvVariable(tt.args.ctx, tt.args.client, tt.args.logger, tt.args.cr, fake.NewSimpleDynamicClient(&runtime.Scheme{})); !reflect.DeepEqual(got, tt.want) { t.Errorf("getSentinelEnvVariable() = %v, want %v", got, tt.want) } }) diff --git a/k8sutils/status.go b/k8sutils/status.go index d652ad7c7..2beb2da91 100644 --- a/k8sutils/status.go +++ b/k8sutils/status.go @@ -10,6 +10,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/dynamic" ) // statusLogger will generate logging interface for status @@ -19,18 +20,13 @@ func statusLogger(namespace string, name string) logr.Logger { } // UpdateRedisClusterStatus will update the status of the RedisCluster -func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.RedisClusterState, resaon string, readyLeaderReplicas, readyFollowerReplicas int32) error { +func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.RedisClusterState, resaon string, readyLeaderReplicas, readyFollowerReplicas int32, dcl dynamic.Interface) error { logger := statusLogger(cr.Namespace, cr.Name) cr.Status.State = status cr.Status.Reason = resaon cr.Status.ReadyLeaderReplicas = readyLeaderReplicas cr.Status.ReadyFollowerReplicas = readyFollowerReplicas - client, err := GenerateK8sDynamicClient(GenerateK8sConfig) - if err != nil { - logger.Error(err, "Failed to generate k8s dynamic client") - return err - } gvr := schema.GroupVersionResource{ Group: "redis.redis.opstreelabs.in", Version: "v1beta2", @@ -43,7 +39,7 @@ func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.Redis } unstructuredRedisCluster := &unstructured.Unstructured{Object: unstructuredObj} - _, err = client.Resource(gvr).Namespace(cr.Namespace).UpdateStatus(context.TODO(), unstructuredRedisCluster, metav1.UpdateOptions{}) + _, err = dcl.Resource(gvr).Namespace(cr.Namespace).UpdateStatus(context.TODO(), unstructuredRedisCluster, metav1.UpdateOptions{}) if err != nil { logger.Error(err, "Failed to update status") return err From 6bf05bcf1bfb8edbc93a47e55355038a8577fc0a Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Thu, 18 Jan 2024 23:11:25 +0100 Subject: [PATCH 087/203] Add redis cluster integration tests (#753) * Move var integration tests Signed-off-by: Mathieu Cesbron * Add dynamic k8s client in integration tests Signed-off-by: Mathieu Cesbron * Add Integration tests for redis cluster Signed-off-by: Mathieu Cesbron --------- Signed-off-by: Mathieu Cesbron --- controllers/redis_controller_test.go | 8 -- controllers/rediscluster_controller_test.go | 145 ++++++++++++++++++++ controllers/suite_test.go | 26 +++- k8sutils/redis-cluster.go | 2 + 4 files changed, 170 insertions(+), 11 deletions(-) create mode 100644 controllers/rediscluster_controller_test.go diff --git a/controllers/redis_controller_test.go b/controllers/redis_controller_test.go index 3b9ff9870..dbc90cffc 100644 --- a/controllers/redis_controller_test.go +++ b/controllers/redis_controller_test.go @@ -3,7 +3,6 @@ package controllers import ( "context" "fmt" - "time" appsv1 "k8s.io/api/apps/v1" @@ -17,13 +16,6 @@ import ( "k8s.io/apimachinery/pkg/types" ) -const ( - ns = "default" - - timeout = time.Second * 5 - interval = time.Millisecond * 250 -) - var _ = Describe("Redis standalone test", func() { var ( redisCR redisv1beta2.Redis diff --git a/controllers/rediscluster_controller_test.go b/controllers/rediscluster_controller_test.go new file mode 100644 index 000000000..9a3c7aed3 --- /dev/null +++ b/controllers/rediscluster_controller_test.go @@ -0,0 +1,145 @@ +package controllers + +import ( + "context" + "fmt" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("Redis cluster test", func() { + var ( + redisClusterCR redisv1beta2.RedisCluster + redisClusterCRName string + size int32 + // version string + // Used to create unique name for each test + testCount int + ) + + JustBeforeEach(func() { + size = 3 + // version = "v7" + redisClusterCR = redisv1beta2.RedisCluster{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redis.redis.opstreelabs.in/v1beta2", + Kind: "RedisCluster", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: redisClusterCRName, + Namespace: ns, + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: &size, + // ClusterVersion: &version, + Storage: &redisv1beta2.ClusterStorage{}, + }, + } + Expect(k8sClient.Create(context.TODO(), &redisClusterCR)).Should(Succeed()) + testCount++ + }) + + BeforeEach(func() { + redisClusterCRName = fmt.Sprintf("redis-cluster-%d", testCount) + }) + + Context("When creating a redis cluster CR", func() { + It("should create a statefulset", func() { + + sts := &appsv1.StatefulSet{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisClusterCRName + "-leader", + Namespace: ns, + }, sts) + }, timeout, interval).Should(BeNil()) + + Expect(sts.Labels).To(Equal(map[string]string{ + "app": redisClusterCRName + "-leader", + "redis_setup_type": "cluster", + "role": "leader", + })) + + Expect(*sts.Spec.Replicas).To(BeEquivalentTo(3)) + Expect(sts.Spec.ServiceName).To(Equal(redisClusterCRName + "-leader-headless")) + }) + + It("should create a service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisClusterCRName + "-leader", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisClusterCRName + "-leader", + "redis_setup_type": "cluster", + "role": "leader", + })) + }) + + It("should create a headless service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisClusterCRName + "-leader-headless", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisClusterCRName + "-leader", + "redis_setup_type": "cluster", + "role": "leader", + })) + }) + + It("should create additional service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisClusterCRName + "-leader-additional", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisClusterCRName + "-leader", + "redis_setup_type": "cluster", + "role": "leader", + })) + }) + + Context("then deleting the redis cluster CR", func() { + It("should delete the statefulset", func() { + redisClusterCR := &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: redisClusterCRName, + Namespace: ns, + }, + } + Expect(k8sClient.Delete(context.TODO(), redisClusterCR)).To(BeNil()) + + Eventually(func() bool { + sts := &appsv1.StatefulSet{} + err := k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisClusterCRName, + Namespace: ns, + }, sts) + return errors.IsNotFound(err) + }, timeout, interval).Should(BeTrue()) + }) + }) + }) +}) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 3bc2b13c7..150022568 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -27,6 +27,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" @@ -41,6 +42,13 @@ import ( var k8sClient client.Client var testEnv *envtest.Environment +const ( + ns = "default" + + timeout = time.Second * 10 + interval = time.Millisecond * 250 +) + func TestAPIs(t *testing.T) { RegisterFailHandler(Fail) @@ -83,10 +91,22 @@ var _ = BeforeSuite(func() { k8sClient, err := kubernetes.NewForConfig(cfg) Expect(err).ToNot(HaveOccurred()) + dk8sClient, err := dynamic.NewForConfig(cfg) + Expect(err).ToNot(HaveOccurred()) + err = (&RedisReconciler{ - Client: k8sManager.GetClient(), - K8sClient: k8sClient, - Scheme: k8sManager.GetScheme(), + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Dk8sClient: dk8sClient, + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + + err = (&RedisClusterReconciler{ + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Dk8sClient: dk8sClient, + Scheme: k8sManager.GetScheme(), }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index cfa2748d2..ae6a26247 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -1,6 +1,7 @@ package k8sutils import ( + "fmt" "strconv" "strings" @@ -34,6 +35,7 @@ type RedisClusterService struct { // generateRedisClusterParams generates Redis cluster information func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, externalConfig *string, params RedisClusterSTS) statefulSetParameters { + fmt.Println(cr.Spec.Storage.NodeConfVolume) res := statefulSetParameters{ Replicas: &replicas, ClusterMode: true, From f9938bc321b9b80472be58551503e1b285d400a5 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Sat, 20 Jan 2024 06:15:54 +0100 Subject: [PATCH 088/203] test: add redis replication integration tests (#754) * Remove commented code Signed-off-by: Mathieu Cesbron * Add redis replication reconciler in suite test Signed-off-by: Mathieu Cesbron * Add redis replication integration tests Signed-off-by: Mathieu Cesbron --------- Signed-off-by: Mathieu Cesbron --- controllers/rediscluster_controller_test.go | 6 +- .../redisreplication_controller_test.go | 134 ++++++++++++++++++ controllers/suite_test.go | 8 ++ 3 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 controllers/redisreplication_controller_test.go diff --git a/controllers/rediscluster_controller_test.go b/controllers/rediscluster_controller_test.go index 9a3c7aed3..da9933f07 100644 --- a/controllers/rediscluster_controller_test.go +++ b/controllers/rediscluster_controller_test.go @@ -21,14 +21,12 @@ var _ = Describe("Redis cluster test", func() { redisClusterCR redisv1beta2.RedisCluster redisClusterCRName string size int32 - // version string // Used to create unique name for each test testCount int ) JustBeforeEach(func() { size = 3 - // version = "v7" redisClusterCR = redisv1beta2.RedisCluster{ TypeMeta: metav1.TypeMeta{ APIVersion: "redis.redis.opstreelabs.in/v1beta2", @@ -39,8 +37,7 @@ var _ = Describe("Redis cluster test", func() { Namespace: ns, }, Spec: redisv1beta2.RedisClusterSpec{ - Size: &size, - // ClusterVersion: &version, + Size: &size, Storage: &redisv1beta2.ClusterStorage{}, }, } @@ -54,7 +51,6 @@ var _ = Describe("Redis cluster test", func() { Context("When creating a redis cluster CR", func() { It("should create a statefulset", func() { - sts := &appsv1.StatefulSet{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ diff --git a/controllers/redisreplication_controller_test.go b/controllers/redisreplication_controller_test.go new file mode 100644 index 000000000..e7aee304b --- /dev/null +++ b/controllers/redisreplication_controller_test.go @@ -0,0 +1,134 @@ +package controllers + +import ( + "context" + "fmt" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("Redis replication test", func() { + var ( + redisReplicationCR redisv1beta2.RedisReplication + redisReplicationCRName string + size int32 + // Used to create unique name for each test + testCount int + ) + + JustBeforeEach(func() { + size = 3 + redisReplicationCR = redisv1beta2.RedisReplication{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redis.redis.opstreelabs.in/v1beta2", + Kind: "RedisReplication", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: redisReplicationCRName, + Namespace: ns, + }, + Spec: redisv1beta2.RedisReplicationSpec{ + Size: &size, + Storage: &redisv1beta2.Storage{}, + }, + } + Expect(k8sClient.Create(context.TODO(), &redisReplicationCR)).Should(Succeed()) + testCount++ + }) + + BeforeEach(func() { + redisReplicationCRName = fmt.Sprintf("redis-replication-%d", testCount) + }) + + Context("When creating a redis replication CR", func() { + It("should create a statefulset", func() { + + sts := &appsv1.StatefulSet{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisReplicationCRName, + Namespace: ns, + }, sts) + }, timeout, interval).Should(BeNil()) + + Expect(*sts.Spec.Replicas).To(BeEquivalentTo(3)) + Expect(sts.Spec.ServiceName).To(Equal(redisReplicationCRName + "-headless")) + }) + + It("should create a service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisReplicationCRName, + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisReplicationCRName, + "redis_setup_type": "replication", + "role": "replication", + })) + }) + + It("should create a headless service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisReplicationCRName + "-headless", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisReplicationCRName, + "redis_setup_type": "replication", + "role": "replication", + })) + }) + + It("should create additional service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisReplicationCRName + "-additional", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisReplicationCRName, + "redis_setup_type": "replication", + "role": "replication", + })) + }) + + Context("then deleting the redis replication CR", func() { + It("should delete the statefulset", func() { + redisReplicationCR := &redisv1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: redisReplicationCRName, + Namespace: ns, + }, + } + Expect(k8sClient.Delete(context.TODO(), redisReplicationCR)).To(BeNil()) + + Eventually(func() bool { + sts := &appsv1.StatefulSet{} + err := k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisReplicationCRName, + Namespace: ns, + }, sts) + return errors.IsNotFound(err) + }, timeout, interval).Should(BeTrue()) + }) + }) + }) +}) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 150022568..cb19c5b01 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -110,6 +110,14 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + err = (&RedisReplicationReconciler{ + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Dk8sClient: dk8sClient, + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + go func() { defer GinkgoRecover() err = k8sManager.Start(ctrl.SetupSignalHandler()) From 2e1ba9764507475e7826be60aa4f457763b16ad6 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Sun, 21 Jan 2024 03:52:44 +0100 Subject: [PATCH 089/203] test: add redis sentinel integration tests (#755) * Add redis sentinel in suite test Signed-off-by: Mathieu Cesbron * Add redis sentinel integration tests Signed-off-by: Mathieu Cesbron --------- Signed-off-by: Mathieu Cesbron --- controllers/redissentinel_controller_test.go | 149 +++++++++++++++++++ controllers/suite_test.go | 8 + 2 files changed, 157 insertions(+) create mode 100644 controllers/redissentinel_controller_test.go diff --git a/controllers/redissentinel_controller_test.go b/controllers/redissentinel_controller_test.go new file mode 100644 index 000000000..f53fafb8c --- /dev/null +++ b/controllers/redissentinel_controller_test.go @@ -0,0 +1,149 @@ +package controllers + +import ( + "context" + "fmt" + + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +var _ = Describe("Redis sentinel test", func() { + var ( + redisSentinelCR redisv1beta2.RedisSentinel + redisSentinelCRName string + size int32 + // Used to create unique name for each test + testCount int + ) + + JustBeforeEach(func() { + size = 3 + redisSentinelCR = redisv1beta2.RedisSentinel{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "redis.redis.opstreelabs.in/v1beta2", + Kind: "RedisReplication", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: redisSentinelCRName, + Namespace: ns, + }, + Spec: redisv1beta2.RedisSentinelSpec{ + Size: &size, + }, + } + Expect(k8sClient.Create(context.TODO(), &redisSentinelCR)).Should(Succeed()) + testCount++ + }) + + BeforeEach(func() { + redisSentinelCRName = fmt.Sprintf("redis-sentinel-%d", testCount) + }) + + Context("When creating a redis sentinel CR", func() { + It("should create a statefulset", func() { + + // Eventually(func() int { + // list := &appsv1.StatefulSetList{} + // // list := &redisv1beta2.RedisClusterList{} + // // list := &corev1.PodList{} + // // list := &corev1.ServiceList{} + + // err := k8sClient.List(context.TODO(), list) + // if err != nil { + // return -1 + // } + // for _, v := range list.Items { + // fmt.Println(v.Name) + // } + // return len(list.Items) + // }, timeout, interval).Should(Equal(3)) + + sts := &appsv1.StatefulSet{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisSentinelCRName + "-sentinel", + Namespace: ns, + }, sts) + }, timeout, interval).Should(BeNil()) + + Expect(*sts.Spec.Replicas).To(BeEquivalentTo(3)) + Expect(sts.Spec.ServiceName).To(Equal(redisSentinelCRName + "-sentinel-headless")) + }) + + It("should create a service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisSentinelCRName + "-sentinel", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisSentinelCRName + "-sentinel", + "redis_setup_type": "sentinel", + "role": "sentinel", + })) + }) + + It("should create a headless service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisSentinelCRName + "-sentinel-headless", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisSentinelCRName + "-sentinel", + "redis_setup_type": "sentinel", + "role": "sentinel", + })) + }) + + It("should create additional service", func() { + svc := &corev1.Service{} + Eventually(func() error { + return k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisSentinelCRName + "-sentinel-additional", + Namespace: ns, + }, svc) + }, timeout, interval).Should(BeNil()) + + Expect(svc.Labels).To(Equal(map[string]string{ + "app": redisSentinelCRName + "-sentinel", + "redis_setup_type": "sentinel", + "role": "sentinel", + })) + }) + + Context("then deleting the redis sentinel CR", func() { + It("should delete the statefulset", func() { + redisSentinelCR := &redisv1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: redisSentinelCRName, + Namespace: ns, + }, + } + Expect(k8sClient.Delete(context.TODO(), redisSentinelCR)).To(BeNil()) + + Eventually(func() bool { + sts := &appsv1.StatefulSet{} + err := k8sClient.Get(context.TODO(), types.NamespacedName{ + Name: redisSentinelCRName + "-sentinel", + Namespace: ns, + }, sts) + return errors.IsNotFound(err) + }, timeout, interval).Should(BeTrue()) + }) + }) + }) +}) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index cb19c5b01..0ab8268ff 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -118,6 +118,14 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + err = (&RedisSentinelReconciler{ + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Dk8sClient: dk8sClient, + Scheme: k8sManager.GetScheme(), + }).SetupWithManager(k8sManager) + Expect(err).ToNot(HaveOccurred()) + go func() { defer GinkgoRecover() err = k8sManager.Start(ctrl.SetupSignalHandler()) From 3e6fcb9a5f44052db0767cbe278f83516d278741 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Tue, 23 Jan 2024 20:34:42 +0100 Subject: [PATCH 090/203] Remove useless comment (#758) Signed-off-by: Mathieu Cesbron --- controllers/redissentinel_controller_test.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/controllers/redissentinel_controller_test.go b/controllers/redissentinel_controller_test.go index f53fafb8c..6b82ef460 100644 --- a/controllers/redissentinel_controller_test.go +++ b/controllers/redissentinel_controller_test.go @@ -48,23 +48,6 @@ var _ = Describe("Redis sentinel test", func() { Context("When creating a redis sentinel CR", func() { It("should create a statefulset", func() { - - // Eventually(func() int { - // list := &appsv1.StatefulSetList{} - // // list := &redisv1beta2.RedisClusterList{} - // // list := &corev1.PodList{} - // // list := &corev1.ServiceList{} - - // err := k8sClient.List(context.TODO(), list) - // if err != nil { - // return -1 - // } - // for _, v := range list.Items { - // fmt.Println(v.Name) - // } - // return len(list.Items) - // }, timeout, interval).Should(Equal(3)) - sts := &appsv1.StatefulSet{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ From a14300132e58ba1b879b2c2b7ddb7aecca40315e Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 1 Feb 2024 16:26:33 +0800 Subject: [PATCH 091/203] chore: enhance log every reconcile redis cluster (#767) Signed-off-by: drivebyer --- controllers/rediscluster_controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 7b10eee15..76b57d305 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -191,8 +191,8 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } } - reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) if nc := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, ""); nc != totalReplicas { + reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) leaderCount := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) From 997dc67f2af66c48e79f8cc6cdba9d4063abedd8 Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 7 Feb 2024 16:23:07 +0800 Subject: [PATCH 092/203] ci: improve the PR semantics (#770) * ci: improve the PR semantics Signed-off-by: drivebyer * update scope Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/pr-semantics.yaml | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 .github/workflows/pr-semantics.yaml diff --git a/.github/workflows/pr-semantics.yaml b/.github/workflows/pr-semantics.yaml new file mode 100644 index 000000000..bf06c5692 --- /dev/null +++ b/.github/workflows/pr-semantics.yaml @@ -0,0 +1,78 @@ +# feat: (new feature for the user, not a new feature for build script) +# fix: (bug fix for the user, not a fix to a build script) +# build: (changes that affect the build system or external dependencies) +# chore: (updating grunt tasks etc; no production code change) +# ci: (updates to CI configuration files and scripts; no production code change) +# docs: (changes to the documentation) +# perf: (a code change that improves performance) +# refactor: (refactoring production code, eg. renaming a variable) +# style: (formatting, missing semi colons, etc; no production code change) +# test: (adding missing tests, refactoring tests; no production code change) +# revert: (reverting a previous commit) + +# Example: +# test(runner): Add test for the runner +# ^ ^ ^ +# | | |__ Subject +# | |_______ Scope +# |____________ Type + +name: Semantic PR Validation +on: + pull_request: + types: + - opened + - edited + - synchronize +defaults: + run: + shell: bash +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Validate Pull Request + uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + # Configure which types are allowed. + # Default: https://github.com/commitizen/conventional-commit-types + types: | + feat + fix + build + chore + ci + docs + perf + refactor + revert + style + test + revert + # Configure which scopes are allowed. + scopes: | + api + config + client + config + data + test + utils + docs + release + testdata + ignoreLabels: | + bot + ignore-semantic-pull-request + # Configure that a scope must always be provided. + requireScope: false + # When using "Squash and merge" on a PR with only one commit, GitHub + # will suggest using that commit message instead of the PR title for the + # merge commit, and it's easy to commit this by mistake. Enable this option + # to also validate the commit message for one commit PRs. + validateSingleCommit: true + # Related to `validateSingleCommit` you can opt-in to validate that the PR + # title matches a single commit to avoid confusion. + validateSingleCommitMatchesPrTitle: true \ No newline at end of file From bb69d00c6a8830e01b75580bc3b812cccd1bd9e4 Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 8 Feb 2024 19:49:33 +0800 Subject: [PATCH 093/203] test: remove redundant creating (#771) test: remove redundant running spec Signed-off-by: drivebyer --- controllers/redis_controller_test.go | 20 ++++--------------- controllers/rediscluster_controller_test.go | 14 +++---------- .../redisreplication_controller_test.go | 14 ++++--------- controllers/redissentinel_controller_test.go | 13 +++--------- 4 files changed, 14 insertions(+), 47 deletions(-) diff --git a/controllers/redis_controller_test.go b/controllers/redis_controller_test.go index dbc90cffc..17830fd1f 100644 --- a/controllers/redis_controller_test.go +++ b/controllers/redis_controller_test.go @@ -44,10 +44,11 @@ var _ = Describe("Redis standalone test", func() { }) Context("When creating a redis standalone CR", func() { - It("should create a statefulset", func() { - var sts *appsv1.StatefulSet + It("should create a statefulset, service", func() { + sts := &appsv1.StatefulSet{} + svc := &corev1.Service{} + Eventually(func() error { - sts = &appsv1.StatefulSet{} return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisCRName, Namespace: ns, @@ -62,12 +63,8 @@ var _ = Describe("Redis standalone test", func() { Expect(*sts.Spec.Replicas).To(BeEquivalentTo(1)) Expect(sts.Spec.ServiceName).To(Equal(redisCRName + "-headless")) - }) - It("should create a service", func() { - var svc *corev1.Service Eventually(func() error { - svc = &corev1.Service{} return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisCR.Name, Namespace: ns, @@ -79,12 +76,8 @@ var _ = Describe("Redis standalone test", func() { "redis_setup_type": "standalone", "role": "standalone", })) - }) - It("should create a headless service", func() { - var svc *corev1.Service Eventually(func() error { - svc = &corev1.Service{} return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisCR.Name + "-headless", Namespace: ns, @@ -96,12 +89,7 @@ var _ = Describe("Redis standalone test", func() { "redis_setup_type": "standalone", "role": "standalone", })) - }) - - It("should create additional service", func() { - var svc *corev1.Service Eventually(func() error { - svc = &corev1.Service{} return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisCR.Name + "-additional", Namespace: ns, diff --git a/controllers/rediscluster_controller_test.go b/controllers/rediscluster_controller_test.go index da9933f07..6ae21cbd9 100644 --- a/controllers/rediscluster_controller_test.go +++ b/controllers/rediscluster_controller_test.go @@ -50,8 +50,10 @@ var _ = Describe("Redis cluster test", func() { }) Context("When creating a redis cluster CR", func() { - It("should create a statefulset", func() { + It("should create a statefulset, service", func() { sts := &appsv1.StatefulSet{} + svc := &corev1.Service{} + Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisClusterCRName + "-leader", @@ -67,10 +69,7 @@ var _ = Describe("Redis cluster test", func() { Expect(*sts.Spec.Replicas).To(BeEquivalentTo(3)) Expect(sts.Spec.ServiceName).To(Equal(redisClusterCRName + "-leader-headless")) - }) - It("should create a service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisClusterCRName + "-leader", @@ -83,10 +82,7 @@ var _ = Describe("Redis cluster test", func() { "redis_setup_type": "cluster", "role": "leader", })) - }) - It("should create a headless service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisClusterCRName + "-leader-headless", @@ -99,10 +95,6 @@ var _ = Describe("Redis cluster test", func() { "redis_setup_type": "cluster", "role": "leader", })) - }) - - It("should create additional service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisClusterCRName + "-leader-additional", diff --git a/controllers/redisreplication_controller_test.go b/controllers/redisreplication_controller_test.go index e7aee304b..3d12c07ee 100644 --- a/controllers/redisreplication_controller_test.go +++ b/controllers/redisreplication_controller_test.go @@ -48,9 +48,11 @@ var _ = Describe("Redis replication test", func() { }) Context("When creating a redis replication CR", func() { - It("should create a statefulset", func() { + It("should create a statefulset, service", func() { + svc := &corev1.Service{} sts := &appsv1.StatefulSet{} + Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisReplicationCRName, @@ -60,10 +62,7 @@ var _ = Describe("Redis replication test", func() { Expect(*sts.Spec.Replicas).To(BeEquivalentTo(3)) Expect(sts.Spec.ServiceName).To(Equal(redisReplicationCRName + "-headless")) - }) - It("should create a service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisReplicationCRName, @@ -76,10 +75,7 @@ var _ = Describe("Redis replication test", func() { "redis_setup_type": "replication", "role": "replication", })) - }) - It("should create a headless service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisReplicationCRName + "-headless", @@ -92,10 +88,7 @@ var _ = Describe("Redis replication test", func() { "redis_setup_type": "replication", "role": "replication", })) - }) - It("should create additional service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisReplicationCRName + "-additional", @@ -108,6 +101,7 @@ var _ = Describe("Redis replication test", func() { "redis_setup_type": "replication", "role": "replication", })) + }) Context("then deleting the redis replication CR", func() { diff --git a/controllers/redissentinel_controller_test.go b/controllers/redissentinel_controller_test.go index 6b82ef460..a43a6b6f5 100644 --- a/controllers/redissentinel_controller_test.go +++ b/controllers/redissentinel_controller_test.go @@ -47,8 +47,10 @@ var _ = Describe("Redis sentinel test", func() { }) Context("When creating a redis sentinel CR", func() { - It("should create a statefulset", func() { + It("should create a statefulset, service", func() { sts := &appsv1.StatefulSet{} + svc := &corev1.Service{} + Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisSentinelCRName + "-sentinel", @@ -58,10 +60,7 @@ var _ = Describe("Redis sentinel test", func() { Expect(*sts.Spec.Replicas).To(BeEquivalentTo(3)) Expect(sts.Spec.ServiceName).To(Equal(redisSentinelCRName + "-sentinel-headless")) - }) - It("should create a service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisSentinelCRName + "-sentinel", @@ -74,10 +73,7 @@ var _ = Describe("Redis sentinel test", func() { "redis_setup_type": "sentinel", "role": "sentinel", })) - }) - It("should create a headless service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisSentinelCRName + "-sentinel-headless", @@ -90,10 +86,7 @@ var _ = Describe("Redis sentinel test", func() { "redis_setup_type": "sentinel", "role": "sentinel", })) - }) - It("should create additional service", func() { - svc := &corev1.Service{} Eventually(func() error { return k8sClient.Get(context.TODO(), types.NamespacedName{ Name: redisSentinelCRName + "-sentinel-additional", From df2df6d4b4cc053d99e92708be6ed261d970d77a Mon Sep 17 00:00:00 2001 From: yangw Date: Fri, 9 Feb 2024 17:58:13 +0800 Subject: [PATCH 094/203] feat: add field to keep pvc after cr be deleted (#772) * feat: add field to keep pvc after cr be deleted Signed-off-by: drivebyer * fix kind Signed-off-by: drivebyer * fix delete name Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/e2e-chainsaw.yml | 1 + api/common_types.go | 1 + .../redis.redis.opstreelabs.in_redis.yaml | 4 + ...is.redis.opstreelabs.in_redisclusters.yaml | 4 + ...edis.opstreelabs.in_redisreplications.yaml | 4 + k8sutils/finalizer.go | 18 +- .../keep-pvc/redis-cluster/chainsaw-test.yaml | 34 +++ .../keep-pvc/redis-cluster/cluster.yaml | 48 +++++ .../keep-pvc/redis-cluster/ready-cluster.yaml | 7 + .../keep-pvc/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../keep-pvc/redis-cluster/ready-sts.yaml | 25 +++ .../keep-pvc/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ .../redis-replication/chainsaw-test.yaml | 32 +++ .../keep-pvc/redis-replication/ready-pvc.yaml | 44 ++++ .../keep-pvc/redis-replication/ready-sts.yaml | 19 ++ .../keep-pvc/redis-replication/ready-svc.yaml | 90 ++++++++ .../redis-replication/replication.yaml | 28 +++ .../redis-standalone/chainsaw-test.yaml | 32 +++ .../keep-pvc/redis-standalone/ready-pvc.yaml | 14 ++ .../keep-pvc/redis-standalone/ready-sts.yaml | 11 + .../keep-pvc/redis-standalone/ready-svc.yaml | 96 +++++++++ .../keep-pvc/redis-standalone/standalone.yaml | 27 +++ 22 files changed, 915 insertions(+), 6 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index e3708c5f9..c3d151ed7 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -22,6 +22,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/ha-setup/ - ./tests/e2e-chainsaw/v1beta2/nodeport/ - ./tests/e2e-chainsaw/v1beta2/pvc-name/ + - ./tests/e2e-chainsaw/v1beta2/keep-pvc/ steps: - name: Checkout code diff --git a/api/common_types.go b/api/common_types.go index a67722406..ae4f5aa6a 100644 --- a/api/common_types.go +++ b/api/common_types.go @@ -54,6 +54,7 @@ type RedisConfig struct { // Storage is the inteface to add pvc and pv support in redis // +k8s:deepcopy-gen=true type Storage struct { + KeepAfterDelete bool `json:"keepAfterDelete,omitempty"` VolumeClaimTemplate corev1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"` VolumeMount AdditionalVolume `json:"volumeMount,omitempty"` } diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index fec228a5e..396696ccd 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -1685,6 +1685,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -6098,6 +6100,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index e525f917e..b781c15ef 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -2884,6 +2884,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -8657,6 +8659,8 @@ spec: storage: description: Node-conf needs to be added only in redis cluster properties: + keepAfterDelete: + type: boolean nodeConfVolume: default: false type: boolean diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index 76856bcfc..c52f9a10a 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -1687,6 +1687,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -6103,6 +6105,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index b85ef3c51..526fac516 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -31,8 +31,10 @@ func finalizerLogger(namespace string, name string) logr.Logger { func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisFinalizer) { - if err := finalizeRedisPVC(k8sClient, logger, cr); err != nil { - return err + if !cr.Spec.Storage.KeepAfterDelete { + if err := finalizeRedisPVC(k8sClient, logger, cr); err != nil { + return err + } } controllerutil.RemoveFinalizer(cr, RedisFinalizer) if err := ctrlclient.Update(context.TODO(), cr); err != nil { @@ -48,8 +50,10 @@ func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interfa func HandleRedisClusterFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisClusterFinalizer) { - if err := finalizeRedisClusterPVC(k8sClient, logger, cr); err != nil { - return err + if !cr.Spec.Storage.KeepAfterDelete { + if err := finalizeRedisClusterPVC(k8sClient, logger, cr); err != nil { + return err + } } controllerutil.RemoveFinalizer(cr, RedisClusterFinalizer) if err := ctrlclient.Update(context.TODO(), cr); err != nil { @@ -65,8 +69,10 @@ func HandleRedisClusterFinalizer(ctrlclient client.Client, k8sClient kubernetes. func HandleRedisReplicationFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisReplicationFinalizer) { - if err := finalizeRedisReplicationPVC(k8sClient, logger, cr); err != nil { - return err + if !cr.Spec.Storage.KeepAfterDelete { + if err := finalizeRedisReplicationPVC(k8sClient, logger, cr); err != nil { + return err + } } controllerutil.RemoveFinalizer(cr, RedisReplicationFinalizer) if err := ctrlclient.Update(context.TODO(), cr); err != nil { diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..5ee5221b4 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: keep-pvc +spec: + steps: + - name: Install + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: Uninstall + try: + - delete: + ref: + name: redis-cluster-v1beta2 + kind: RedisCluster + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml new file mode 100644 index 000000000..126651a37 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml @@ -0,0 +1,48 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + keepAfterDelete: true + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml new file mode 100644 index 000000000..922c98e94 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: keep-pvc +spec: + steps: + - name: Install + try: + - apply: + file: replication.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: Uninstall + try: + - delete: + ref: + name: redis-replication + kind: RedisReplication + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml new file mode 100644 index 000000000..f57cb3f61 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-0 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-1 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-replication-redis-replication-2 + labels: + app: redis-replication + redis_setup_type: replication + role: replication +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml new file mode 100644 index 000000000..f2ac67b1a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + annotations: + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +status: + readyReplicas: 3 + replicas: 3 \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml new file mode 100644 index 000000000..707a8df9b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml @@ -0,0 +1,90 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-replication + labels: + app: redis-replication + redis_setup_type: replication + role: replication + name: redis-replication-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisReplication + name: redis-replication +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-replication + redis_setup_type: replication + role: replication + type: ClusterIP \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml new file mode 100644 index 000000000..5b3f3c5ac --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + keepAfterDelete: true + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml new file mode 100644 index 000000000..130ba36df --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: keep-pvc +spec: + steps: + - name: Install + try: + - apply: + file: standalone.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: Uninstall + try: + - delete: + ref: + name: redis-standalone-v1beta2 + kind: Redis + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml new file mode 100644 index 000000000..777fa3656 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-standalone-v1beta2-redis-standalone-v1beta2-0 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml new file mode 100644 index 000000000..5402de920 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml @@ -0,0 +1,11 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone +status: + replicas: 1 + readyReplicas: 1 diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml new file mode 100644 index 000000000..08b416ce2 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml @@ -0,0 +1,96 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2 + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-standalone-v1beta2 + labels: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + name: redis-standalone-v1beta2-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: Redis + name: redis-standalone-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-standalone-v1beta2 + redis_setup_type: standalone + role: standalone + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml new file mode 100644 index 000000000..3962ff653 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml @@ -0,0 +1,27 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: redis-standalone-v1beta2 +spec: + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + keepAfterDelete: true + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi From db14d1b018b2fd0f62485bd2f8bd9b376c81dc10 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 20 Feb 2024 14:20:32 +0800 Subject: [PATCH 095/203] chore: enhance log every reconcile redis replication (#780) Signed-off-by: drivebyer --- controllers/redisreplication_controller.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index defc3e6d2..9929e332c 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -78,10 +78,8 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{RequeueAfter: time.Second * 60}, nil } - reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) - if len(k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master")) > int(leaderReplicas) { - + reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) masterNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master") slaveNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "slave") err := k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, slaveNodes) From 891d740293ab27ee8502f212088d05e0b29cb15f Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 26 Feb 2024 20:06:48 +0800 Subject: [PATCH 096/203] fix: nil pointer dereference in conversion webhook (#787) Signed-off-by: drivebyer --- api/v1beta1/redissentinel_conversion.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1beta1/redissentinel_conversion.go b/api/v1beta1/redissentinel_conversion.go index a069e1677..63a460b1c 100644 --- a/api/v1beta1/redissentinel_conversion.go +++ b/api/v1beta1/redissentinel_conversion.go @@ -121,7 +121,7 @@ func (dst *RedisSentinel) ConvertFrom(srcRaw conversion.Hub) error { } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.ReadinessProbe = &Probe{} + dst.Spec.LivenessProbe = &Probe{} dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe } // Sidecars From 30315eb5d10fc396a80b5f082a40c81d3e1e7852 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 2 Mar 2024 23:44:37 +0530 Subject: [PATCH 097/203] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..38cd2ca04 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: shubham-cmyk drivebyer From e97bf7d46ff4ee633cbfed3c78796f6a6e2ace56 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 2 Mar 2024 23:47:15 +0530 Subject: [PATCH 098/203] ci: bump chainsaw version (#789) Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index c3d151ed7..653233432 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -34,7 +34,7 @@ jobs: - name: Install chainsaw uses: kyverno/chainsaw/.github/actions/install@v0.0.9 with: - release: v0.0.9 + release: v0.1.7 - name: Check install run: chainsaw version From 8f5969f973763e3df421df17d9fb6381c5f0b25a Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 3 Mar 2024 03:49:18 +0530 Subject: [PATCH 099/203] add: codeowners (#793) Signed-off-by: Shubham Gupta --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..3fb870fd7 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +* @shubham-cmyk +* @drivebyer +* @iamabhishek-dubey \ No newline at end of file From 1193987d4e358cce946261cf36267f014256c2a1 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 3 Mar 2024 03:50:41 +0530 Subject: [PATCH 100/203] ci: fmt and vet covered in golang Ci linters by default (#792) Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 35 ++---------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 8d055d1bd..46caf204c 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -16,35 +16,6 @@ env: DOCKERFILE_PATH: "**/Dockerfile" jobs: - gofmt: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: ${{ env.GOLANG_VERSION }} - - name: Check Go Fmt - run: | - gofmt_files=$(go fmt ./... | wc -l) - if [[ ${gofmt_files} > 0 ]] - then - echo "Please format golang files using:- go fmt ./..." - exit 1 - else - echo "All files are formated using gofmt" - fi - govet: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: ${{ env.GOLANG_VERSION }} - - name: Run Go Vet - run: go vet ./... - gotest: name: Go Test runs-on: ubuntu-latest @@ -65,8 +36,7 @@ jobs: fail_ci_if_error: false verbose: true - code_quality_golang_ci_lint: - needs: [gofmt, govet] + lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -90,7 +60,6 @@ jobs: version: v1.54.0 container_quality_dockerfile_lint: - needs: [gofmt, govet] runs-on: ubuntu-latest steps: - name: Checkout code @@ -103,7 +72,7 @@ jobs: ignore: DL3007,DL3018 build_go_binary: - needs: [code_quality_golang_ci_lint] + needs: [lint] runs-on: ubuntu-latest strategy: matrix: From 4e66ea217aadca1f69b15e7b6c5a60206ceb3512 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 3 Mar 2024 03:57:38 +0530 Subject: [PATCH 101/203] ci: halt failing release (#794) Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 130 +++++++++++++------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index cefe56970..d8a6c722f 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -1,74 +1,74 @@ -name: Release container images +# name: Release container images -on: - pull_request: - types: [closed] - branches: - - master +# on: +# pull_request: +# types: [closed] +# branches: +# - master -env: - APPLICATION_NAME: redis-operator - QuayImageName: quay.io/opstree/redis-operator - APP_VERSION: "v0.15.2" - DOCKERFILE_PATH: './Dockerfile' +# env: +# APPLICATION_NAME: redis-operator +# QuayImageName: quay.io/opstree/redis-operator +# APP_VERSION: "v0.15.2" +# DOCKERFILE_PATH: './Dockerfile' -jobs: - release_image: - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - environment: release-image - steps: - - name: Checkout - uses: actions/checkout@v2 +# jobs: +# release_image: +# if: github.event.pull_request.merged == true +# runs-on: ubuntu-latest +# environment: release-image +# steps: +# - name: Checkout +# uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 +# - name: Set up Docker Buildx +# uses: docker/setup-buildx-action@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 +# - name: Set up QEMU +# uses: docker/setup-qemu-action@v3 - - name: Login to Quay.io - uses: docker/login-action@v3 - with: - registry: quay.io - username: ${{ secrets.QUAY_USERNAME }} - password: ${{ secrets.QUAY_PASSWORD }} +# - name: Login to Quay.io +# uses: docker/login-action@v3 +# with: +# registry: quay.io +# username: ${{ secrets.QUAY_USERNAME }} +# password: ${{ secrets.QUAY_PASSWORD }} - - name: Build and push multi-arch latest image - uses: docker/build-push-action@v2 - with: - context: . - file: ${{ env.DOCKERFILE_PATH }} - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ env.QuayImageName }}:${{ env.APP_VERSION }}, ${{ env.QuayImageName }}:latest +# - name: Build and push multi-arch latest image +# uses: docker/build-push-action@v2 +# with: +# context: . +# file: ${{ env.DOCKERFILE_PATH }} +# platforms: linux/amd64,linux/arm64 +# push: true +# tags: ${{ env.QuayImageName }}:${{ env.APP_VERSION }}, ${{ env.QuayImageName }}:latest - trivy_scan: - needs: [release_image] - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Run Trivy vulnerability scanner for arm64 image - uses: aquasecurity/trivy-action@master +# trivy_scan: +# needs: [release_image] +# runs-on: ubuntu-latest +# steps: +# - name: Checkout +# uses: actions/checkout@v2 +# - name: Run Trivy vulnerability scanner for arm64 image +# uses: aquasecurity/trivy-action@master - - name: Run Trivy vulnerability scanner for multi-arch image - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.QuayImageName }}:${{ env.APP_VERSION }} - format: 'template' - template: '@/contrib/sarif.tpl' - output: 'trivy-results-latest.sarif' - exit-code: '1' - ignore-unfixed: true - severity: 'CRITICAL,HIGH' - - name: Run Trivy vulnerability scanner for latest image - uses: aquasecurity/trivy-action@master - with: - image-ref: ${{ env.QuayImageName }}:latest - format: 'template' - template: '@/contrib/sarif.tpl' - output: 'trivy-results-latest.sarif' - exit-code: '1' - ignore-unfixed: true - severity: 'CRITICAL,HIGH' \ No newline at end of file +# - name: Run Trivy vulnerability scanner for multi-arch image +# uses: aquasecurity/trivy-action@master +# with: +# image-ref: ${{ env.QuayImageName }}:${{ env.APP_VERSION }} +# format: 'template' +# template: '@/contrib/sarif.tpl' +# output: 'trivy-results-latest.sarif' +# exit-code: '1' +# ignore-unfixed: true +# severity: 'CRITICAL,HIGH' +# - name: Run Trivy vulnerability scanner for latest image +# uses: aquasecurity/trivy-action@master +# with: +# image-ref: ${{ env.QuayImageName }}:latest +# format: 'template' +# template: '@/contrib/sarif.tpl' +# output: 'trivy-results-latest.sarif' +# exit-code: '1' +# ignore-unfixed: true +# severity: 'CRITICAL,HIGH' \ No newline at end of file From 649ebd4f3d0423e8d78a9b9cc2c3ab4d74f2a5da Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 3 Mar 2024 18:35:55 +0530 Subject: [PATCH 102/203] ci: Improve CI linting (#791) * ci: enable more linters Signed-off-by: Shubham Gupta * ci: diable few checks for temporary Signed-off-by: Shubham Gupta * ci: read permission to ci Signed-off-by: Shubham Gupta * ci: try removing cache Signed-off-by: Shubham Gupta * ci: diable ifelse linter for temp Signed-off-by: Shubham Gupta * syle: run gofumpt Signed-off-by: Shubham Gupta * sytle: run gci Signed-off-by: Shubham Gupta * ci: prevent misspell Signed-off-by: Shubham Gupta * ci: run go import Signed-off-by: Shubham Gupta * style: fix style errors Signed-off-by: Shubham Gupta * style: fix trailing lines Signed-off-by: Shubham Gupta * remove unwanted conversion Signed-off-by: Shubham Gupta * remove gci from generated file Signed-off-by: Shubham Gupta * style: remove init check Signed-off-by: Shubham Gupta * fix: type conversion Signed-off-by: Shubham Gupta * fix: remove context Signed-off-by: Shubham Gupta * ci: update configuration file Signed-off-by: Shubham Gupta * ci: skip generated files Signed-off-by: Shubham Gupta * ci: remove disabled lintesr Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/operator-ci.yaml | 13 +-- .golangci.yml | 87 ++++++++++--------- api/v1beta1/redis_types.go | 4 +- api/v1beta1/rediscluster_types.go | 4 +- api/v1beta1/redisreplication_types.go | 4 +- api/v1beta1/redissentinel_types.go | 4 +- api/v1beta2/redis_types.go | 4 +- api/v1beta2/rediscluster_types.go | 1 + api/v1beta2/redisreplication_types.go | 4 +- api/v1beta2/redissentinel_types.go | 4 +- controllers/redis_controller_test.go | 4 +- controllers/rediscluster_controller.go | 1 - controllers/rediscluster_controller_test.go | 6 +- controllers/redisreplication_controller.go | 6 +- .../redisreplication_controller_test.go | 2 - controllers/suite_test.go | 10 +-- k8sutils/client_test.go | 1 + k8sutils/cluster-scaling.go | 9 +- k8sutils/finalizer.go | 4 +- k8sutils/finalizers_test.go | 4 - k8sutils/labels.go | 8 +- k8sutils/labels_test.go | 3 +- k8sutils/poddisruption.go | 12 +-- k8sutils/redis-cluster.go | 6 +- k8sutils/redis-cluster_test.go | 3 +- k8sutils/redis-replication.go | 4 - k8sutils/redis-replication_test.go | 3 +- k8sutils/redis-sentinel.go | 15 +--- k8sutils/redis-sentinel_test.go | 14 ++- k8sutils/redis-standalone.go | 4 - k8sutils/redis-standalone_test.go | 3 +- k8sutils/redis.go | 7 +- k8sutils/redis_test.go | 2 +- k8sutils/services.go | 6 +- k8sutils/statefulset.go | 18 ++-- main.go | 17 ++-- mocks/utils/utils.go | 2 +- 37 files changed, 127 insertions(+), 176 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 46caf204c..72cd7db61 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -7,6 +7,9 @@ on: branches: - master +permissions: + contents: read + env: GOLANG_VERSION: 1.21 APPLICATION_NAME: redis-operator @@ -44,15 +47,7 @@ jobs: uses: actions/setup-go@v4 with: go-version: ${{ env.GOLANG_VERSION }} - - - name: Download Go modules - run: go mod download - - - name: Check disk space - run: df -h - - - name: List Go module cache - run: ls -la $(go env GOPATH)/pkg/mod + cache: false - name: Run GolangCI-Lint uses: golangci/golangci-lint-action@v3 diff --git a/.golangci.yml b/.golangci.yml index a72eb7d4d..1f6276d5a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,50 +2,59 @@ linters-settings: govet: check-shadowing: true golint: - min-confidence: 0.8 + min-confidence: 0.8 gofmt: simplify: true linters: - disable: - - errcheck - - tagliatelle + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - decorder + - dogsled + - durationcheck + - errcheck + - errname + - exportloopref + - gci + - gochecknoinits + - gofmt + - gofumpt + - goprintffuncname + - gosec + - gosimple + - govet + - grouper + - importas - ineffassign + - makezero + - misspell + - noctx + - nolintlint + - nosprintfhostport - staticcheck - -# Exclude the files that are causing the errors -issues: - exclude-rules: - - path: _test\.go # Ignore test files for linting - linters: - - gocyclo - - errcheck - - dupl - - gosec -run: - timeout: 5m - go-version: "1.21" - output: - format: colored-line-number - sort-results: true + - tenv + - thelper + - tparallel + - typecheck + - unconvert + - unused + - wastedassign + - whitespace - test: false - # Exclude third-party packages and go.mod from the lint checks - exclude: | - '(^vendor/.*|.*_test\.go|go\.mod|.*validatingwebhookconfiguration\.go|.*mutatingwebhookconfiguration\.go)' +run: + timeout: 15m + go: "1.21" + tests: true + show-stats: true skip-files: - - '^.*validatingwebhookconfiguration\.go$' - - controllers/suite_test.go - skip-dirs: - - k8s.io/client-go - - github.com/banzaicloud/k8s-objectmatcher - - github.com/go-logr/logr - - github.com/redis/go-redis - - github.com/onsi/ginkgo - - github.com/onsi/gomega - - github.com/pkg/errors - - k8s.io/api - - k8s.io/apimachinery - - sigs.k8s.io/controller-runtime - - golang.org/x/sys - - vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ \ No newline at end of file + - ".+\\.generated.go" + +output: + format: colored-line-number + sort-results: true + print-linter-name: true + print-issued-lines: true \ No newline at end of file diff --git a/api/v1beta1/redis_types.go b/api/v1beta1/redis_types.go index 6a38be57a..8f30e2d10 100644 --- a/api/v1beta1/redis_types.go +++ b/api/v1beta1/redis_types.go @@ -45,8 +45,7 @@ type RedisSpec struct { } // RedisStatus defines the observed state of Redis -type RedisStatus struct { -} +type RedisStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -69,6 +68,7 @@ type RedisList struct { Items []Redis `json:"items"` } +// //nolint:gochecknoinits func init() { SchemeBuilder.Register(&Redis{}, &RedisList{}) } diff --git a/api/v1beta1/rediscluster_types.go b/api/v1beta1/rediscluster_types.go index 4076e71c0..21df7fde0 100644 --- a/api/v1beta1/rediscluster_types.go +++ b/api/v1beta1/rediscluster_types.go @@ -64,8 +64,7 @@ type RedisFollower struct { } // RedisClusterStatus defines the observed state of RedisCluster -type RedisClusterStatus struct { -} +type RedisClusterStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -91,6 +90,7 @@ type RedisClusterList struct { Items []RedisCluster `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&RedisCluster{}, &RedisClusterList{}) } diff --git a/api/v1beta1/redisreplication_types.go b/api/v1beta1/redisreplication_types.go index df9ea159c..4cca92403 100644 --- a/api/v1beta1/redisreplication_types.go +++ b/api/v1beta1/redisreplication_types.go @@ -31,8 +31,7 @@ func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { } // RedisStatus defines the observed state of Redis -type RedisReplicationStatus struct { -} +type RedisReplicationStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -55,6 +54,7 @@ type RedisReplicationList struct { Items []RedisReplication `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&RedisReplication{}, &RedisReplicationList{}) } diff --git a/api/v1beta1/redissentinel_types.go b/api/v1beta1/redissentinel_types.go index 43103f2d5..54536b231 100644 --- a/api/v1beta1/redissentinel_types.go +++ b/api/v1beta1/redissentinel_types.go @@ -37,8 +37,7 @@ type RedisSentinelConfig struct { common.RedisSentinelConfig `json:",inline"` } -type RedisSentinelStatus struct { -} +type RedisSentinelStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -61,6 +60,7 @@ type RedisSentinelList struct { Items []RedisSentinel `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&RedisSentinel{}, &RedisSentinelList{}) } diff --git a/api/v1beta2/redis_types.go b/api/v1beta2/redis_types.go index 091cb19ea..d6e56c775 100644 --- a/api/v1beta2/redis_types.go +++ b/api/v1beta2/redis_types.go @@ -50,8 +50,7 @@ type RedisSpec struct { } // RedisStatus defines the observed state of Redis -type RedisStatus struct { -} +type RedisStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -75,6 +74,7 @@ type RedisList struct { Items []Redis `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&Redis{}, &RedisList{}) } diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index b9e629f7a..31c188494 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -113,6 +113,7 @@ type RedisClusterList struct { Items []RedisCluster `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&RedisCluster{}, &RedisClusterList{}) } diff --git a/api/v1beta2/redisreplication_types.go b/api/v1beta2/redisreplication_types.go index cb04c169d..59248fb55 100644 --- a/api/v1beta2/redisreplication_types.go +++ b/api/v1beta2/redisreplication_types.go @@ -36,8 +36,7 @@ func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { } // RedisStatus defines the observed state of Redis -type RedisReplicationStatus struct { -} +type RedisReplicationStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -61,6 +60,7 @@ type RedisReplicationList struct { Items []RedisReplication `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&RedisReplication{}, &RedisReplicationList{}) } diff --git a/api/v1beta2/redissentinel_types.go b/api/v1beta2/redissentinel_types.go index b40ee6e10..8787ee96c 100644 --- a/api/v1beta2/redissentinel_types.go +++ b/api/v1beta2/redissentinel_types.go @@ -41,8 +41,7 @@ type RedisSentinelConfig struct { common.RedisSentinelConfig `json:",inline"` } -type RedisSentinelStatus struct { -} +type RedisSentinelStatus struct{} // +kubebuilder:object:root=true // +kubebuilder:subresource:status @@ -66,6 +65,7 @@ type RedisSentinelList struct { Items []RedisSentinel `json:"items"` } +//nolint:gochecknoinits func init() { SchemeBuilder.Register(&RedisSentinel{}, &RedisSentinelList{}) } diff --git a/controllers/redis_controller_test.go b/controllers/redis_controller_test.go index 17830fd1f..ea04c705d 100644 --- a/controllers/redis_controller_test.go +++ b/controllers/redis_controller_test.go @@ -4,13 +4,11 @@ import ( "context" "fmt" - appsv1 "k8s.io/api/apps/v1" - redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 76b57d305..3cc478f93 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -141,7 +141,6 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } if redisLeaderInfo.Status.ReadyReplicas == leaderReplicas { - // Mark the cluster status as initializing if there are no follower nodes if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, 0, r.Dk8sClient) diff --git a/controllers/rediscluster_controller_test.go b/controllers/rediscluster_controller_test.go index 6ae21cbd9..a28cbedf0 100644 --- a/controllers/rediscluster_controller_test.go +++ b/controllers/rediscluster_controller_test.go @@ -4,13 +4,11 @@ import ( "context" "fmt" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 9929e332c..d6f9b85cb 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -26,7 +26,6 @@ type RedisReplicationReconciler struct { } func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name) reqLogger.Info("Reconciling opstree redis replication controller") instance := &redisv1beta2.RedisReplication{} @@ -73,7 +72,7 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req } // Check that the Leader and Follower are ready in redis replication - if int32(redisReplicationInfo.Status.ReadyReplicas) != totalReplicas { + if redisReplicationInfo.Status.ReadyReplicas != totalReplicas { reqLogger.Info("Redis replication nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas)), "Expected.Replicas", totalReplicas) return ctrl.Result{RequeueAfter: time.Second * 60}, nil } @@ -86,12 +85,9 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } - } - reqLogger.Info("Will reconcile redis operator in again 10 seconds") return ctrl.Result{RequeueAfter: time.Second * 10}, nil - } // SetupWithManager sets up the controller with the Manager. diff --git a/controllers/redisreplication_controller_test.go b/controllers/redisreplication_controller_test.go index 3d12c07ee..ff833a5b1 100644 --- a/controllers/redisreplication_controller_test.go +++ b/controllers/redisreplication_controller_test.go @@ -49,7 +49,6 @@ var _ = Describe("Redis replication test", func() { Context("When creating a redis replication CR", func() { It("should create a statefulset, service", func() { - svc := &corev1.Service{} sts := &appsv1.StatefulSet{} @@ -101,7 +100,6 @@ var _ = Describe("Redis replication test", func() { "redis_setup_type": "replication", "role": "replication", })) - }) Context("then deleting the redis replication CR", func() { diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 0ab8268ff..970eaf24d 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -23,7 +23,6 @@ import ( // redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" @@ -31,16 +30,16 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - // +kubebuilder:scaffold:imports ) -var k8sClient client.Client -var testEnv *envtest.Environment +var ( + k8sClient client.Client + testEnv *envtest.Environment +) const ( ns = "default" @@ -136,5 +135,4 @@ var _ = BeforeSuite(func() { err := testEnv.Stop() Expect(err).ToNot(HaveOccurred()) }() - }) diff --git a/k8sutils/client_test.go b/k8sutils/client_test.go index 13618dc70..4a9904e1c 100644 --- a/k8sutils/client_test.go +++ b/k8sutils/client_test.go @@ -11,6 +11,7 @@ import ( func mockK8sConfigProvider() (*rest.Config, error) { return &rest.Config{}, nil } + func mockInvalidK8sConfigProvider() (*rest.Config, error) { return nil, errors.New("invalid configuration") } diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index 957b74b28..6e9303bc3 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -94,7 +94,6 @@ func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logg // Split the Redis cluster info into lines lines := strings.Split(redisClusterInfo, "\n") - // Iterate through all lines for _, line := range lines { if strings.Contains(line, "master") && strings.Contains(line, "connected") { // Check if this line is a master node @@ -114,9 +113,7 @@ func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logg } } } - logger.V(1).Info("Total cluster slots to be transferred from", "node", nodeID, "is", totalSlots) - return strconv.Itoa(totalSlots) } @@ -290,7 +287,6 @@ func getAttachedFollowerNodeIDs(ctx context.Context, client kubernetes.Interface slaveIDs = append(slaveIDs, parts[0]) } } - } logger.V(1).Info("Slaves Nodes attached to", "node", masterNodeID, "are", slaveIDs) @@ -334,7 +330,6 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. } for _, followerNodeID := range followerNodeIDs { - cmd = append(cmd, followerNodeID) logger.V(1).Info("Redis cluster follower remove command is", "Command", cmd) executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") @@ -345,7 +340,7 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. // Remove redis cluster node would remove last node to the existing redis cluster using redis-cli func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, removePod RedisDetails) { var cmd []string - //currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") + // currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") existingPod := RedisDetails{ PodName: cr.ObjectMeta.Name + "-leader-0", @@ -398,7 +393,7 @@ func VerifyLeaderPod(ctx context.Context, client kubernetes.Interface, logger lo } lines := strings.Split(info, "\r\n") - role := "" + var role string for _, line := range lines { if strings.HasPrefix(line, "role:") { role = strings.TrimPrefix(line, "role:") diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index 526fac516..b9a08d27c 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -3,13 +3,13 @@ package k8sutils import ( "context" "fmt" - "k8s.io/utils/env" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" + "k8s.io/utils/env" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) @@ -172,7 +172,6 @@ func finalizeRedisClusterPVC(client kubernetes.Interface, logger logr.Logger, cr } } } - } return nil } @@ -192,6 +191,5 @@ func finalizeRedisReplicationPVC(client kubernetes.Interface, logger logr.Logger } func finalizeRedisSentinelPVC(cr *redisv1beta2.RedisSentinel) error { - return nil } diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go index f99a021df..a20ab6362 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizers_test.go @@ -5,8 +5,6 @@ import ( "fmt" "testing" - // "time" - "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr/testr" "github.com/stretchr/testify/assert" @@ -14,12 +12,10 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - // "k8s.io/apimachinery/pkg/types" // utilruntime "k8s.io/apimachinery/pkg/util/runtime" k8sClientFake "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/pointer" - // ctrlClientFake "sigs.k8s.io/controller-runtime/pkg/client/fake" ) // func TestHandleRedisFinalizer(t *testing.T) { diff --git a/k8sutils/labels.go b/k8sutils/labels.go index 4d0d4518d..da3960870 100644 --- a/k8sutils/labels.go +++ b/k8sutils/labels.go @@ -39,7 +39,7 @@ func AddOwnerRefToObject(obj metav1.Object, ownerRef metav1.OwnerReference) { obj.SetOwnerReferences(append(obj.GetOwnerReferences(), ownerRef)) } -// redisAsOwner generates and returns object refernece +// redisAsOwner generates and returns object reference func redisAsOwner(cr *redisv1beta2.Redis) metav1.OwnerReference { trueVar := true return metav1.OwnerReference{ @@ -51,7 +51,7 @@ func redisAsOwner(cr *redisv1beta2.Redis) metav1.OwnerReference { } } -// redisClusterAsOwner generates and returns object refernece +// redisClusterAsOwner generates and returns object reference func redisClusterAsOwner(cr *redisv1beta2.RedisCluster) metav1.OwnerReference { trueVar := true return metav1.OwnerReference{ @@ -63,7 +63,7 @@ func redisClusterAsOwner(cr *redisv1beta2.RedisCluster) metav1.OwnerReference { } } -// redisReplicationAsOwner generates and returns object refernece +// redisReplicationAsOwner generates and returns object reference func redisReplicationAsOwner(cr *redisv1beta2.RedisReplication) metav1.OwnerReference { trueVar := true return metav1.OwnerReference{ @@ -75,7 +75,7 @@ func redisReplicationAsOwner(cr *redisv1beta2.RedisReplication) metav1.OwnerRefe } } -// RedisSentinelAsOwner generates and returns object refernece +// RedisSentinelAsOwner generates and returns object reference func redisSentinelAsOwner(cr *redisv1beta2.RedisSentinel) metav1.OwnerReference { trueVar := true return metav1.OwnerReference{ diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go index 274f9c1a0..3331a1784 100644 --- a/k8sutils/labels_test.go +++ b/k8sutils/labels_test.go @@ -48,7 +48,8 @@ func Test_generateObjectMetaInformation(t *testing.T) { name: "test", namespace: "default", labels: map[string]string{"test": "test"}, - annotations: map[string]string{"test": "test"}}, + annotations: map[string]string{"test": "test"}, + }, want: metav1.ObjectMeta{ Name: "test", Namespace: "default", diff --git a/k8sutils/poddisruption.go b/k8sutils/poddisruption.go index 77412673f..4561b8cc9 100644 --- a/k8sutils/poddisruption.go +++ b/k8sutils/poddisruption.go @@ -76,14 +76,14 @@ func generatePodDisruptionBudgetDef(cr *redisv1beta2.RedisCluster, role string, }, } if pdbParams.MinAvailable != nil { - pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: int32(*pdbParams.MinAvailable)} + pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: (*pdbParams.MinAvailable)} } if pdbParams.MaxUnavailable != nil { - pdbTemplate.Spec.MaxUnavailable = &intstr.IntOrString{Type: intstr.Int, IntVal: int32(*pdbParams.MaxUnavailable)} + pdbTemplate.Spec.MaxUnavailable = &intstr.IntOrString{Type: intstr.Int, IntVal: *pdbParams.MaxUnavailable} } // If we don't have a value for either, assume quorum: (N/2)+1 if pdbTemplate.Spec.MaxUnavailable == nil && pdbTemplate.Spec.MinAvailable == nil { - pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: int32((*cr.Spec.Size / 2) + 1)} + pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: (*cr.Spec.Size / 2) + 1} } AddOwnerRefToObject(pdbTemplate, redisClusterAsOwner(cr)) return pdbTemplate @@ -103,14 +103,14 @@ func generateSentinelPodDisruptionBudgetDef(cr *redisv1beta2.RedisSentinel, role }, } if pdbParams.MinAvailable != nil { - pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: int32(*pdbParams.MinAvailable)} + pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: *pdbParams.MinAvailable} } if pdbParams.MaxUnavailable != nil { - pdbTemplate.Spec.MaxUnavailable = &intstr.IntOrString{Type: intstr.Int, IntVal: int32(*pdbParams.MaxUnavailable)} + pdbTemplate.Spec.MaxUnavailable = &intstr.IntOrString{Type: intstr.Int, IntVal: *pdbParams.MaxUnavailable} } // If we don't have a value for either, assume quorum: (N/2)+1 if pdbTemplate.Spec.MaxUnavailable == nil && pdbTemplate.Spec.MinAvailable == nil { - pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: int32((*cr.Spec.Size / 2) + 1)} + pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{Type: intstr.Int, IntVal: (*cr.Spec.Size / 2) + 1} } AddOwnerRefToObject(pdbTemplate, redisSentinelAsOwner(cr)) return pdbTemplate diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index ae6a26247..273158be5 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -5,13 +5,12 @@ import ( "strconv" "strings" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/client-go/kubernetes" - commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" ) @@ -96,7 +95,6 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init if cr.Spec.Storage != nil { initcontainerProp.PersistenceEnabled = &trueProperty } - } return initcontainerProp diff --git a/k8sutils/redis-cluster_test.go b/k8sutils/redis-cluster_test.go index bdaac7a61..3774a0889 100644 --- a/k8sutils/redis-cluster_test.go +++ b/k8sutils/redis-cluster_test.go @@ -5,14 +5,13 @@ import ( "path/filepath" "testing" - "k8s.io/client-go/kubernetes/fake" - common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/pointer" ) diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 81803b10a..5fa84f53e 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -143,11 +143,9 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) if cr.Spec.RedisExporter.Resources != nil { containerProp.RedisExporterResources = cr.Spec.RedisExporter.Resources } - if cr.Spec.RedisExporter.EnvVars != nil { containerProp.RedisExporterEnv = cr.Spec.RedisExporter.EnvVars } - } if cr.Spec.ReadinessProbe != nil { containerProp.ReadinessProbe = &cr.Spec.ReadinessProbe.Probe @@ -193,8 +191,6 @@ func generateRedisReplicationInitContainerParams(cr *redisv1beta2.RedisReplicati if cr.Spec.Storage != nil { initcontainerProp.PersistenceEnabled = &trueProperty } - } - return initcontainerProp } diff --git a/k8sutils/redis-replication_test.go b/k8sutils/redis-replication_test.go index 509f863e7..57765acba 100644 --- a/k8sutils/redis-replication_test.go +++ b/k8sutils/redis-replication_test.go @@ -21,7 +21,8 @@ func Test_generateRedisReplicationParams(t *testing.T) { ClusterMode: false, NodeConfVolume: false, NodeSelector: map[string]string{ - "node-role.kubernetes.io/infra": "worker"}, + "node-role.kubernetes.io/infra": "worker", + }, PodSecurityContext: &corev1.PodSecurityContext{ RunAsUser: pointer.Int64(1000), FSGroup: pointer.Int64(1000), diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 698a19980..ad0c754b6 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -5,17 +5,16 @@ import ( "encoding/json" "errors" - "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" - "k8s.io/utils/pointer" - commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" + "k8s.io/utils/pointer" ) // RedisSentinelSTS is a interface to call Redis Statefulset function @@ -52,12 +51,10 @@ func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logge } return prop.CreateRedisSentinelSetup(ctx, client, logger, cr, cl, dcl) - } // Create RedisSentinel Service func CreateRedisSentinelService(cr *redisv1beta2.RedisSentinel, cl kubernetes.Interface) error { - prop := RedisSentinelService{ RedisServiceRole: "sentinel", } @@ -80,7 +77,6 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cl cr.Spec.Sidecars, cl, ) - if err != nil { logger.Error(err, "Cannot create Sentinel statefulset for Redis") return err @@ -90,7 +86,6 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cl // Create Redis Sentile Params for the statefulset func generateRedisSentinelParams(cr *redisv1beta2.RedisSentinel, replicas int32, externalConfig *string, affinity *corev1.Affinity) statefulSetParameters { - res := statefulSetParameters{ Replicas: &replicas, ClusterMode: false, @@ -123,7 +118,6 @@ func generateRedisSentinelParams(cr *redisv1beta2.RedisSentinel, replicas int32, // generateRedisSentinelInitContainerParams generates Redis sentinel initcontainer information func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) initContainerParameters { - initcontainerProp := initContainerParameters{} if cr.Spec.InitContainer != nil { @@ -139,9 +133,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in Command: initContainer.Command, Arguments: initContainer.Args, } - } - return initcontainerProp } @@ -190,7 +182,6 @@ func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes } return containerProp - } // Get the Count of the Sentinel @@ -243,7 +234,6 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. return err } return nil - } func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) *[]corev1.EnvVar { @@ -289,7 +279,6 @@ func getSentinelEnvVariable(ctx context.Context, client kubernetes.Interface, lo }) } return envVar - } func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, dcl dynamic.Interface) string { diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index 85260d5b1..98cee4ee9 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -7,9 +7,6 @@ import ( "reflect" "testing" - "k8s.io/client-go/dynamic/fake" - "k8s.io/client-go/kubernetes" - common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" @@ -18,6 +15,8 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/yaml" + "k8s.io/client-go/dynamic/fake" + "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" ) @@ -28,7 +27,8 @@ func Test_generateRedisSentinelParams(t *testing.T) { ClusterMode: false, NodeConfVolume: false, NodeSelector: map[string]string{ - "node-role.kubernetes.io/infra": "worker"}, + "node-role.kubernetes.io/infra": "worker", + }, PodSecurityContext: &corev1.PodSecurityContext{ RunAsUser: pointer.Int64(1000), FSGroup: pointer.Int64(1000), @@ -254,7 +254,6 @@ func Test_generateRedisSentinelInitContainerParams(t *testing.T) { func Test_getSentinelEnvVariable(t *testing.T) { type args struct { - ctx context.Context client kubernetes.Interface logger logr.Logger cr *redisv1beta2.RedisSentinel @@ -267,7 +266,6 @@ func Test_getSentinelEnvVariable(t *testing.T) { { name: "When RedisSentinelConfig is nil", args: args{ - ctx: context.TODO(), client: nil, logger: logr.Logger{}, cr: &redisv1beta2.RedisSentinel{}, @@ -277,7 +275,6 @@ func Test_getSentinelEnvVariable(t *testing.T) { { name: "When RedisSentinelConfig is not nil", args: args{ - ctx: context.TODO(), client: nil, logger: logr.Logger{}, cr: &redisv1beta2.RedisSentinel{ @@ -329,7 +326,8 @@ func Test_getSentinelEnvVariable(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := getSentinelEnvVariable(tt.args.ctx, tt.args.client, tt.args.logger, tt.args.cr, fake.NewSimpleDynamicClient(&runtime.Scheme{})); !reflect.DeepEqual(got, tt.want) { + ctx := context.TODO() + if got := getSentinelEnvVariable(ctx, tt.args.client, tt.args.logger, tt.args.cr, fake.NewSimpleDynamicClient(&runtime.Scheme{})); !reflect.DeepEqual(got, tt.want) { t.Errorf("getSentinelEnvVariable() = %v, want %v", got, tt.want) } }) diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index c47e6a934..a99a45b92 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -103,7 +103,6 @@ func generateRedisStandaloneParams(cr *redisv1beta2.Redis) statefulSetParameters } if cr.Spec.RedisExporter != nil { res.EnableMetrics = cr.Spec.RedisExporter.Enabled - } if cr.Spec.ServiceAccountName != nil { res.ServiceAccountName = cr.Spec.ServiceAccountName @@ -153,7 +152,6 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar if cr.Spec.RedisExporter.EnvVars != nil { containerProp.RedisExporterEnv = cr.Spec.RedisExporter.EnvVars } - } if cr.Spec.ReadinessProbe != nil { containerProp.ReadinessProbe = &cr.Spec.ReadinessProbe.Probe @@ -199,8 +197,6 @@ func generateRedisStandaloneInitContainerParams(cr *redisv1beta2.Redis) initCont if cr.Spec.Storage != nil { initcontainerProp.PersistenceEnabled = &trueProperty } - } - return initcontainerProp } diff --git a/k8sutils/redis-standalone_test.go b/k8sutils/redis-standalone_test.go index 81d13e537..e7eebe882 100644 --- a/k8sutils/redis-standalone_test.go +++ b/k8sutils/redis-standalone_test.go @@ -29,7 +29,8 @@ func Test_generateRedisStandaloneParams(t *testing.T) { // "opstreelabs.in.redis": "true"}, // }, NodeSelector: map[string]string{ - "node-role.kubernetes.io/infra": "worker"}, + "node-role.kubernetes.io/infra": "worker", + }, PodSecurityContext: &corev1.PodSecurityContext{ RunAsUser: pointer.Int64(1000), FSGroup: pointer.Int64(1000), diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 221917c13..ddca1b8ed 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -182,7 +182,7 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter Namespace: cr.Namespace, } leaderPod := RedisDetails{ - PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(int(followerIdx)%int(leaderCounts)), + PodName: cr.ObjectMeta.Name + "-leader-" + strconv.Itoa((followerIdx)%int(leaderCounts)), Namespace: cr.Namespace, } podIP = getRedisServerIP(client, logger, followerPod) @@ -486,7 +486,6 @@ func GetRedisNodesByRole(ctx context.Context, cl kubernetes.Interface, logger lo replicas := cr.Spec.GetReplicationCounts("replication") for i := 0; i < int(replicas); i++ { - podName := statefulset.Name + "-" + strconv.Itoa(i) podRole := checkRedisServerRole(ctx, cl, logger, cr, podName) if podRole == redisRole { @@ -542,11 +541,8 @@ func checkAttachedSlave(ctx context.Context, client kubernetes.Interface, logger if nums > 0 { return podName } - } - return "" - } func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { @@ -568,7 +564,6 @@ func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interfa for i := 0; i < len(masterPods); i++ { if masterPods[i] != realMasterPod { - redisClient := configureRedisReplicationClient(client, logger, cr, masterPods[i]) defer redisClient.Close() logger.V(1).Info("Setting the", "pod", masterPods[i], "to slave of", realMasterPod) diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 8dacd2032..14c0b2717 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -24,7 +24,7 @@ func TestCheckRedisNodePresence(t *testing.T) { csvOutput.FieldsPerRecord = -1 nodes, _ := csvOutput.ReadAll() - var tests = []struct { + tests := []struct { nodes [][]string ip string want bool diff --git a/k8sutils/services.go b/k8sutils/services.go index 353e68f58..94e93c00c 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -19,9 +19,7 @@ const ( redisExporterPortName = "redis-exporter" ) -var ( - serviceType corev1.ServiceType -) +var serviceType corev1.ServiceType // exporterPortProvider return the exporter port if bool is true type exporterPortProvider func() (port int, enable bool) @@ -49,7 +47,7 @@ func generateServiceDef(serviceMeta metav1.ObjectMeta, epp exporterPortProvider, { Name: PortName, Port: int32(port), - TargetPort: intstr.FromInt(int(port)), + TargetPort: intstr.FromInt(port), Protocol: corev1.ProtocolTCP, }, }, diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 67f394a6e..b732a3afc 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -8,13 +8,9 @@ import ( "strconv" "strings" - "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" - "k8s.io/client-go/kubernetes" - "k8s.io/utils/env" - "k8s.io/utils/pointer" - commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "github.com/banzaicloud/k8s-objectmatcher/patch" "github.com/go-logr/logr" "github.com/pkg/errors" @@ -24,6 +20,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/kubernetes" + "k8s.io/utils/env" + "k8s.io/utils/pointer" ) const ( @@ -169,12 +168,13 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St } updateFailed := false realUpdate := false - for _, pvc := range pvcs.Items { + for i := range pvcs.Items { + pvc := &pvcs.Items[i] realCapacity := pvc.Spec.Resources.Requests.Storage().Value() if realCapacity != stateCapacity { realUpdate = true pvc.Spec.Resources.Requests = newStateful.Spec.VolumeClaimTemplates[0].Spec.Resources.Requests - _, err = cl.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).Update(context.Background(), &pvc, metav1.UpdateOptions{}) + _, err = cl.CoreV1().PersistentVolumeClaims(storedStateful.Namespace).Update(context.Background(), pvc, metav1.UpdateOptions{}) if err != nil { if !updateFailed { updateFailed = true @@ -183,6 +183,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St } } } + if !updateFailed && len(pvcs.Items) != 0 { annotations["storageCapacity"] = fmt.Sprintf("%d", stateCapacity) storedStateful.Annotations = annotations @@ -612,7 +613,8 @@ func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { // getEnvironmentVariables returns all the required Environment Variables func getEnvironmentVariables(role string, enabledPassword *bool, secretName *string, secretKey *string, persistenceEnabled *bool, tlsConfig *redisv1beta2.TLSConfig, - aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar, port *int, clusterVersion *string) []corev1.EnvVar { + aclConfig *redisv1beta2.ACLConfig, envVar *[]corev1.EnvVar, port *int, clusterVersion *string, +) []corev1.EnvVar { envVars := []corev1.EnvVar{ {Name: "SERVER_MODE", Value: role}, {Name: "SETUP_MODE", Value: role}, diff --git a/main.go b/main.go index 5f552bb35..0111770e5 100644 --- a/main.go +++ b/main.go @@ -20,26 +20,20 @@ import ( "flag" "os" - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - + redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/controllers" + "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + _ "k8s.io/client-go/plugin/pkg/client/auth" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - - redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" - "github.com/OT-CONTAINER-KIT/redis-operator/controllers" - "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" - - redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" - // +kubebuilder:scaffold:imports ) var ( @@ -47,6 +41,7 @@ var ( setupLog = ctrl.Log.WithName("setup") ) +//nolint:gochecknoinits func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) diff --git a/mocks/utils/utils.go b/mocks/utils/utils.go index 6f9c33b99..9c58952fc 100644 --- a/mocks/utils/utils.go +++ b/mocks/utils/utils.go @@ -66,7 +66,7 @@ func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { func CreateFakeClientWithSecrets(cr *redisv1beta2.RedisCluster, secretName, secretKey, secretValue string) *fake.Clientset { leaderReplicas := cr.Spec.GetReplicaCounts("leader") followerReplicas := cr.Spec.GetReplicaCounts("follower") - pods := make([]runtime.Object, leaderReplicas+followerReplicas) + pods := make([]runtime.Object, 0) for i := 0; i < int(leaderReplicas); i++ { podName := cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(i) From 45dfa17a84a1ea60685eeedba35db4823fa919bc Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:21:25 +0530 Subject: [PATCH 103/203] test: test for acl user (#797) * test: test for acl user Signed-off-by: Shubham Gupta * ci: add to ci Signed-off-by: Shubham Gupta * style: remove trailing space Signed-off-by: Shubham Gupta * test: fix uri scheme Signed-off-by: Shubham Gupta * ci: test on all Signed-off-by: Shubham Gupta * test: fix typo Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 7 +- .github/workflows/e2e.yaml | 6 +- tests/_config/chainsaw-configuration.yaml | 4 +- .../acl-user/redis-cluster/acl-secret.yaml | 11 + .../acl-user/redis-cluster/chainsaw-test.yaml | 137 ++++++++++++ .../acl-user/redis-cluster/cluster.yaml | 50 +++++ .../acl-user/redis-cluster/ready-cluster.yaml | 7 + .../acl-user/redis-cluster/ready-pvc.yaml | 181 ++++++++++++++++ .../acl-user/redis-cluster/ready-sts.yaml | 25 +++ .../acl-user/redis-cluster/ready-svc.yaml | 201 ++++++++++++++++++ 10 files changed, 621 insertions(+), 8 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index 653233432..946039c79 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -23,6 +23,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/nodeport/ - ./tests/e2e-chainsaw/v1beta2/pvc-name/ - ./tests/e2e-chainsaw/v1beta2/keep-pvc/ + - ./tests/e2e-chainsaw/v1beta2/acl-user/ steps: - name: Checkout code @@ -38,7 +39,7 @@ jobs: - name: Check install run: chainsaw version - + - name: Install kubectl run: | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" @@ -55,7 +56,7 @@ jobs: cluster_name: kind - name: Load Docker image into Kind - run: | + run: | kubectl cluster-info --context kind-kind kind load docker-image redis-operator:e2e --name kind @@ -66,6 +67,6 @@ jobs: - name: Wait for Redis Operator to be ready run: | kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system - + - name: Run chainsaw test run: chainsaw test --test-dir ${{ matrix.testpath }} --config tests/_config/chainsaw-configuration.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index c9c271f0a..1d8fc2a6d 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -32,7 +32,7 @@ jobs: run: | curl -L https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64 -o /usr/local/bin/kuttl chmod +x /usr/local/bin/kuttl - + - name: Install kubectl run: | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" @@ -46,7 +46,7 @@ jobs: cluster_name: kind - name: Load Docker image into Kind - run: | + run: | kubectl cluster-info --context kind-kind kind load docker-image redis-operator:e2e --name kind @@ -57,6 +57,6 @@ jobs: - name: Wait for Redis Operator to be ready run: | kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system - + - name: Run kuttl test run: kuttl test ${{ matrix.testpath }} --config tests/_config/kuttl-test.yaml diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml index 3e2daf4bb..2259297c9 100644 --- a/tests/_config/chainsaw-configuration.yaml +++ b/tests/_config/chainsaw-configuration.yaml @@ -3,8 +3,8 @@ apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Configuration metadata: - name: chainsaw-configuration -spec: + name: chainsaw-configuration +spec: delayBeforeCleanup: 10s timeouts: apply: 5m diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml new file mode 100644 index 000000000..675db6f1c --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: acl-secret +type: Opaque +stringData: + # yamllint disable-line rule:line-length + user.acl: | + user opstree on ~* &* +@all >abc@123 + user buildpiper on ~* &* +@all >abc@123 diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..46bf2141c --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,137 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-setup +spec: + steps: + - try: + - apply: + file: acl-secret.yaml + - assert: + resource: + apiVersion: v1 + kind: Secret + metadata: + name: acl-secret + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Cluster Nodes + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Check Cluster Slots Coverage + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + + - name: Try saving a key With Password + try: + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-5 bar-5 + check: + ($stdout=='OK'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml new file mode 100644 index 000000000..6c231d87b --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml @@ -0,0 +1,50 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + acl: + secret: + secretName: acl-secret + redisExporter: + enabled: true + image: quay.io/opstree/redis-exporter:v1.44.0 + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 100m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..49e754e81 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml @@ -0,0 +1,7 @@ +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml new file mode 100644 index 000000000..a89bfa22a --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml @@ -0,0 +1,181 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: node-conf-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + accessModes: + - ReadWriteOnce + capacity: + storage: 1Gi + phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml new file mode 100644 index 000000000..1053eb784 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-leader + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader +status: + replicas: 3 + readyReplicas: 3 + +--- + +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: redis-cluster-v1beta2-follower + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower +status: + replicas: 3 + readyReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml new file mode 100644 index 000000000..e8af234a6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml @@ -0,0 +1,201 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + name: redis-cluster-v1beta2-leader-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-leader + redis_setup_type: cluster + role: leader + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + - name: redis-exporter + port: 9121 + protocol: TCP + targetPort: 9121 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-additional + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "9121" + prometheus.io/scrape: "true" + redis.opstreelabs.in: "true" + redis.opstreelabs.instance: redis-cluster-v1beta2 + labels: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + name: redis-cluster-v1beta2-follower-headless + ownerReferences: + - apiVersion: redis.redis.opstreelabs.in/v1beta2 + controller: true + kind: RedisCluster + name: redis-cluster-v1beta2 +spec: + clusterIP: None + ports: + - name: redis-client + port: 6379 + protocol: TCP + targetPort: 6379 + selector: + app: redis-cluster-v1beta2-follower + redis_setup_type: cluster + role: follower + type: ClusterIP +status: + loadBalancer: {} \ No newline at end of file From dd8318bba59adb938541ba79895954979e3dec94 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Tue, 5 Mar 2024 01:39:18 +0530 Subject: [PATCH 104/203] test: Remove Duplicate Kuttl Test (#798) * test: remove kuttl hostnetwork test Signed-off-by: Shubham Gupta * ci: remove kutll hostnetwork Signed-off-by: Shubham Gupta * test: Add chainsaw redis-standalone teardown Signed-off-by: Shubham Gupta * test: Add yaml language server Signed-off-by: Shubham Gupta * test: Add chainsaw redis-replication teardown Signed-off-by: Shubham Gupta * ci: Drop teardown kuttl test Signed-off-by: Shubham Gupta * test: Add chainsaw redis-sentinel teardown Signed-off-by: Shubham Gupta * ci: Drop setup kuttl test Signed-off-by: Shubham Gupta * test: fix typo in chainsaw redis-replication teardown Signed-off-by: Shubham Gupta * test: Add cluster scaling test Signed-off-by: Shubham Gupta * ci: Add cluster scaling Signed-off-by: Shubham Gupta * test: test for acl user (#797) * test: test for acl user Signed-off-by: Shubham Gupta * ci: add to ci Signed-off-by: Shubham Gupta * style: remove trailing space Signed-off-by: Shubham Gupta * test: fix uri scheme Signed-off-by: Shubham Gupta * ci: test on all Signed-off-by: Shubham Gupta * test: fix typo Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta * ci: Add cluster scaling Signed-off-by: Shubham Gupta * test: remove kuttl test Signed-off-by: Shubham Gupta * test: Add chainasw ignore annots Signed-off-by: Shubham Gupta * ci: add ignore annots Signed-off-by: Shubham Gupta * ci: mutiple runs Signed-off-by: Shubham Gupta * ci: fix failure Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 2 + .github/workflows/e2e.yaml | 9 +- .../redis-cluster/chainsaw-test.yaml | 20 ++ .../ignore-annots/redis-cluster/cluster.yaml | 0 .../redis-cluster/ignore-annots-sts.yaml | 0 .../redis-cluster/ready-cluster.yaml | 0 .../redis-cluster/ready-pvc.yaml | 0 .../redis-cluster/ready-sts.yaml | 0 .../redis-standalone/chainsaw-test.yaml | 20 ++ .../redis-standalone/ignore-annots-sts.yaml | 0 .../redis-standalone/ready-pvc.yaml | 0 .../redis-standalone/ready-standalone.yaml | 0 .../redis-standalone/ready-sts.yaml | 0 .../redis-standalone/standalone.yaml | 0 .../scaling/redis-cluster/chainsaw-test.yaml | 227 ++++++++++++++++++ .../redis-cluster/cluster-scale-up.yaml | 0 .../scaling/redis-cluster/cluster.yaml | 0 .../redis-cluster/ready-cluster-scale-up.yaml | 0 .../scaling/redis-cluster/ready-cluster.yaml | 0 .../redis-cluster/ready-sts-scale-up.yaml | 0 .../scaling}/redis-cluster/ready-sts.yaml | 0 .../redis-replication/chainsaw-test.yaml | 34 +++ .../redis-replication/ready-pvc.yaml | 0 .../redis-replication/ready-sts.yaml | 0 .../redis-replication/ready-svc.yaml | 0 .../redis-replication/replication.yaml | 2 +- .../redis-sentinel/chainsaw-test.yaml | 31 +++ .../teardown}/redis-sentinel/ready-sts.yaml | 0 .../teardown}/redis-sentinel/ready-svc.yaml | 0 .../teardown}/redis-sentinel/sentinel.yaml | 0 .../redis-standalone/chainsaw-test.yaml | 32 +++ .../teardown/redis-standalone/ready-pvc.yaml | 2 +- .../teardown}/redis-standalone/ready-sts.yaml | 0 .../teardown}/redis-standalone/ready-svc.yaml | 0 .../redis-standalone/standalone.yaml | 0 .../hostnetwork/redis-cluster/00-install.yaml | 10 - .../hostnetwork/redis-cluster/cluster.yaml | 49 ---- .../redis-cluster/ready-cluster.yaml | 7 - .../hostnetwork/redis-cluster/ready-pod.yaml | 167 ------------- .../hostnetwork/redis-cluster/ready-svc.yaml | 201 ---------------- .../redis-cluster/00-install.yaml | 10 - .../redis-cluster/ready-pvc.yaml | 181 -------------- .../redis-standalone/00-install.yaml | 10 - .../scaling/redis-cluster/00-install.yaml | 7 - .../scaling/redis-cluster/01-scale-up.yaml | 7 - .../scaling/redis-cluster/02-scale-down.yaml | 7 - .../scaling/redis-cluster/ready-sts.yaml | 25 -- .../setup/redis-cluster/00-install.yaml | 9 - .../v1beta2/setup/redis-cluster/cluster.yaml | 47 ---- .../setup/redis-cluster/ready-cluster.yaml | 7 - .../setup/redis-cluster/ready-pvc.yaml | 181 -------------- .../setup/redis-cluster/ready-sts.yaml | 25 -- .../setup/redis-cluster/ready-svc.yaml | 201 ---------------- .../setup/redis-replication/00-install.yaml | 8 - .../setup/redis-sentinel/00-install.yaml | 7 - .../setup/redis-standalone/00-install.yaml | 9 - .../setup/redis-standalone/ready-pvc.yaml | 14 -- .../teardown/redis-cluster/00-install.yaml | 9 - .../teardown/redis-cluster/01-uninstall.yaml | 10 - .../teardown/redis-cluster/cluster.yaml | 47 ---- .../teardown/redis-cluster/ready-cluster.yaml | 7 - .../teardown/redis-cluster/ready-pvc.yaml | 181 -------------- .../teardown/redis-cluster/ready-sts.yaml | 25 -- .../teardown/redis-cluster/ready-svc.yaml | 201 ---------------- .../redis-replication/00-install.yaml | 8 - .../redis-replication/01-uninstall.yaml | 9 - .../teardown/redis-replication/ready-pvc.yaml | 44 ---- .../teardown/redis-replication/ready-sts.yaml | 19 -- .../teardown/redis-replication/ready-svc.yaml | 90 ------- .../redis-replication/replication.yaml | 38 --- .../teardown/redis-sentinel/00-install.yaml | 7 - .../teardown/redis-sentinel/01-uninstall.yaml | 8 - .../teardown/redis-sentinel/ready-sts.yaml | 35 --- .../teardown/redis-sentinel/ready-svc.yaml | 96 -------- .../teardown/redis-sentinel/sentinel.yaml | 22 -- .../teardown/redis-standalone/00-install.yaml | 9 - .../redis-standalone/01-uninstall.yaml | 9 - .../teardown/redis-standalone/ready-sts.yaml | 11 - .../teardown/redis-standalone/ready-svc.yaml | 96 -------- .../teardown/redis-standalone/standalone.yaml | 26 -- 80 files changed, 370 insertions(+), 2205 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-cluster/cluster.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml (100%) rename tests/{e2e/v1beta2/hostnetwork => e2e-chainsaw/v1beta2/ignore-annots}/redis-cluster/ready-pvc.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml (100%) create mode 100644 tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/ignore-annots/redis-standalone/standalone.yaml (100%) create mode 100644 tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml rename tests/{e2e => e2e-chainsaw}/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/scaling/redis-cluster/cluster.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/scaling/redis-cluster/ready-cluster.yaml (100%) rename tests/{e2e => e2e-chainsaw}/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml (100%) rename tests/{e2e/v1beta2/hostnetwork => e2e-chainsaw/v1beta2/scaling}/redis-cluster/ready-sts.yaml (100%) create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-replication/ready-pvc.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-replication/ready-sts.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-replication/ready-svc.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-replication/replication.yaml (96%) create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-sentinel/ready-sts.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-sentinel/ready-svc.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-sentinel/sentinel.yaml (100%) create mode 100644 tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml rename tests/{e2e => e2e-chainsaw}/v1beta2/teardown/redis-standalone/ready-pvc.yaml (93%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-standalone/ready-sts.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-standalone/ready-svc.yaml (100%) rename tests/{e2e/v1beta2/setup => e2e-chainsaw/v1beta2/teardown}/redis-standalone/standalone.yaml (100%) delete mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml delete mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml delete mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml delete mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml delete mode 100644 tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml delete mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml delete mode 100644 tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml delete mode 100644 tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml delete mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml delete mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml delete mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml delete mode 100644 tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-replication/00-install.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml delete mode 100644 tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-replication/replication.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml delete mode 100644 tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index 946039c79..6b0b7a8a0 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -24,6 +24,8 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/pvc-name/ - ./tests/e2e-chainsaw/v1beta2/keep-pvc/ - ./tests/e2e-chainsaw/v1beta2/acl-user/ + - ./tests/e2e-chainsaw/v1beta2/scaling/ + - ./tests/e2e-chainsaw/v1beta2/ignore-annots/ steps: - name: Checkout code diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 1d8fc2a6d..db749ea61 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -1,4 +1,4 @@ -name: E2E tests +name: E2E Kuttl tests on: pull_request: @@ -14,12 +14,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - testpath: - - ./tests/e2e/v1beta2/setup - - ./tests/e2e/v1beta2/teardown - - ./tests/e2e/v1beta2/ignore-annots - - ./tests/e2e/v1beta2/scaling - - ./tests/e2e/v1beta2/hostnetwork + testpath: [] steps: - name: Checkout code diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..f78603de4 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,20 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-ignore-annots +spec: + steps: + - name: Setup Redis Cluster + try: + - create: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-pvc.yaml + - error: + file: ignore-annots-sts.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/cluster.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-cluster/cluster.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/cluster.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml similarity index 100% rename from tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml new file mode 100644 index 000000000..338c32525 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml @@ -0,0 +1,20 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-ignore-annots +spec: + steps: + - name: Setup Redis Standalone + try: + - create: + file: standalone.yaml + - assert: + file: ready-standalone.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-pvc.yaml + - error: + file: ignore-annots-sts.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/standalone.yaml similarity index 100% rename from tests/e2e/v1beta2/ignore-annots/redis-standalone/standalone.yaml rename to tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/standalone.yaml diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..85aa0cb3d --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,227 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster-setup +spec: + steps: + - name: Create Redis Cluster + try: + - create: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Cluster Nodes + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Check Cluster Slots + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + + - name: Scale Redis Cluster + try: + - apply: + file: cluster-scale-up.yaml + - assert: + file: ready-cluster-scale-up.yaml + - assert: + file: ready-sts-scale-up.yaml + + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + + - name: Ping Scaled Cluster Nodes + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + + - name: Check Scaled Cluster Slots + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml similarity index 100% rename from tests/e2e/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster.yaml similarity index 100% rename from tests/e2e/v1beta2/scaling/redis-cluster/cluster.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster.yaml diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml similarity index 100% rename from tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml similarity index 100% rename from tests/e2e/v1beta2/scaling/redis-cluster/ready-cluster.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml similarity index 100% rename from tests/e2e/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml new file mode 100644 index 000000000..e040a64d2 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-replication-teardown +spec: + steps: + - name: redis-replication-install + description: Install Redis Replication + try: + - apply: + file: replication.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: redis-replication-uninstall + description: Uninstall Redis Replication + try: + - delete: + ref: + name: redis-replication + kind: RedisReplication + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - error: + file: ready-pvc.yaml diff --git a/tests/e2e/v1beta2/setup/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-pvc.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-replication/ready-pvc.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-pvc.yaml diff --git a/tests/e2e/v1beta2/setup/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-replication/ready-sts.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-sts.yaml diff --git a/tests/e2e/v1beta2/setup/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-svc.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-replication/ready-svc.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-svc.yaml diff --git a/tests/e2e/v1beta2/setup/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml similarity index 96% rename from tests/e2e/v1beta2/setup/redis-replication/replication.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml index 8e4ba0705..7c85e8e03 100644 --- a/tests/e2e/v1beta2/setup/redis-replication/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml @@ -2,7 +2,7 @@ apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisReplication metadata: - name: redis-replication + name: redis-replication spec: clusterSize: 3 podSecurityContext: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml new file mode 100644 index 000000000..163731940 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml @@ -0,0 +1,31 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-sentinel-teardown +spec: + steps: + - name: redis-sentinel-install + description: Install Redis Sentinel + try: + - apply: + file: sentinel.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + + - name: redis-sentinel-uninstall + description: Uninstall Redis Sentinel + try: + - delete: + ref: + name: redis-sentinel + kind: RedisSentinel + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-sentinel/ready-sts.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-sts.yaml diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-svc.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-sentinel/ready-svc.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-svc.yaml diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-sentinel/sentinel.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml new file mode 100644 index 000000000..1300c14c6 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json + +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-standalone-teardown +spec: + steps: + - name: redis-standalone-install + try: + - apply: + file: standalone.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + + - name: redis-standalone-uninstall + try: + - delete: + ref: + name: redis-standalone-v1beta2 + kind: Redis + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - error: + file: ready-pvc.yaml diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml similarity index 93% rename from tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml index 777fa3656..5649e1c3b 100644 --- a/tests/e2e/v1beta2/teardown/redis-standalone/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml @@ -8,7 +8,7 @@ metadata: role: standalone status: accessModes: - - ReadWriteOnce + - ReadWriteOnce capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e/v1beta2/setup/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-sts.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-standalone/ready-sts.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-sts.yaml diff --git a/tests/e2e/v1beta2/setup/redis-standalone/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-svc.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-standalone/ready-svc.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-svc.yaml diff --git a/tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/standalone.yaml similarity index 100% rename from tests/e2e/v1beta2/setup/redis-standalone/standalone.yaml rename to tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/standalone.yaml diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml deleted file mode 100644 index 56b451984..000000000 --- a/tests/e2e/v1beta2/hostnetwork/redis-cluster/00-install.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - cluster.yaml -assert : - - ready-cluster.yaml - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml - - ready-pod.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml deleted file mode 100644 index afe493178..000000000 --- a/tests/e2e/v1beta2/hostnetwork/redis-cluster/cluster.yaml +++ /dev/null @@ -1,49 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta2 -spec: - hostNetwork: true - port: 6380 - clusterSize: 3 - clusterVersion: v6 # hostNetwork only works with v6 - persistenceEnabled: true - podSecurityContext: - runAsUser: 1000 - fsGroup: 1000 - kubernetesConfig: - image: quay.io/opstree/redis:latest - imagePullPolicy: Always - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisExporter: - enabled: true - image: quay.io/opstree/redis-exporter:v1.44.0 - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - storage: - volumeClaimTemplate: - spec: - # storageClassName: standard - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi - nodeConfVolume: true - nodeConfVolumeClaimTemplate: - spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml deleted file mode 100644 index 49e754e81..000000000 --- a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta2 -status: - readyFollowerReplicas: 3 - readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml deleted file mode 100644 index b26382e6d..000000000 --- a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml +++ /dev/null @@ -1,167 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - name: redis-cluster-v1beta2-leader-0 -spec: - containers: - - name: redis-cluster-v1beta2-leader - env: - - name: PERSISTENCE_ENABLED - value: "true" - - name: REDIS_ADDR - value: "redis://localhost:6379" - - name: REDIS_MAJOR_VERSION - value: "v6" - - name: REDIS_PORT - value: "6380" - - name: SERVER_MODE - value: "cluster" - - name: SETUP_MODE - value: "cluster" - - name: redis-exporter - hostNetwork: true -status: - phase: Running ---- -apiVersion: v1 -kind: Pod -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - name: redis-cluster-v1beta2-leader-1 -spec: - containers: - - name: redis-cluster-v1beta2-leader - env: - - name: PERSISTENCE_ENABLED - value: "true" - - name: REDIS_ADDR - value: "redis://localhost:6379" - - name: REDIS_MAJOR_VERSION - value: "v6" - - name: REDIS_PORT - value: "6380" - - name: SERVER_MODE - value: "cluster" - - name: SETUP_MODE - value: "cluster" - - name: redis-exporter - hostNetwork: true -status: - phase: Running ---- -apiVersion: v1 -kind: Pod -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - name: redis-cluster-v1beta2-leader-2 -spec: - containers: - - name: redis-cluster-v1beta2-leader - env: - - name: PERSISTENCE_ENABLED - value: "true" - - name: REDIS_ADDR - value: "redis://localhost:6379" - - name: REDIS_MAJOR_VERSION - value: "v6" - - name: REDIS_PORT - value: "6380" - - name: SERVER_MODE - value: "cluster" - - name: SETUP_MODE - value: "cluster" - - name: redis-exporter - hostNetwork: true -status: - phase: Running ---- -apiVersion: v1 -kind: Pod -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - name: redis-cluster-v1beta2-follower-0 -spec: - containers: - - name: redis-cluster-v1beta2-follower - env: - - name: PERSISTENCE_ENABLED - value: "true" - - name: REDIS_ADDR - value: "redis://localhost:6379" - - name: REDIS_MAJOR_VERSION - value: "v6" - - name: REDIS_PORT - value: "6380" - - name: SERVER_MODE - value: "cluster" - - name: SETUP_MODE - value: "cluster" - - name: redis-exporter - hostNetwork: true -status: - phase: Running ---- -apiVersion: v1 -kind: Pod -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - name: redis-cluster-v1beta2-follower-1 -spec: - containers: - - name: redis-cluster-v1beta2-follower - env: - - name: PERSISTENCE_ENABLED - value: "true" - - name: REDIS_ADDR - value: "redis://localhost:6379" - - name: REDIS_MAJOR_VERSION - value: "v6" - - name: REDIS_PORT - value: "6380" - - name: SERVER_MODE - value: "cluster" - - name: SETUP_MODE - value: "cluster" - - name: redis-exporter - hostNetwork: true -status: - phase: Running ---- -apiVersion: v1 -kind: Pod -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - name: redis-cluster-v1beta2-follower-2 -spec: - containers: - - name: redis-cluster-v1beta2-follower - env: - - name: PERSISTENCE_ENABLED - value: "true" - - name: REDIS_ADDR - value: "redis://localhost:6379" - - name: REDIS_MAJOR_VERSION - value: "v6" - - name: REDIS_PORT - value: "6380" - - name: SERVER_MODE - value: "cluster" - - name: SETUP_MODE - value: "cluster" - - name: redis-exporter - hostNetwork: true -status: - phase: Running \ No newline at end of file diff --git a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml b/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml deleted file mode 100644 index 7dd11eb37..000000000 --- a/tests/e2e/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml +++ /dev/null @@ -1,201 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6380 - protocol: TCP - targetPort: 6380 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6380 - protocol: TCP - targetPort: 6380 - - name: redis-exporter - port: 9121 - protocol: TCP - targetPort: 9121 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6380 - protocol: TCP - targetPort: 6380 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6380 - protocol: TCP - targetPort: 6380 - - name: redis-exporter - port: 9121 - protocol: TCP - targetPort: 9121 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6380 - protocol: TCP - targetPort: 6380 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6380 - protocol: TCP - targetPort: 6380 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml deleted file mode 100644 index 97d68615d..000000000 --- a/tests/e2e/v1beta2/ignore-annots/redis-cluster/00-install.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: - - cluster.yaml -assert: - - ready-cluster.yaml - - ready-sts.yaml - - ready-pvc.yaml -error: - - ignore-annots-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml deleted file mode 100644 index a89bfa22a..000000000 --- a/tests/e2e/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml +++ /dev/null @@ -1,181 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-0 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-1 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-0 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-1 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound - ---- - -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound diff --git a/tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml deleted file mode 100644 index 7c6267c56..000000000 --- a/tests/e2e/v1beta2/ignore-annots/redis-standalone/00-install.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: - - standalone.yaml -assert: - - ready-sts.yaml - - ready-pvc.yaml - - ready-standalone.yaml -error: - - ignore-annots-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml deleted file mode 100644 index 7529f3a78..000000000 --- a/tests/e2e/v1beta2/scaling/redis-cluster/00-install.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - cluster.yaml -assert : - - ready-cluster.yaml - - ready-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml deleted file mode 100644 index 7272499a2..000000000 --- a/tests/e2e/v1beta2/scaling/redis-cluster/01-scale-up.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - cluster-scale-up.yaml -assert : - - ready-cluster-scale-up.yaml - - ready-sts-scale-up.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml deleted file mode 100644 index 60d8821f1..000000000 --- a/tests/e2e/v1beta2/scaling/redis-cluster/02-scale-down.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - cluster.yaml -assert : - - ready-cluster.yaml - - ready-sts.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml b/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml deleted file mode 100644 index 1053eb784..000000000 --- a/tests/e2e/v1beta2/scaling/redis-cluster/ready-sts.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-leader - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - replicas: 3 - readyReplicas: 3 - ---- - -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-follower - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - replicas: 3 - readyReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml deleted file mode 100644 index a4d7ca849..000000000 --- a/tests/e2e/v1beta2/setup/redis-cluster/00-install.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - cluster.yaml -assert : - - ready-cluster.yaml - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml deleted file mode 100644 index ecf147104..000000000 --- a/tests/e2e/v1beta2/setup/redis-cluster/cluster.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta2 -spec: - clusterSize: 3 - clusterVersion: v7 - persistenceEnabled: true - podSecurityContext: - runAsUser: 1000 - fsGroup: 1000 - kubernetesConfig: - image: quay.io/opstree/redis:latest - imagePullPolicy: Always - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisExporter: - enabled: true - image: quay.io/opstree/redis-exporter:v1.44.0 - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - storage: - volumeClaimTemplate: - spec: - # storageClassName: standard - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi - nodeConfVolume: true - nodeConfVolumeClaimTemplate: - spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml deleted file mode 100644 index 49e754e81..000000000 --- a/tests/e2e/v1beta2/setup/redis-cluster/ready-cluster.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta2 -status: - readyFollowerReplicas: 3 - readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml deleted file mode 100644 index a89bfa22a..000000000 --- a/tests/e2e/v1beta2/setup/redis-cluster/ready-pvc.yaml +++ /dev/null @@ -1,181 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-0 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-1 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-0 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-1 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound - ---- - -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml deleted file mode 100644 index 1053eb784..000000000 --- a/tests/e2e/v1beta2/setup/redis-cluster/ready-sts.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-leader - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - replicas: 3 - readyReplicas: 3 - ---- - -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-follower - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - replicas: 3 - readyReplicas: 3 diff --git a/tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml b/tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml deleted file mode 100644 index e8af234a6..000000000 --- a/tests/e2e/v1beta2/setup/redis-cluster/ready-svc.yaml +++ /dev/null @@ -1,201 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - - name: redis-exporter - port: 9121 - protocol: TCP - targetPort: 9121 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - - name: redis-exporter - port: 9121 - protocol: TCP - targetPort: 9121 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-replication/00-install.yaml b/tests/e2e/v1beta2/setup/redis-replication/00-install.yaml deleted file mode 100644 index 19b92e39d..000000000 --- a/tests/e2e/v1beta2/setup/redis-replication/00-install.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: - - replication.yaml -assert: - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml b/tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml deleted file mode 100644 index 21253678d..000000000 --- a/tests/e2e/v1beta2/setup/redis-sentinel/00-install.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: - - sentinel.yaml -assert: - - ready-sts.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml deleted file mode 100644 index f6256b4f1..000000000 --- a/tests/e2e/v1beta2/setup/redis-standalone/00-install.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - standalone.yaml -assert : - # - ready-standalone.yaml - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml b/tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml deleted file mode 100644 index 777fa3656..000000000 --- a/tests/e2e/v1beta2/setup/redis-standalone/ready-pvc.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-standalone-v1beta2-redis-standalone-v1beta2-0 - labels: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml deleted file mode 100644 index a4d7ca849..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/00-install.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - cluster.yaml -assert : - - ready-cluster.yaml - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml deleted file mode 100644 index db6a4fc84..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/01-uninstall.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - command: kubectl delete -f cluster.yaml - namespaced: true -error: - - ready-cluster.yaml - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml deleted file mode 100644 index ecf147104..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/cluster.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta2 -spec: - clusterSize: 3 - clusterVersion: v7 - persistenceEnabled: true - podSecurityContext: - runAsUser: 1000 - fsGroup: 1000 - kubernetesConfig: - image: quay.io/opstree/redis:latest - imagePullPolicy: Always - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisExporter: - enabled: true - image: quay.io/opstree/redis-exporter:v1.44.0 - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - storage: - volumeClaimTemplate: - spec: - # storageClassName: standard - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi - nodeConfVolume: true - nodeConfVolumeClaimTemplate: - spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml deleted file mode 100644 index 49e754e81..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/ready-cluster.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta2 -status: - readyFollowerReplicas: 3 - readyLeaderReplicas: 3 diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml deleted file mode 100644 index a89bfa22a..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/ready-pvc.yaml +++ /dev/null @@ -1,181 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-0 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-1 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-leader-2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-0 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-1 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: node-conf-redis-cluster-v1beta2-follower-2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound - ---- - -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-0 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-1 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-leader-redis-cluster-v1beta2-leader-2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-0 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-1 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-cluster-v1beta2-follower-redis-cluster-v1beta2-follower-2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml deleted file mode 100644 index 1053eb784..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/ready-sts.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-leader - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - replicas: 3 - readyReplicas: 3 - ---- - -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-follower - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - replicas: 3 - readyReplicas: 3 diff --git a/tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml deleted file mode 100644 index e8af234a6..000000000 --- a/tests/e2e/v1beta2/teardown/redis-cluster/ready-svc.yaml +++ /dev/null @@ -1,201 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - - name: redis-exporter - port: 9121 - protocol: TCP - targetPort: 9121 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - name: redis-cluster-v1beta2-leader-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - - name: redis-exporter - port: 9121 - protocol: TCP - targetPort: 9121 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-cluster-v1beta2 - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - name: redis-cluster-v1beta2-follower-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisCluster - name: redis-cluster-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower - type: ClusterIP -status: - loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml deleted file mode 100644 index 19b92e39d..000000000 --- a/tests/e2e/v1beta2/teardown/redis-replication/00-install.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: - - replication.yaml -assert: - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml deleted file mode 100644 index c9e2422b7..000000000 --- a/tests/e2e/v1beta2/teardown/redis-replication/01-uninstall.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - command: kubectl delete -f replication.yaml - namespaced: true -error: - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml b/tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml deleted file mode 100644 index f57cb3f61..000000000 --- a/tests/e2e/v1beta2/teardown/redis-replication/ready-pvc.yaml +++ /dev/null @@ -1,44 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-replication-redis-replication-0 - labels: - app: redis-replication - redis_setup_type: replication - role: replication -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-replication-redis-replication-1 - labels: - app: redis-replication - redis_setup_type: replication - role: replication -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: redis-replication-redis-replication-2 - labels: - app: redis-replication - redis_setup_type: replication - role: replication -status: - accessModes: - - ReadWriteOnce - capacity: - storage: 1Gi - phase: Bound diff --git a/tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml deleted file mode 100644 index f2ac67b1a..000000000 --- a/tests/e2e/v1beta2/teardown/redis-replication/ready-sts.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-replication - labels: - app: redis-replication - redis_setup_type: replication - role: replication - name: redis-replication - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisReplication - name: redis-replication -status: - readyReplicas: 3 - replicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml deleted file mode 100644 index 707a8df9b..000000000 --- a/tests/e2e/v1beta2/teardown/redis-replication/ready-svc.yaml +++ /dev/null @@ -1,90 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-replication - labels: - app: redis-replication - redis_setup_type: replication - role: replication - name: redis-replication - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisReplication - name: redis-replication -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-replication - redis_setup_type: replication - role: replication - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-replication - labels: - app: redis-replication - redis_setup_type: replication - role: replication - name: redis-replication-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisReplication - name: redis-replication -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-replication - redis_setup_type: replication - role: replication - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-replication - labels: - app: redis-replication - redis_setup_type: replication - role: replication - name: redis-replication-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisReplication - name: redis-replication -spec: - clusterIP: None - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-replication - redis_setup_type: replication - role: replication - type: ClusterIP \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-replication/replication.yaml b/tests/e2e/v1beta2/teardown/redis-replication/replication.yaml deleted file mode 100644 index 8e4ba0705..000000000 --- a/tests/e2e/v1beta2/teardown/redis-replication/replication.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisReplication -metadata: - name: redis-replication -spec: - clusterSize: 3 - podSecurityContext: - runAsUser: 1000 - fsGroup: 1000 - kubernetesConfig: - image: quay.io/opstree/redis:latest - imagePullPolicy: Always - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisExporter: - enabled: false - image: quay.io/opstree/redis-exporter:v1.44.0 - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - storage: - volumeClaimTemplate: - spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml deleted file mode 100644 index 21253678d..000000000 --- a/tests/e2e/v1beta2/teardown/redis-sentinel/00-install.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: - - sentinel.yaml -assert: - - ready-sts.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml deleted file mode 100644 index 12984e42a..000000000 --- a/tests/e2e/v1beta2/teardown/redis-sentinel/01-uninstall.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - command: kubectl delete -f sentinel.yaml - namespaced: true -error: - - ready-sts.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml deleted file mode 100644 index c6056ab05..000000000 --- a/tests/e2e/v1beta2/teardown/redis-sentinel/ready-sts.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-sentinel - labels: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - name: redis-sentinel-sentinel - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisSentinel - name: redis-sentinel -spec: - selector: - matchLabels: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - serviceName: redis-sentinel-sentinel-headless - template: - metadata: - annotations: - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-sentinel - labels: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel -status: - readyReplicas: 3 - replicas: 3 \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml deleted file mode 100644 index 4ce66a032..000000000 --- a/tests/e2e/v1beta2/teardown/redis-sentinel/ready-svc.yaml +++ /dev/null @@ -1,96 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-sentinel - labels: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - name: redis-sentinel-sentinel - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisSentinel - name: redis-sentinel -spec: - ports: - - name: sentinel-client - port: 26379 - protocol: TCP - targetPort: 26379 - selector: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-sentinel - labels: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - name: redis-sentinel-sentinel-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisSentinel - name: redis-sentinel -spec: - ports: - - name: sentinel-client - port: 26379 - protocol: TCP - targetPort: 26379 - selector: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-sentinel - labels: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - name: redis-sentinel-sentinel-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: RedisSentinel - name: redis-sentinel -spec: - clusterIP: None - ports: - - name: sentinel-client - port: 26379 - protocol: TCP - targetPort: 26379 - selector: - app: redis-sentinel-sentinel - redis_setup_type: sentinel - role: sentinel - type: ClusterIP -status: - loadBalancer: {} diff --git a/tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml b/tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml deleted file mode 100644 index d18d07f58..000000000 --- a/tests/e2e/v1beta2/teardown/redis-sentinel/sentinel.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: RedisSentinel -metadata: - name: redis-sentinel -spec: - clusterSize: 3 - podSecurityContext: - runAsUser: 1000 - fsGroup: 1000 - redisSentinelConfig: - redisReplicationName : redis-replication - kubernetesConfig: - image: quay.io/opstree/redis-sentinel:latest - imagePullPolicy: Always - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml deleted file mode 100644 index f6256b4f1..000000000 --- a/tests/e2e/v1beta2/teardown/redis-standalone/00-install.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply : - - standalone.yaml -assert : - # - ready-standalone.yaml - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml deleted file mode 100644 index c9c1a7361..000000000 --- a/tests/e2e/v1beta2/teardown/redis-standalone/01-uninstall.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - command: kubectl delete -f standalone.yaml - namespaced: true -error: - - ready-sts.yaml - - ready-pvc.yaml - - ready-svc.yaml \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml deleted file mode 100644 index 5402de920..000000000 --- a/tests/e2e/v1beta2/teardown/redis-standalone/ready-sts.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-standalone-v1beta2 - labels: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone -status: - replicas: 1 - readyReplicas: 1 diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml deleted file mode 100644 index 08b416ce2..000000000 --- a/tests/e2e/v1beta2/teardown/redis-standalone/ready-svc.yaml +++ /dev/null @@ -1,96 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-standalone-v1beta2 - labels: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone - name: redis-standalone-v1beta2-headless - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: Redis - name: redis-standalone-v1beta2 -spec: - clusterIP: None - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-standalone-v1beta2 - labels: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone - name: redis-standalone-v1beta2 - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: Redis - name: redis-standalone-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone - type: ClusterIP -status: - loadBalancer: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" - redis.opstreelabs.instance: redis-standalone-v1beta2 - labels: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone - name: redis-standalone-v1beta2-additional - ownerReferences: - - apiVersion: redis.redis.opstreelabs.in/v1beta2 - controller: true - kind: Redis - name: redis-standalone-v1beta2 -spec: - ports: - - name: redis-client - port: 6379 - protocol: TCP - targetPort: 6379 - selector: - app: redis-standalone-v1beta2 - redis_setup_type: standalone - role: standalone - type: ClusterIP -status: - loadBalancer: {} \ No newline at end of file diff --git a/tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml b/tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml deleted file mode 100644 index c0cc6ded9..000000000 --- a/tests/e2e/v1beta2/teardown/redis-standalone/standalone.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: redis.redis.opstreelabs.in/v1beta2 -kind: Redis -metadata: - name: redis-standalone-v1beta2 -spec: - podSecurityContext: - runAsUser: 1000 - fsGroup: 1000 - kubernetesConfig: - image: quay.io/opstree/redis:latest - imagePullPolicy: Always - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - storage: - volumeClaimTemplate: - spec: - # storageClassName: standard - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 1Gi From 63189221844e67b974d497e90a15f7db6f4d3165 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:56:02 +0530 Subject: [PATCH 105/203] test: Add Finalizers Unit Test (#799) * test: Add Unit Test Signed-off-by: Shubham Gupta * chore: update makefile Signed-off-by: Shubham Gupta * gci-ed Signed-off-by: Shubham Gupta * test: Add finalizers testing Signed-off-by: Shubham Gupta * gci-ed Signed-off-by: Shubham Gupta * style: fix trailing new line Signed-off-by: Shubham Gupta * test: Add Handle Redis Cluster Finalizers Signed-off-by: Shubham Gupta * chore: makefile Signed-off-by: Shubham Gupta * test: Add Handle Replication Finalizers Signed-off-by: Shubham Gupta * test: Add Redis Sentinel Handle Finalizers Signed-off-by: Shubham Gupta * chore: remove unused code Signed-off-by: Shubham Gupta * test: fix coverage Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- Makefile | 35 +- controllers/redissentinel_controller.go | 2 +- k8sutils/finalizer.go | 11 +- k8sutils/finalizers_test.go | 935 ++++++++++++++++++++++-- k8sutils/log/log.go | 17 + 5 files changed, 930 insertions(+), 70 deletions(-) create mode 100644 k8sutils/log/log.go diff --git a/Makefile b/Makefile index 49695e5cc..110a2626c 100644 --- a/Makefile +++ b/Makefile @@ -134,22 +134,37 @@ verify-codegen: codegen @echo 'To correct this, locally run "make codegen", commit the changes, and re-run tests.' >&2 @git diff --quiet --exit-code -- . + +######## +# TEST # +######## + +.PHONY: tests +tests: integration-test-setup unit-tests + +.PHONY: unit-tests +unit-tests: + @echo Running tests... >&2 + @go test ./... -race -coverprofile=coverage.out -covermode=atomic + @go tool cover -html=coverage.out + +.PHONY: e2e-test +e2e-test: e2e-kind-setup install-kuttl + $(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml + +.PHONY: integration-test-setup +integration-test-setup: + ./hack/integrationSetup.sh + + .PHONY: install-kuttl install-kuttl: curl -L https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64 -o $(shell pwd)/bin/kuttl chmod +x $(shell pwd)/bin/kuttl .PHONY: e2e-kind-setup -e2e-kind-setup: +e2e-kind-setup: docker build -t redis-operator:e2e -f Dockerfile . kind create cluster --config tests/_config/kind-config.yaml kind load docker-image redis-operator:e2e --name kind - make deploy IMG=redis-operator:e2e - -.PHONY: e2e-test -e2e-test: e2e-kind-setup install-kuttl - $(shell pwd)/bin/kuttl test --config tests/_config/kuttl-test.yaml - -.PHONY: integration-test-setup -integration-test-setup: - ./hack/integrationSetup.sh \ No newline at end of file + make deploy IMG=redis-operator:e2e \ No newline at end of file diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 42b117672..55d4ee7d9 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -46,7 +46,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques // Get total Sentinel Replicas // sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel") - if err = k8sutils.HandleRedisSentinelFinalizer(instance, r.Client); err != nil { + if err = k8sutils.HandleRedisSentinelFinalizer(r.Client, r.Log, instance); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index b9a08d27c..62faf4b7a 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -21,12 +21,6 @@ const ( RedisSentinelFinalizer string = "redisSentinelFinalizer" ) -// finalizeLogger will generate logging interface -func finalizerLogger(namespace string, name string) logr.Logger { - reqLogger := log.WithValues("Request.Service.Namespace", namespace, "Request.Finalizer.Name", name) - return reqLogger -} - // HandleRedisFinalizer finalize resource if instance is marked to be deleted func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error { if cr.GetDeletionTimestamp() != nil { @@ -85,15 +79,14 @@ func HandleRedisReplicationFinalizer(ctrlclient client.Client, k8sClient kuberne } // HandleRedisSentinelFinalizer finalize resource if instance is marked to be deleted -func HandleRedisSentinelFinalizer(cr *redisv1beta2.RedisSentinel, cl client.Client) error { - logger := finalizerLogger(cr.Namespace, RedisSentinelFinalizer) +func HandleRedisSentinelFinalizer(ctrlclient client.Client, logger logr.Logger, cr *redisv1beta2.RedisSentinel) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisSentinelFinalizer) { if err := finalizeRedisSentinelPVC(cr); err != nil { return err } controllerutil.RemoveFinalizer(cr, RedisSentinelFinalizer) - if err := cl.Update(context.TODO(), cr); err != nil { + if err := ctrlclient.Update(context.TODO(), cr); err != nil { logger.Error(err, "Could not remove finalizer "+RedisSentinelFinalizer) return err } diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go index a20ab6362..5ad37c2ed 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizers_test.go @@ -4,61 +4,570 @@ import ( "context" "fmt" "testing" + "time" + "github.com/OT-CONTAINER-KIT/redis-operator/api" "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + mockClient "github.com/OT-CONTAINER-KIT/redis-operator/mocks/client" "github.com/go-logr/logr/testr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - // "k8s.io/apimachinery/pkg/types" - // utilruntime "k8s.io/apimachinery/pkg/util/runtime" k8sClientFake "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" ) -// func TestHandleRedisFinalizer(t *testing.T) { -// cr := &v1beta2.Redis{ -// TypeMeta: metav1.TypeMeta{ -// Kind: "Redis", -// APIVersion: "redis.opstreelabs.in/v1beta2", -// }, -// ObjectMeta: metav1.ObjectMeta{ -// Name: "test-redis", -// Namespace: "default", -// DeletionTimestamp: &metav1.Time{Time: time.Now()}, -// Finalizers: []string{RedisFinalizer}, -// }, -// } - -// // Create a fake controller-runtime client -// scheme := runtime.NewScheme() -// mockAddToScheme := v1beta2.SchemeBuilder.Register(&v1beta2.Redis{}, &v1beta2.RedisList{}).AddToScheme(scheme) -// utilruntime.Must(mockAddToScheme) - -// ctrlFakeclient := ctrlClientFake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(cr.DeepCopyObject()).Build() -// k8sFakeClient := k8sClientFake.NewSimpleClientset(cr.DeepCopyObject()) - -// logger := testr.New(t) -// // Run the HandleRedisFinalizer function -// err := HandleRedisFinalizer(ctrlFakeclient, k8sFakeClient, logger, cr) -// assert.NoError(t, err) - -// // Check if the PVC was deleted -// PVCName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) -// _, err = k8sFakeClient.CoreV1().PersistentVolumeClaims(cr.Namespace).Get(context.TODO(), PVCName, metav1.GetOptions{}) -// assert.True(t, k8serrors.IsNotFound(err)) - -// // Check if the finalizer was removed -// updatedCR := &v1beta2.Redis{} -// err = ctrlFakeclient.Get(context.TODO(), types.NamespacedName{Namespace: "default", Name: "test-redis"}, updatedCR) -// assert.NoError(t, err) -// assert.NotContains(t, updatedCR.GetFinalizers(), RedisFinalizer) - -// // Ensure the logger's Error method was not called -// //logger.AssertNotCalled(t, "Error", mock.Anything, mock.Anything, mock.Anything) -// } +func TestHandleRedisFinalizer(t *testing.T) { + tests := []struct { + name string + mockClient *mockClient.MockClient + hasFinalizers bool + cr *v1beta2.Redis + existingPVC *corev1.PersistentVolumeClaim + expectError bool + }{ + { + name: "Redis CR without finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisSpec{ + Storage: &v1beta2.Storage{ + Storage: api.Storage{ + KeepAfterDelete: false, + }, + }, + }, + }, + existingPVC: &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone-redis-standalone-0", + Namespace: "default", + }, + }, + expectError: false, + }, + { + name: "Redis CR with finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: true, + cr: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{RedisFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisSpec{ + Storage: &v1beta2.Storage{ + Storage: api.Storage{ + KeepAfterDelete: false, + }, + }, + }, + }, + existingPVC: &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone-redis-standalone-0", + Namespace: "default", + }, + }, + expectError: false, + }, + { + name: "Redis CR with finalizer and keepAfterDelete true", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: true, + cr: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{RedisFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisSpec{ + Storage: &v1beta2.Storage{ + Storage: api.Storage{ + KeepAfterDelete: true, + }, + }, + }, + }, + existingPVC: &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone-redis-standalone-0", + Namespace: "default", + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tc.existingPVC != nil { + k8sClient = k8sClientFake.NewSimpleClientset(tc.existingPVC.DeepCopyObject()) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + // Verify that the PVC was created + if tc.existingPVC != nil { + pvcName := fmt.Sprintf("%s-%s-0", tc.cr.Name, tc.cr.Name) + _, err := k8sClient.CoreV1().PersistentVolumeClaims(tc.cr.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{}) + assert.NoError(t, err) + } + + err := HandleRedisFinalizer(tc.mockClient, k8sClient, logger, tc.cr) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Empty(t, tc.cr.GetFinalizers()) + } + + // Verify that the PVC is not found in case of success or non-existent PVC + if !tc.expectError && tc.cr.DeletionTimestamp != nil && tc.hasFinalizers { + pvcName := fmt.Sprintf("%s-%s-0", tc.cr.GetName(), tc.cr.GetName()) + _, err = k8sClient.CoreV1().PersistentVolumeClaims(tc.cr.GetNamespace()).Get(context.TODO(), pvcName, metav1.GetOptions{}) + if tc.cr.Spec.Storage.KeepAfterDelete { + assert.NoError(t, err) + } else { + assert.True(t, k8serrors.IsNotFound(err)) + } + } + }) + } +} + +func TestHandleRedisClusterFinalizer(t *testing.T) { + tests := []struct { + name string + mockClient *mockClient.MockClient + hasFinalizers bool + cr *v1beta2.RedisCluster + existingPVC []*corev1.PersistentVolumeClaim + expectError bool + }{ + { + name: "Redis Cluster CR without finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + }, + existingPVC: helperRedisClusterPVCs("redis-cluster", "default"), + expectError: false, + }, + { + name: "Redis Cluster CR with finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: true, + cr: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{RedisClusterFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.ClusterStorage{ + Storage: api.Storage{ + KeepAfterDelete: false, + }, + NodeConfVolume: true, + }, + }, + }, + existingPVC: helperRedisClusterPVCs("redis-cluster", "default"), + expectError: false, + }, + { + name: "Redis Cluster CR with finalizer and keepAfterDelete true", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: true, + cr: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{RedisClusterFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisClusterSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.ClusterStorage{ + Storage: api.Storage{ + KeepAfterDelete: true, + }, + }, + }, + }, + existingPVC: helperRedisClusterPVCs("redis-cluster", "default"), + expectError: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tc.existingPVC != nil { + k8sClient = k8sClientFake.NewSimpleClientset(helperToRuntimeObjects(tc.existingPVC)...) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + // Verify that the PVC was created + if tc.existingPVC != nil && len(tc.existingPVC) != 0 { + for _, pvc := range tc.existingPVC { + pvcName := pvc.GetName() + _, err := k8sClient.CoreV1().PersistentVolumeClaims(tc.cr.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{}) + assert.NoError(t, err) + } + } + + err := HandleRedisClusterFinalizer(tc.mockClient, k8sClient, logger, tc.cr) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Empty(t, tc.cr.GetFinalizers()) + } + + // Verify that the PVC is not found in case of success or non-existent PVC + if !tc.expectError && tc.cr.DeletionTimestamp != nil && tc.hasFinalizers { + for _, pvc := range tc.existingPVC { + pvcName := pvc.GetName() + t.Log(pvcName) + _, err := k8sClient.CoreV1().PersistentVolumeClaims(tc.cr.GetNamespace()).Get(context.TODO(), pvcName, metav1.GetOptions{}) + if tc.cr.Spec.Storage.KeepAfterDelete { + assert.NoError(t, err) + } else { + assert.True(t, k8serrors.IsNotFound(err)) + } + } + } + }) + } +} + +func TestHandleRedisReplicationFinalizer(t *testing.T) { + tests := []struct { + name string + mockClient *mockClient.MockClient + hasFinalizers bool + cr *v1beta2.RedisReplication + existingPVC []*corev1.PersistentVolumeClaim + expectError bool + }{ + { + name: "Redis Replication CR without finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "redis", + Finalizers: []string{}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisReplicationSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.Storage{ + Storage: api.Storage{ + KeepAfterDelete: false, + }, + }, + }, + }, + existingPVC: []*corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-0", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-1", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-2", + Namespace: "redis", + }, + }, + }, + expectError: false, + }, + { + name: "Redis Replication CR with finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "redis", + Finalizers: []string{RedisReplicationFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisReplicationSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.Storage{ + Storage: api.Storage{ + KeepAfterDelete: false, + }, + }, + }, + }, + existingPVC: []*corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-0", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-1", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-2", + Namespace: "redis", + }, + }, + }, + expectError: false, + }, + { + name: "Redis Replication CR with finalizer and keepAfterDelete true", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "redis", + Finalizers: []string{RedisReplicationFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisReplicationSpec{ + Size: pointer.Int32(3), + Storage: &v1beta2.Storage{ + Storage: api.Storage{ + KeepAfterDelete: true, + }, + }, + }, + }, + existingPVC: []*corev1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-0", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-1", + Namespace: "redis", + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication-redis-replication-2", + Namespace: "redis", + }, + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tc.existingPVC != nil { + k8sClient = k8sClientFake.NewSimpleClientset(helperToRuntimeObjects(tc.existingPVC)...) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + // Verify that the PVC was created + if tc.existingPVC != nil && len(tc.existingPVC) != 0 { + for _, pvc := range tc.existingPVC { + pvcName := pvc.GetName() + _, err := k8sClient.CoreV1().PersistentVolumeClaims(tc.cr.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{}) + assert.NoError(t, err) + } + } + + err := HandleRedisReplicationFinalizer(tc.mockClient, k8sClient, logger, tc.cr) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Empty(t, tc.cr.GetFinalizers()) + } + + // Verify that the PVC is not found in case of success or non-existent PVC + if !tc.expectError && tc.cr.DeletionTimestamp != nil && tc.hasFinalizers { + for _, pvc := range tc.existingPVC { + pvcName := pvc.GetName() + t.Log(pvcName) + _, err := k8sClient.CoreV1().PersistentVolumeClaims(tc.cr.GetNamespace()).Get(context.TODO(), pvcName, metav1.GetOptions{}) + if tc.cr.Spec.Storage.KeepAfterDelete { + assert.NoError(t, err) + } else { + assert.True(t, k8serrors.IsNotFound(err)) + } + } + } + }) + } +} + +func TestHandleRedisSentinelFinalizer(t *testing.T) { + tests := []struct { + name string + mockClient *mockClient.MockClient + hasFinalizers bool + cr *v1beta2.RedisSentinel + expectError bool + }{ + { + name: "Redis Sentinel CR without finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisSentinelSpec{}, + }, + expectError: false, + }, + { + name: "Redis Sentinel CR with finalizer", + mockClient: &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + }, + hasFinalizers: false, + cr: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{RedisSentinelFinalizer}, + DeletionTimestamp: &metav1.Time{ + Time: time.Now(), + }, + }, + Spec: v1beta2.RedisSentinelSpec{}, + }, + expectError: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + logger := testr.New(t) + err := HandleRedisSentinelFinalizer(tc.mockClient, logger, tc.cr) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Empty(t, tc.cr.GetFinalizers()) + } + }) + } +} func TestFinalizeRedisPVC(t *testing.T) { tests := []struct { @@ -79,13 +588,8 @@ func TestFinalizeRedisPVC(t *testing.T) { errorExpected: nil, }, { - name: "PVC does not exist and no error should be returned", - existingPVC: &corev1.PersistentVolumeClaim{ - ObjectMeta: metav1.ObjectMeta{ - Name: "nonexistent", - Namespace: "default", - }, - }, + name: "PVC does not exist and no error should be returned", + existingPVC: nil, expectError: false, errorExpected: nil, }, @@ -107,6 +611,13 @@ func TestFinalizeRedisPVC(t *testing.T) { k8sClient = k8sClientFake.NewSimpleClientset() } + // Verify that the PVC was created + if tc.existingPVC != nil { + pvcName := fmt.Sprintf("%s-%s-0", cr.Name, cr.Name) + _, err := k8sClient.CoreV1().PersistentVolumeClaims(cr.Namespace).Get(context.TODO(), pvcName, metav1.GetOptions{}) + assert.NoError(t, err) + } + err := finalizeRedisPVC(k8sClient, logger, cr) if tc.expectError { assert.Error(t, err) @@ -313,3 +824,327 @@ func helperRedisClusterPVCs(clusterName string, namespace string) []*corev1.Pers } return pvcs } + +func TestAddRedisFinalizer(t *testing.T) { + fakeFinalizer := "FakeFinalizer" + tests := []struct { + name string + redisStandalone *v1beta2.Redis + want *v1beta2.Redis + expectError bool + }{ + { + name: "Redis CR without finalizer", + redisStandalone: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + }, + }, + want: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{RedisFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis CR with finalizer", + redisStandalone: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{RedisFinalizer}, + }, + }, + want: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{RedisFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis CR with random finalizer", + redisStandalone: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{fakeFinalizer}, + }, + }, + want: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-standalone", + Namespace: "default", + Finalizers: []string{fakeFinalizer, RedisFinalizer}, + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + mockClient := &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + } + t.Run(tc.name, func(t *testing.T) { + err := AddRedisFinalizer(tc.redisStandalone, mockClient) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.want, tc.redisStandalone) + } + }) + } +} + +func TestAddRedisClusterFinalizer(t *testing.T) { + fakeFinalizer := "FakeFinalizer" + tests := []struct { + name string + redisCluster *v1beta2.RedisCluster + want *v1beta2.RedisCluster + expectError bool + }{ + { + name: "Redis Cluster CR without finalizer", + redisCluster: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + }, + want: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{RedisClusterFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis Cluster CR with finalizer", + redisCluster: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{RedisClusterFinalizer}, + }, + }, + want: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{RedisClusterFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis Cluster CR with random finalizer", + redisCluster: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{fakeFinalizer}, + }, + }, + want: &v1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + Finalizers: []string{fakeFinalizer, RedisClusterFinalizer}, + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + mockClient := &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + } + t.Run(tc.name, func(t *testing.T) { + err := AddRedisClusterFinalizer(tc.redisCluster, mockClient) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.want, tc.redisCluster) + } + }) + } +} + +func TestAddRedisReplicationFinalizer(t *testing.T) { + fakeFinalizer := "FakeFinalizer" + tests := []struct { + name string + redisReplication *v1beta2.RedisReplication + want *v1beta2.RedisReplication + expectError bool + }{ + { + name: "Redis Replication CR without finalizer", + redisReplication: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "default", + }, + }, + want: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "default", + Finalizers: []string{RedisReplicationFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis Replication CR with finalizer", + redisReplication: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "default", + Finalizers: []string{RedisReplicationFinalizer}, + }, + }, + want: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "default", + Finalizers: []string{RedisReplicationFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis Replication CR with random finalizer", + redisReplication: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "default", + Finalizers: []string{fakeFinalizer}, + }, + }, + want: &v1beta2.RedisReplication{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-replication", + Namespace: "default", + Finalizers: []string{fakeFinalizer, RedisReplicationFinalizer}, + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + mockClient := &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + } + t.Run(tc.name, func(t *testing.T) { + err := AddRedisReplicationFinalizer(tc.redisReplication, mockClient) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.want, tc.redisReplication) + } + }) + } +} + +func TestAddRedisSentinelFinalizer(t *testing.T) { + fakeFinalizer := "FakeFinalizer" + tests := []struct { + name string + redisSentinel *v1beta2.RedisSentinel + want *v1beta2.RedisSentinel + expectError bool + }{ + { + name: "Redis Sentinel CR without finalizer", + redisSentinel: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + }, + }, + want: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{RedisSentinelFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis Sentinel CR with finalizer", + redisSentinel: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{RedisSentinelFinalizer}, + }, + }, + want: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{RedisSentinelFinalizer}, + }, + }, + expectError: false, + }, + { + name: "Redis Sentinel CR with random finalizer", + redisSentinel: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{fakeFinalizer}, + }, + }, + want: &v1beta2.RedisSentinel{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-sentinel", + Namespace: "default", + Finalizers: []string{fakeFinalizer, RedisSentinelFinalizer}, + }, + }, + expectError: false, + }, + } + + for _, tc := range tests { + mockClient := &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil + }, + } + t.Run(tc.name, func(t *testing.T) { + err := AddRedisSentinelFinalizer(tc.redisSentinel, mockClient) + if tc.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.want, tc.redisSentinel) + } + }) + } +} diff --git a/k8sutils/log/log.go b/k8sutils/log/log.go new file mode 100644 index 000000000..b8ee0130d --- /dev/null +++ b/k8sutils/log/log.go @@ -0,0 +1,17 @@ +package log + +import "github.com/go-logr/logr" + +type Logger interface { + Enabled() bool + Error(err error, msg string, keysAndValues ...interface{}) + GetSink() logr.LogSink + Info(msg string, keysAndValues ...interface{}) + IsZero() bool + V(level int) logr.Logger + WithCallDepth(depth int) logr.Logger + WithCallStackHelper() (func(), logr.Logger) + WithName(name string) logr.Logger + WithSink(sink logr.LogSink) logr.Logger + WithValues(keysAndValues ...interface{}) logr.Logger +} From 17b9d2c812e8cfa9d0f7973b1d5b8ef77052100e Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Tue, 5 Mar 2024 22:05:23 +0530 Subject: [PATCH 106/203] test: service unit Testing (#800) * test: service unit Testing Signed-off-by: Shubham Gupta * test: add Test_createService Signed-off-by: Shubham Gupta * test: update service Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- k8sutils/redis-cluster.go | 7 +- k8sutils/redis-cluster_test.go | 6 +- k8sutils/services.go | 21 ++-- k8sutils/services_test.go | 202 +++++++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+), 17 deletions(-) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 273158be5..aae4cf5bf 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -8,6 +8,7 @@ import ( commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" @@ -101,7 +102,7 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init } // generateRedisClusterContainerParams generates Redis container information -func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, role string, cl kubernetes.Interface) containerParameters { +func generateRedisClusterContainerParams(cl kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, role string) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ @@ -137,7 +138,7 @@ func generateRedisClusterContainerParams(cr *redisv1beta2.RedisCluster, security nps := map[string]ports{} // pod name to ports replicas := cr.Spec.GetReplicaCounts(role) for i := 0; i < int(replicas); i++ { - svc, err := getService(cr.Namespace, cr.ObjectMeta.Name+"-"+role+"-"+strconv.Itoa(i), cl) + svc, err := getService(cl, logger, cr.Namespace, cr.ObjectMeta.Name+"-"+role+"-"+strconv.Itoa(i)) if err != nil { log.Error(err, "Cannot get service for Redis", "Setup.Type", role) } else { @@ -274,7 +275,7 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu generateRedisClusterParams(cr, service.getReplicaCount(cr), service.ExternalConfig, service), redisClusterAsOwner(cr), generateRedisClusterInitContainerParams(cr), - generateRedisClusterContainerParams(cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType, cl), + generateRedisClusterContainerParams(cl, logger, cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType), cr.Spec.Sidecars, cl, ) diff --git a/k8sutils/redis-cluster_test.go b/k8sutils/redis-cluster_test.go index 3774a0889..ff7e83672 100644 --- a/k8sutils/redis-cluster_test.go +++ b/k8sutils/redis-cluster_test.go @@ -7,6 +7,7 @@ import ( common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr/testr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -427,11 +428,12 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { if err != nil { t.Fatalf("Failed to unmarshal file %s: %v", path, err) } + logger := testr.New(t) - actualLeaderContainer := generateRedisClusterContainerParams(input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader", fake.NewSimpleClientset()) + actualLeaderContainer := generateRedisClusterContainerParams(fake.NewSimpleClientset(), logger, input, input.Spec.RedisLeader.SecurityContext, input.Spec.RedisLeader.ReadinessProbe, input.Spec.RedisLeader.LivenessProbe, "leader") assert.EqualValues(t, expectedLeaderContainer, actualLeaderContainer, "Expected %+v, got %+v", expectedLeaderContainer, actualLeaderContainer) - actualFollowerContainer := generateRedisClusterContainerParams(input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower", fake.NewSimpleClientset()) + actualFollowerContainer := generateRedisClusterContainerParams(fake.NewSimpleClientset(), logger, input, input.Spec.RedisFollower.SecurityContext, input.Spec.RedisFollower.ReadinessProbe, input.Spec.RedisFollower.LivenessProbe, "follower") assert.EqualValues(t, expectedFollowerContainer, actualFollowerContainer, "Expected %+v, got %+v", expectedFollowerContainer, actualFollowerContainer) } diff --git a/k8sutils/services.go b/k8sutils/services.go index 94e93c00c..627117277 100644 --- a/k8sutils/services.go +++ b/k8sutils/services.go @@ -94,9 +94,8 @@ func generateServiceType(k8sServiceType string) corev1.ServiceType { } // createService is a method to create service is Kubernetes -func createService(namespace string, service *corev1.Service, cl kubernetes.Interface) error { - logger := serviceLogger(namespace, service.Name) - _, err := cl.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) +func createService(kusClient kubernetes.Interface, logger logr.Logger, namespace string, service *corev1.Service) error { + _, err := kusClient.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis service creation is failed") return err @@ -106,9 +105,8 @@ func createService(namespace string, service *corev1.Service, cl kubernetes.Inte } // updateService is a method to update service is Kubernetes -func updateService(namespace string, service *corev1.Service, cl kubernetes.Interface) error { - logger := serviceLogger(namespace, service.Name) - _, err := cl.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) +func updateService(k8sClient kubernetes.Interface, logger logr.Logger, namespace string, service *corev1.Service) error { + _, err := k8sClient.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) if err != nil { logger.Error(err, "Redis service update failed") return err @@ -118,12 +116,11 @@ func updateService(namespace string, service *corev1.Service, cl kubernetes.Inte } // getService is a method to get service is Kubernetes -func getService(namespace string, service string, cl kubernetes.Interface) (*corev1.Service, error) { - logger := serviceLogger(namespace, service) +func getService(k8sClient kubernetes.Interface, logger logr.Logger, namespace string, name string) (*corev1.Service, error) { getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("Service", "v1"), } - serviceInfo, err := cl.CoreV1().Services(namespace).Get(context.TODO(), service, getOpts) + serviceInfo, err := k8sClient.CoreV1().Services(namespace).Get(context.TODO(), name, getOpts) if err != nil { logger.V(1).Info("Redis service get action is failed") return nil, err @@ -141,13 +138,13 @@ func serviceLogger(namespace string, name string) logr.Logger { func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, ownerDef metav1.OwnerReference, epp exporterPortProvider, headless bool, serviceType string, port int, cl kubernetes.Interface, extra ...corev1.ServicePort) error { logger := serviceLogger(namespace, serviceMeta.Name) serviceDef := generateServiceDef(serviceMeta, epp, ownerDef, headless, serviceType, port, extra...) - storedService, err := getService(namespace, serviceMeta.Name, cl) + storedService, err := getService(cl, logger, namespace, serviceMeta.GetName()) if err != nil { if errors.IsNotFound(err) { if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil { //nolint logger.Error(err, "Unable to patch redis service with compare annotations") } - return createService(namespace, serviceDef, cl) + return createService(cl, logger, namespace, serviceDef) } return err } @@ -188,7 +185,7 @@ func patchService(storedService *corev1.Service, newService *corev1.Service, nam return err } logger.V(1).Info("Syncing Redis service with defined properties") - return updateService(namespace, newService, cl) + return updateService(cl, logger, namespace, newService) } logger.V(1).Info("Redis service is already in-sync") return nil diff --git a/k8sutils/services_test.go b/k8sutils/services_test.go index 786783944..5906d61db 100644 --- a/k8sutils/services_test.go +++ b/k8sutils/services_test.go @@ -1,12 +1,15 @@ package k8sutils import ( + "context" "testing" + "github.com/go-logr/logr/testr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + k8sClientFake "k8s.io/client-go/kubernetes/fake" ) var defaultExporterPortProvider exporterPortProvider = func() (int, bool) { @@ -276,3 +279,202 @@ func TestGenerateServiceType(t *testing.T) { }) } } + +func Test_createService(t *testing.T) { + tests := []struct { + name string + service *corev1.Service + exist bool + wantErr bool + }{ + { + name: "Service created successfully", + service: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + }, + wantErr: false, + }, + { + name: "Service creation failed already exists", + service: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + }, + exist: true, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tt.exist { + k8sClient = k8sClientFake.NewSimpleClientset(tt.service.DeepCopyObject()) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + err := createService(k8sClient, logger, tt.service.GetNamespace(), tt.service) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + // Verify the service was created + got, err := k8sClient.CoreV1().Services(tt.service.GetNamespace()).Get(context.TODO(), tt.service.GetName(), metav1.GetOptions{}) + assert.NoError(t, err) + assert.Equal(t, tt.service, got) + } + }) + } +} + +func Test_updateService(t *testing.T) { + tests := []struct { + name string + serviceName string + servinceNamespace string + current *corev1.Service + updated *corev1.Service + wantErr bool + }{ + { + name: "Service updated successfully", + serviceName: "test-service", + servinceNamespace: "test-namespace", + current: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "test-port", + Port: 6379, + TargetPort: intstr.FromInt(6379), + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + updated: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "fake-port", + Port: 6380, + TargetPort: intstr.FromInt(6380), + Protocol: corev1.ProtocolUDP, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "Service does not exist", + serviceName: "test-service", + servinceNamespace: "test-namespace", + current: &corev1.Service{}, + updated: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "fake-port", + Port: 6380, + TargetPort: intstr.FromInt(6380), + Protocol: corev1.ProtocolUDP, + }, + }, + }, + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + logger := testr.New(t) + k8sClient := k8sClientFake.NewSimpleClientset(tt.current.DeepCopyObject()) + + err := updateService(k8sClient, logger, tt.servinceNamespace, tt.updated) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + // Verify the service was updated + got, err := k8sClient.CoreV1().Services(tt.servinceNamespace).Get(context.TODO(), tt.serviceName, metav1.GetOptions{}) + assert.NoError(t, err) + assert.Equal(t, tt.updated, got) + } + }) + } +} + +func Test_getService(t *testing.T) { + tests := []struct { + name string + have *corev1.Service + want *corev1.Service + wantErr bool + }{ + { + name: "Service exists", + have: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + }, + want: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + }, + }, + { + name: "Service does not exist", + have: &corev1.Service{}, + want: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-service", + Namespace: "test-namespace", + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + logger := testr.New(t) + var k8sClient *k8sClientFake.Clientset + if tt.have != nil { + k8sClient = k8sClientFake.NewSimpleClientset(tt.have.DeepCopyObject()) + } else { + k8sClient = k8sClientFake.NewSimpleClientset() + } + + got, err := getService(k8sClient, logger, tt.want.GetNamespace(), tt.want.GetName()) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.want, got) + } + }) + } +} From d3abdd37a26316eaf779c7d9d2beb4ae491b1a88 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Thu, 7 Mar 2024 23:23:24 +0530 Subject: [PATCH 107/203] ci: Add dependabot and cherry-pick-bot (#807) Signed-off-by: Shubham Gupta --- .github/cherry-pick-bot.yml | 2 ++ .github/dependabot.yml | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 .github/cherry-pick-bot.yml create mode 100644 .github/dependabot.yml diff --git a/.github/cherry-pick-bot.yml b/.github/cherry-pick-bot.yml new file mode 100644 index 000000000..2f6674478 --- /dev/null +++ b/.github/cherry-pick-bot.yml @@ -0,0 +1,2 @@ +enabled: true +preservePullRequestTitle: true \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..0476c5b94 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: gomod + directory: / + schedule: + interval: daily + - package-ecosystem: github-actions + directory: / + schedule: + interval: daily \ No newline at end of file From 39e5bf5ddfe829facf1c35a47f9ecb062279a324 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Thu, 7 Mar 2024 23:27:42 +0530 Subject: [PATCH 108/203] ci: add deps scope in pr semantics (#818) Signed-off-by: Shubham Gupta --- .github/workflows/pr-semantics.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-semantics.yaml b/.github/workflows/pr-semantics.yaml index bf06c5692..55c78c8a3 100644 --- a/.github/workflows/pr-semantics.yaml +++ b/.github/workflows/pr-semantics.yaml @@ -54,6 +54,7 @@ jobs: # Configure which scopes are allowed. scopes: | api + deps config client config From 90122a4fe10e885b4226ca74449a5875fe8ea2fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 10:14:12 +0800 Subject: [PATCH 109/203] chore(deps): bump github.com/onsi/ginkgo/v2 from 2.11.0 to 2.16.0 (#815) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.11.0 to 2.16.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.11.0...v2.16.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 18 +++++++++--------- go.sum | 37 ++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index eff13a616..8d04071e5 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.21 require ( github.com/banzaicloud/k8s-objectmatcher v1.7.0 - github.com/go-logr/logr v1.2.4 - github.com/onsi/ginkgo/v2 v2.11.0 - github.com/onsi/gomega v1.27.10 + github.com/go-logr/logr v1.4.1 + github.com/onsi/ginkgo/v2 v2.16.0 + github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.2.1 github.com/stretchr/testify v1.8.4 @@ -36,7 +36,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect @@ -58,13 +58,13 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.17.0 // indirect + golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.9.3 // indirect + golang.org/x/tools v0.17.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 0aec70c41..69eb423c7 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,9 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= @@ -97,8 +98,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -156,12 +157,12 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM= +github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -221,8 +222,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -236,8 +235,8 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= @@ -261,16 +260,16 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -284,8 +283,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= -golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 9bab658b7ae0315634fc8c6d03cf562cc8d48c6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 10:14:46 +0800 Subject: [PATCH 110/203] chore(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0 (#814) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8d04071e5..f10a31e71 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.2.1 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 k8s.io/api v0.28.2 k8s.io/apimachinery v0.28.2 k8s.io/client-go v0.28.2 diff --git a/go.sum b/go.sum index 69eb423c7..a6c484cc4 100644 --- a/go.sum +++ b/go.sum @@ -194,8 +194,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= From fcd7d5858ca8e19f8f49d26be59711a6c917bb35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 10:15:44 +0800 Subject: [PATCH 111/203] chore(deps): bump actions/checkout from 2 to 4 (#808) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/e2e-chainsaw.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/operator-ci.yaml | 12 ++++++------ .github/workflows/validate-example.yaml | 2 +- .github/workflows/verify-codegen.yaml | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5102a0f45..798335143 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -39,7 +39,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index 6b0b7a8a0..fde2d1489 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build Dockerfile run: docker build . --file Dockerfile --tag redis-operator:e2e diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index db749ea61..eb4005b9f 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -18,7 +18,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build Dockerfile run: docker build . --file Dockerfile --tag redis-operator:e2e diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 72cd7db61..cf8522e61 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -23,7 +23,7 @@ jobs: name: Go Test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: @@ -42,7 +42,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: @@ -58,7 +58,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Execute dockerlinter uses: hadolint/hadolint-action@v3.1.0 @@ -74,7 +74,7 @@ jobs: arch: ["amd64", "arm64"] steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup Go Environment uses: actions/setup-go@v4 with: @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -111,7 +111,7 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Gosec Scan uses: securego/gosec@master with: diff --git a/.github/workflows/validate-example.yaml b/.github/workflows/validate-example.yaml index f0f11de98..4b8efe74e 100644 --- a/.github/workflows/validate-example.yaml +++ b/.github/workflows/validate-example.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install yamllint run: sudo apt-get install -y yamllint diff --git a/.github/workflows/verify-codegen.yaml b/.github/workflows/verify-codegen.yaml index 4ac6795f9..0f8fea071 100644 --- a/.github/workflows/verify-codegen.yaml +++ b/.github/workflows/verify-codegen.yaml @@ -25,7 +25,7 @@ jobs: swap-storage: false - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: From 012d5babae040ce3f5362a714df8dd46c56b0aa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 10:16:25 +0800 Subject: [PATCH 112/203] chore(deps): bump github/codeql-action from 1 to 3 (#809) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v1...v3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 798335143..e4385c33d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -43,7 +43,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,7 +54,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -68,4 +68,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v3 From 4ddd2f8441b710f8da6fc2fa8ed82d9520c8a73a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 13:47:16 +0800 Subject: [PATCH 113/203] chore(deps): bump actions/setup-go from 4 to 5 (#811) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 6 +++--- .github/workflows/verify-codegen.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index cf8522e61..6d0c17f28 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -25,7 +25,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GOLANG_VERSION }} - name: Install integration test dependencies @@ -44,7 +44,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GOLANG_VERSION }} cache: false @@ -76,7 +76,7 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 - name: Setup Go Environment - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: ${{ env.GOLANG_VERSION }} - name: Set GOARCH diff --git a/.github/workflows/verify-codegen.yaml b/.github/workflows/verify-codegen.yaml index 0f8fea071..cd1acb128 100644 --- a/.github/workflows/verify-codegen.yaml +++ b/.github/workflows/verify-codegen.yaml @@ -27,7 +27,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version-file: go.mod cache-dependency-path: go.sum From 60ea39042259d68bc5702657249fea82cee5f331 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 13:48:33 +0800 Subject: [PATCH 114/203] chore(deps): bump github.com/redis/go-redis/v9 from 9.2.1 to 9.5.1 (#813) Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.2.1 to 9.5.1. - [Release notes](https://github.com/redis/go-redis/releases) - [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md) - [Commits](https://github.com/redis/go-redis/compare/v9.2.1...v9.5.1) --- updated-dependencies: - dependency-name: github.com/redis/go-redis/v9 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f10a31e71..3f1b930ea 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/onsi/ginkgo/v2 v2.16.0 github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 - github.com/redis/go-redis/v9 v9.2.1 + github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 k8s.io/api v0.28.2 k8s.io/apimachinery v0.28.2 diff --git a/go.sum b/go.sum index a6c484cc4..82a082e78 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= -github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= From 69c549e96eab545ff489a59eb4ab41dbfbce3bd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:50:13 +0800 Subject: [PATCH 115/203] chore(deps): bump jlumbroso/free-disk-space from 1.3.0 to 1.3.1 (#812) Bumps [jlumbroso/free-disk-space](https://github.com/jlumbroso/free-disk-space) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/jlumbroso/free-disk-space/releases) - [Commits](https://github.com/jlumbroso/free-disk-space/compare/v1.3.0...v1.3.1) --- updated-dependencies: - dependency-name: jlumbroso/free-disk-space dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/verify-codegen.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/verify-codegen.yaml b/.github/workflows/verify-codegen.yaml index cd1acb128..aeb3e0c23 100644 --- a/.github/workflows/verify-codegen.yaml +++ b/.github/workflows/verify-codegen.yaml @@ -14,7 +14,7 @@ jobs: steps: - name: Free disk space - uses: jlumbroso/free-disk-space@v1.3.0 + uses: jlumbroso/free-disk-space@v1.3.1 with: tool-cache: true android: true From e4d5aec6713537f8ca1b11aa6855437246d7438f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:51:05 +0800 Subject: [PATCH 116/203] chore(deps): bump golangci/golangci-lint-action from 3 to 4 (#810) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 3 to 4. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v3...v4) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 6d0c17f28..afb7d8df5 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -50,7 +50,7 @@ jobs: cache: false - name: Run GolangCI-Lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v4 with: version: v1.54.0 From 6fb1bdbfee021587fb0e4e912cdf7c8bd931e742 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:28:07 +0800 Subject: [PATCH 117/203] chore(deps): bump helm/kind-action from 1.5.0 to 1.9.0 (#824) Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.5.0 to 1.9.0. - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](https://github.com/helm/kind-action/compare/v1.5.0...v1.9.0) --- updated-dependencies: - dependency-name: helm/kind-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e-chainsaw.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/validate-example.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index fde2d1489..ebf73029a 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -52,7 +52,7 @@ jobs: # uses: shogo82148/actions-setup-redis@v1 - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.5.0 + uses: helm/kind-action@v1.9.0 with: config: tests/_config/kind-config.yaml cluster_name: kind diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index eb4005b9f..370c15c00 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -35,7 +35,7 @@ jobs: sudo mv kubectl /usr/local/bin/ - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.5.0 + uses: helm/kind-action@v1.9.0 with: config: tests/_config/kind-config.yaml cluster_name: kind diff --git a/.github/workflows/validate-example.yaml b/.github/workflows/validate-example.yaml index 4b8efe74e..d6ec8acad 100644 --- a/.github/workflows/validate-example.yaml +++ b/.github/workflows/validate-example.yaml @@ -28,7 +28,7 @@ jobs: sudo mv kubectl /usr/local/bin/ - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.5.0 + uses: helm/kind-action@v1.9.0 with: cluster_name: kind From d121d8698862ba1594b463e035c122da3af78644 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:28:49 +0800 Subject: [PATCH 118/203] chore(deps): bump docker/setup-buildx-action from 2 to 3 (#825) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index afb7d8df5..2a0e86482 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -95,7 +95,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build multi-arch image uses: docker/build-push-action@v2 From 044d389b4da6b06e13d2c7c326dbf29df19661c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:29:14 +0800 Subject: [PATCH 119/203] chore(deps): bump codecov/codecov-action from 3 to 4 (#823) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3...v4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 2a0e86482..f16164b6b 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -33,7 +33,7 @@ jobs: - name: Run Go Tests with coverage run: go test ./... -coverprofile=coverage.txt -covermode=atomic - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: file: ./coverage.txt fail_ci_if_error: false From fd786066f85fb8ca86399119357fbbd2de9ea4d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:29:42 +0800 Subject: [PATCH 120/203] chore(deps): bump github.com/onsi/gomega from 1.30.0 to 1.31.1 (#820) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.30.0 to 1.31.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.30.0...v1.31.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3f1b930ea..dbeaf227a 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/banzaicloud/k8s-objectmatcher v1.7.0 github.com/go-logr/logr v1.4.1 github.com/onsi/ginkgo/v2 v2.16.0 - github.com/onsi/gomega v1.30.0 + github.com/onsi/gomega v1.31.1 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index 82a082e78..2aec7c437 100644 --- a/go.sum +++ b/go.sum @@ -161,8 +161,8 @@ github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From 61d89f40504686a95d8ebe66781239d9b3b1bef3 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 11 Mar 2024 19:08:56 +0800 Subject: [PATCH 121/203] fix: sentinel waiting for replication pod got ready (#806) * fix: sentinel waiting for replication pod got ready Signed-off-by: drivebyer * avoid nil pointer Signed-off-by: drivebyer * fix for linter Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- controllers/redissentinel_controller.go | 8 ++++++++ k8sutils/redis-replication.go | 16 ++++++++++++++++ .../teardown/redis-sentinel/sentinel.yaml | 5 +++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 55d4ee7d9..b1aa0a620 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -43,6 +43,14 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{RequeueAfter: time.Second * 10}, nil } + if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, r.K8sClient, &client.ObjectKey{ + Namespace: instance.Namespace, + Name: instance.Spec.RedisSentinelConfig.RedisReplicationName, + }) { + reqLogger.Info("Redis Replication is specified but not ready, so will reconcile again in 10 seconds") + return ctrl.Result{RequeueAfter: time.Second * 10}, nil + } + // Get total Sentinel Replicas // sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel") diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 5fa84f53e..9f47f85dd 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -1,10 +1,14 @@ package k8sutils import ( + "context" + redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" ) // CreateReplicationService method will create replication service for Redis @@ -194,3 +198,15 @@ func generateRedisReplicationInitContainerParams(cr *redisv1beta2.RedisReplicati } return initcontainerProp } + +func IsRedisReplicationReady(ctx context.Context, ki kubernetes.Interface, o *client.ObjectKey) bool { + // statefulset name the same as the redis replication name + sts, err := ki.AppsV1().StatefulSets(o.Namespace).Get(ctx, o.Name, metav1.GetOptions{}) + if err != nil { + return false + } + if sts.Status.ReadyReplicas != *sts.Spec.Replicas { + return false + } + return true +} diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml index d18d07f58..ca09db7f9 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml @@ -8,8 +8,9 @@ spec: podSecurityContext: runAsUser: 1000 fsGroup: 1000 - redisSentinelConfig: - redisReplicationName : redis-replication + # If we specify the redisReplicationName, we should wait for the redis cluster to be ready before deploying the sentinel +# redisSentinelConfig: +# redisReplicationName : redis-replication kubernetesConfig: image: quay.io/opstree/redis-sentinel:latest imagePullPolicy: Always From 1dae4235b16659ed792ce90580652efb733c7528 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:39:10 +0530 Subject: [PATCH 122/203] refactor(client): Use interface (#804) Signed-off-by: Shubham Gupta --- k8sutils/client.go | 4 ++-- k8sutils/redis.go | 2 +- main.go | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/k8sutils/client.go b/k8sutils/client.go index a12031004..0730f1af6 100644 --- a/k8sutils/client.go +++ b/k8sutils/client.go @@ -29,11 +29,11 @@ func GenerateK8sDynamicClient(configProvider K8sConfigProvider) (dynamic.Interfa } // GenerateK8sConfig will load the kube config file -func GenerateK8sConfig() (*rest.Config, error) { +func GenerateK8sConfig() K8sConfigProvider { loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() // if you want to change the loading rules (which files in which order), you can do so here configOverrides := &clientcmd.ConfigOverrides{} // if you want to change override values or bind them to flags, there are methods to help you kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides) - return kubeConfig.ClientConfig() + return kubeConfig.ClientConfig } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index ddca1b8ed..3de6e2787 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -362,7 +362,7 @@ func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1 execOut bytes.Buffer execErr bytes.Buffer ) - config, err := GenerateK8sConfig() + config, err := GenerateK8sConfig()() if err != nil { logger.Error(err, "Could not find pod to execute") return diff --git a/main.go b/main.go index 0111770e5..1507e584e 100644 --- a/main.go +++ b/main.go @@ -96,13 +96,13 @@ func main() { os.Exit(1) } - k8sclient, err := k8sutils.GenerateK8sClient(k8sutils.GenerateK8sConfig) + k8sclient, err := k8sutils.GenerateK8sClient(k8sutils.GenerateK8sConfig()) if err != nil { setupLog.Error(err, "unable to create k8s client") os.Exit(1) } - dk8sClient, err := k8sutils.GenerateK8sDynamicClient(k8sutils.GenerateK8sConfig) + dk8sClient, err := k8sutils.GenerateK8sDynamicClient(k8sutils.GenerateK8sConfig()) if err != nil { setupLog.Error(err, "unable to create k8s dynamic client") os.Exit(1) From 94afadd506a8a886b5c3c34054641b26d3bde2bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 21:38:50 +0800 Subject: [PATCH 123/203] chore(deps): bump docker/build-push-action from 2 to 5 (#826) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2 to 5. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v2...v5) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index f16164b6b..01e062ffb 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -98,7 +98,7 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Build multi-arch image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: context: . platforms: linux/arm64,linux/amd64 From 96c1b1552685c24ac8fc2ad551dc7f4ad42bf960 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 10:31:50 +0800 Subject: [PATCH 124/203] chore(deps): bump google.golang.org/protobuf from 1.30.0 to 1.33.0 (#828) Bumps google.golang.org/protobuf from 1.30.0 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dbeaf227a..1214a3755 100644 --- a/go.mod +++ b/go.mod @@ -67,7 +67,7 @@ require ( golang.org/x/tools v0.17.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 2aec7c437..ac5a0cc2d 100644 --- a/go.sum +++ b/go.sum @@ -312,8 +312,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 1cf27bbf089eece85d343de8e69c5a574d419b4d Mon Sep 17 00:00:00 2001 From: Jami Karvanen Date: Fri, 15 Mar 2024 07:37:58 +0200 Subject: [PATCH 125/203] fix: m/s replication when using ipv6 (#827) * Delete unnecessary brackets wrapping the IPv6 address Signed-off-by: Jami Karvanen * Extract redis address formatting into separate getRedisServerAddress function Signed-off-by: Jami Karvanen * Add tests for getRedisServerAddress Signed-off-by: Jami Karvanen * Use getRedisServerAddress also in cluster-scaling.go Signed-off-by: Jami Karvanen --------- Signed-off-by: Jami Karvanen --- k8sutils/cluster-scaling.go | 16 ++++----- k8sutils/redis.go | 27 ++++++++++----- k8sutils/redis_test.go | 67 ++++++++++++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 17 deletions(-) diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index 6e9303bc3..6699a5a75 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -35,7 +35,7 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(transferPOD, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, transferPOD)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, transferPOD, *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -157,7 +157,7 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, pod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, pod, *cr.Spec.Port)) } cmd = append(cmd, "--cluster-use-empty-masters") @@ -209,7 +209,7 @@ func RebalanceRedisCluster(client kubernetes.Interface, logger logr.Logger, cr * if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, pod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, pod, *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -247,8 +247,8 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log cmd = append(cmd, getRedisHostname(newPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, newPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) - cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, newPod, *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, existingPod, *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { @@ -326,7 +326,7 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, existingPod, *cr.Spec.Port)) } for _, followerNodeID := range followerNodeIDs { @@ -356,7 +356,7 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(existingPod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, existingPod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, existingPod, *cr.Spec.Port)) } removePodNodeID := getRedisNodeID(ctx, client, logger, cr, removePod) @@ -417,7 +417,7 @@ func ClusterFailover(ctx context.Context, client kubernetes.Interface, logger lo if *cr.Spec.ClusterVersion == "v7" { cmd = append(cmd, getRedisHostname(pod, cr, "leader")+fmt.Sprintf(":%d", *cr.Spec.Port)) } else { - cmd = append(cmd, getRedisServerIP(client, logger, pod)+fmt.Sprintf(":%d", *cr.Spec.Port)) + cmd = append(cmd, getRedisServerAddress(client, logger, pod, *cr.Spec.Port)) } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 3de6e2787..ee0db0a17 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -47,13 +47,24 @@ func getRedisServerIP(client kubernetes.Interface, logger logr.Logger, redisInfo // If we're NOT IPv4, assume we're IPv6.. if net.ParseIP(redisIP).To4() == nil { logger.V(1).Info("Redis is using IPv6", "ip", redisIP) - redisIP = fmt.Sprintf("[%s]", redisIP) } logger.V(1).Info("Successfully got the IP for Redis", "ip", redisIP) return redisIP } +func getRedisServerAddress(client kubernetes.Interface, logger logr.Logger, rd RedisDetails, port int) string { + ip := getRedisServerIP(client, logger, rd) + format := "%s:%d" + + // if ip is IPv6, wrap it in brackets + if net.ParseIP(ip).To4() == nil { + format = "[%s]:%d" + } + + return fmt.Sprintf(format, ip, port) +} + // getRedisHostname will return the complete FQDN for redis func getRedisHostname(redisInfo RedisDetails, cr *redisv1beta2.RedisCluster, role string) string { fqdn := fmt.Sprintf("%s.%s-%s-headless.%s.svc", redisInfo.PodName, cr.ObjectMeta.Name, role, cr.Namespace) @@ -85,7 +96,7 @@ func CreateMultipleLeaderRedisCommand(client kubernetes.Interface, logger logr.L if cr.Spec.ClusterVersion != nil && *cr.Spec.ClusterVersion == "v7" { address = getRedisHostname(RedisDetails{PodName: podName, Namespace: cr.Namespace}, cr, "leader") + fmt.Sprintf(":%d", *cr.Spec.Port) } else { - address = getRedisServerIP(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}) + fmt.Sprintf(":%d", *cr.Spec.Port) + address = getRedisServerAddress(client, logger, RedisDetails{PodName: podName, Namespace: cr.Namespace}, *cr.Spec.Port) } cmd = append(cmd, address) } @@ -144,8 +155,8 @@ func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logg followerAddress = getRedisHostname(followerPod, cr, "follower") + fmt.Sprintf(":%d", *cr.Spec.Port) leaderAddress = getRedisHostname(leaderPod, cr, "leader") + fmt.Sprintf(":%d", *cr.Spec.Port) } else { - followerAddress = getRedisServerIP(client, logger, followerPod) + fmt.Sprintf(":%d", *cr.Spec.Port) - leaderAddress = getRedisServerIP(client, logger, leaderPod) + fmt.Sprintf(":%d", *cr.Spec.Port) + followerAddress = getRedisServerAddress(client, logger, followerPod, *cr.Spec.Port) + leaderAddress = getRedisServerAddress(client, logger, leaderPod, *cr.Spec.Port) } cmd = append(cmd, followerAddress, leaderAddress, "--cluster-slave") @@ -340,14 +351,14 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(client, logger, redisInfo) + fmt.Sprintf(":%d", *cr.Spec.Port), + Addr: getRedisServerAddress(client, logger, redisInfo, *cr.Spec.Port), Password: pass, DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(client, logger, redisInfo) + fmt.Sprintf(":%d", *cr.Spec.Port), + Addr: getRedisServerAddress(client, logger, redisInfo, *cr.Spec.Port), Password: "", DB: 0, TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), @@ -459,14 +470,14 @@ func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Lo logger.Error(err, "Error in getting redis password") } redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", + Addr: getRedisServerAddress(client, logger, redisInfo, 6379), Password: pass, DB: 0, TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), }) } else { redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerIP(client, logger, redisInfo) + ":6379", + Addr: getRedisServerAddress(client, logger, redisInfo, 6379), Password: "", DB: 0, TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 14c0b2717..732654592 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -90,7 +90,7 @@ func TestGetRedisServerIP(t *testing.T) { PodName: "redis-pod", Namespace: "default", }, - expectedIP: "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]", + expectedIP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", expectEmpty: false, }, { @@ -141,6 +141,71 @@ func TestGetRedisServerIP(t *testing.T) { } } +func TestGetRedisServerAddress(t *testing.T) { + tests := []struct { + name string + setup func() *k8sClientFake.Clientset + redisInfo RedisDetails + expectedAddr string + expectEmpty bool + }{ + { + name: "Successfully retrieve IPv4 URI", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "192.168.1.1", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectedAddr: "192.168.1.1:6379", + expectEmpty: false, + }, + { + name: "Successfully retrieve IPv6 URI", + setup: func() *k8sClientFake.Clientset { + return k8sClientFake.NewSimpleClientset(&corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-pod", + Namespace: "default", + }, + Status: corev1.PodStatus{ + PodIP: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + }, + }) + }, + redisInfo: RedisDetails{ + PodName: "redis-pod", + Namespace: "default", + }, + expectedAddr: "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:6379", + expectEmpty: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + client := tt.setup() + logger := testr.New(t) + redisIP := getRedisServerAddress(client, logger, tt.redisInfo, 6379) + + if tt.expectEmpty { + assert.Empty(t, redisIP, "Expected an empty address") + } else { + assert.Equal(t, tt.expectedAddr, redisIP, "Expected and actual address do not match") + } + }) + } +} + func TestGetRedisHostname(t *testing.T) { tests := []struct { name string From e8b1ffffeeb93da57f445404218740782b6edb07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 16:14:59 +0530 Subject: [PATCH 126/203] chore(deps): bump github.com/banzaicloud/k8s-objectmatcher from 1.7.0 to 1.8.0 (#819) chore(deps): bump github.com/banzaicloud/k8s-objectmatcher Bumps [github.com/banzaicloud/k8s-objectmatcher](https://github.com/banzaicloud/k8s-objectmatcher) from 1.7.0 to 1.8.0. - [Commits](https://github.com/banzaicloud/k8s-objectmatcher/compare/v1.7.0...v1.8.0) --- updated-dependencies: - dependency-name: github.com/banzaicloud/k8s-objectmatcher dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 1214a3755..80f6df4d4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/OT-CONTAINER-KIT/redis-operator go 1.21 require ( - github.com/banzaicloud/k8s-objectmatcher v1.7.0 + github.com/banzaicloud/k8s-objectmatcher v1.8.0 github.com/go-logr/logr v1.4.1 github.com/onsi/ginkgo/v2 v2.16.0 github.com/onsi/gomega v1.31.1 diff --git a/go.sum b/go.sum index ac5a0cc2d..91c44efa4 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/banzaicloud/k8s-objectmatcher v1.7.0 h1:6ufo47TaPC0jXJPg8d8/oooCy1ma3vEfM0J8ZbomKaw= -github.com/banzaicloud/k8s-objectmatcher v1.7.0/go.mod h1:DSctpi6o9FqTfX7RluuEBeRLUahoDC7JavCeuu6Y+sg= +github.com/banzaicloud/k8s-objectmatcher v1.8.0 h1:Nugn25elKtPMTA2br+JgHNeSQ04sc05MDPmpJnd1N2A= +github.com/banzaicloud/k8s-objectmatcher v1.8.0/go.mod h1:p2LSNAjlECf07fbhDyebTkPUIYnU05G+WfGgkTmgeMg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -121,7 +121,6 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= From edc308332262471d7b479ab634471c8e6f0b461d Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 18 Mar 2024 22:12:09 +0800 Subject: [PATCH 127/203] fix: ensure sentinel does not observes the failover progress in replication cluster (#803) * fix: ensure sentinel does not observes the failover progress in replication cluster Signed-off-by: drivebyer * add e2e Signed-off-by: drivebyer * enhance check Signed-off-by: drivebyer * check master through sentinel Signed-off-by: drivebyer --------- Signed-off-by: drivebyer Signed-off-by: drivebyer --- .github/workflows/e2e-chainsaw.yml | 1 + controllers/redissentinel_controller.go | 9 ++-- k8sutils/redis-replication.go | 14 ++++-- .../v1beta2/ha-failover/chainsaw-test.yaml | 49 +++++++++++++++++++ .../v1beta2/ha-failover/cli-pod.yaml | 14 ++++++ .../v1beta2/ha-failover/replication.yaml | 27 ++++++++++ .../v1beta2/ha-failover/sentinel.yaml | 23 +++++++++ 7 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index ebf73029a..c939d6815 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -20,6 +20,7 @@ jobs: - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ - ./tests/e2e-chainsaw/v1beta2/password/ - ./tests/e2e-chainsaw/v1beta2/ha-setup/ + - ./tests/e2e-chainsaw/v1beta2/ha-failover/ - ./tests/e2e-chainsaw/v1beta2/nodeport/ - ./tests/e2e-chainsaw/v1beta2/pvc-name/ - ./tests/e2e-chainsaw/v1beta2/keep-pvc/ diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index b1aa0a620..ff2292f29 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -43,10 +43,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{RequeueAfter: time.Second * 10}, nil } - if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, r.K8sClient, &client.ObjectKey{ - Namespace: instance.Namespace, - Name: instance.Spec.RedisSentinelConfig.RedisReplicationName, - }) { + if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, reqLogger, r.K8sClient, r.Dk8sClient, instance) { reqLogger.Info("Redis Replication is specified but not ready, so will reconcile again in 10 seconds") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } @@ -79,8 +76,8 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } - reqLogger.Info("Will reconcile redis operator in again 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + reqLogger.Info("Will reconcile after 600 seconds") + return ctrl.Result{RequeueAfter: time.Second * 600}, nil } // SetupWithManager sets up the controller with the Manager. diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 9f47f85dd..4a780de06 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -5,10 +5,10 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/go-logr/logr" + "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/utils/pointer" - "sigs.k8s.io/controller-runtime/pkg/client" ) // CreateReplicationService method will create replication service for Redis @@ -199,14 +199,20 @@ func generateRedisReplicationInitContainerParams(cr *redisv1beta2.RedisReplicati return initcontainerProp } -func IsRedisReplicationReady(ctx context.Context, ki kubernetes.Interface, o *client.ObjectKey) bool { +func IsRedisReplicationReady(ctx context.Context, logger logr.Logger, ki kubernetes.Interface, di dynamic.Interface, rs *redisv1beta2.RedisSentinel) bool { // statefulset name the same as the redis replication name - sts, err := ki.AppsV1().StatefulSets(o.Namespace).Get(ctx, o.Name, metav1.GetOptions{}) + sts, err := GetStatefulSet(rs.Namespace, rs.Spec.RedisSentinelConfig.RedisReplicationName, ki) if err != nil { return false } if sts.Status.ReadyReplicas != *sts.Spec.Replicas { return false } + // Enhanced check: When the pod is ready, it may not have been + // created as part of a replication cluster, so we should verify + // whether there is an actual master node. + if master := getRedisReplicationMasterIP(ctx, ki, logger, rs, di); master == "" { + return false + } return true } diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml new file mode 100644 index 000000000..f4fd45914 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml @@ -0,0 +1,49 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-ha-failover +spec: + steps: + - try: + - apply: + file: replication.yaml + - apply: + file: sentinel.yaml + - create: + file: cli-pod.yaml + + - name: Sleep for 3 minutes + try: + - sleep: + duration: 3m + + - name: Test sentinel monitoring + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 sentinel master myMaster | grep -A 1 'flags' | tail -n 1 + check: + ($stdout=='master'): true + + # New created cluster, the first pod is master + - name: Terminate the redis-replication-0 pod + try: + - script: + timeout: 10s + content: | + kubectl --namespace ${NAMESPACE} delete pod redis-replication-0 + + - name: Sleep for 3 minutes + try: + - sleep: + duration: 3m + + - name: Test sentinel monitoring + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 sentinel master myMaster | grep -A 1 'flags' | tail -n 1 + check: + ($stdout=='master'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml new file mode 100644 index 000000000..e8501253e --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Pod +metadata: + name: redis + labels: + app: redis +spec: + containers: + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml new file mode 100644 index 000000000..3fb33dcac --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +spec: + clusterSize: 3 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml new file mode 100644 index 000000000..955066544 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: redis-sentinel +spec: + clusterSize: 1 + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + redisSentinelConfig: + redisReplicationName : redis-replication + quorum: "1" + kubernetesConfig: + image: quay.io/opstree/redis-sentinel:latest + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi \ No newline at end of file From 17abdf401ed0f61bff19e8f5c960b56518929e2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:00:23 +0800 Subject: [PATCH 128/203] chore(deps): bump github.com/onsi/gomega from 1.31.1 to 1.32.0 (#834) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.31.1 to 1.32.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.31.1...v1.32.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 80f6df4d4..ece74a259 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/banzaicloud/k8s-objectmatcher v1.8.0 github.com/go-logr/logr v1.4.1 github.com/onsi/ginkgo/v2 v2.16.0 - github.com/onsi/gomega v1.31.1 + github.com/onsi/gomega v1.32.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index 91c44efa4..71caed038 100644 --- a/go.sum +++ b/go.sum @@ -160,8 +160,8 @@ github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= -github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= +github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= +github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= From 2ee43243be1a6a13de69e26fc53c3f5cde3c66b0 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 24 Mar 2024 11:40:25 +0530 Subject: [PATCH 129/203] test(client): Add redis mock client (#841) * test(Client): Add redis mock client Signed-off-by: Shubham Gupta * fake commit Signed-off-by: Shubham Gupta * fake commit Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- go.mod | 1 + go.sum | 2 + k8sutils/cluster-scaling.go | 4 ++ k8sutils/cluster-scaling_test.go | 63 ++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 k8sutils/cluster-scaling_test.go diff --git a/go.mod b/go.mod index ece74a259..245bbcb6d 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-redis/redismock/v9 v9.2.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect diff --git a/go.sum b/go.sum index 71caed038..0ba4a0e12 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw= +github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index 6699a5a75..e5e86726c 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -386,6 +386,10 @@ func VerifyLeaderPod(ctx context.Context, client kubernetes.Interface, logger lo redisClient := configureRedisClient(client, logger, cr, podName) defer redisClient.Close() + return verifyLeaderPodInfo(ctx, redisClient, logger, podName) +} + +func verifyLeaderPodInfo(ctx context.Context, redisClient *redis.Client, logger logr.Logger, podName string) bool { info, err := redisClient.Info(ctx, "replication").Result() if err != nil { logger.Error(err, "Failed to Get the role Info of the", "redis pod", podName) diff --git a/k8sutils/cluster-scaling_test.go b/k8sutils/cluster-scaling_test.go new file mode 100644 index 000000000..ca8107712 --- /dev/null +++ b/k8sutils/cluster-scaling_test.go @@ -0,0 +1,63 @@ +package k8sutils + +import ( + "context" + "testing" + + "github.com/go-logr/logr" + "github.com/go-redis/redismock/v9" + redis "github.com/redis/go-redis/v9" + "github.com/stretchr/testify/assert" +) + +func Test_verifyLeaderPodInfo(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + section string + response string + err error + expectedBool bool + }{ + { + name: "is master", + section: "replication", + response: "role:master\r\n", + expectedBool: true, + }, + { + name: "is replica", + section: "replication", + response: "role:slave\r\n", + expectedBool: false, + }, + { + name: "redis info error", + section: "replication", + err: redis.ErrClosed, + expectedBool: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + client, mock := redismock.NewClientMock() + + if tt.err != nil { + mock.ExpectInfo(tt.section).SetErr(tt.err) + } else { + mock.ExpectInfo(tt.section).SetVal(tt.response) + } + + result := verifyLeaderPodInfo(ctx, client, logger, "test-pod") + + assert.Equal(t, tt.expectedBool, result, "Test case: "+tt.name) + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unmet expectations: %s", err) + } + }) + } +} From ff9166508b135bb2554516bbb2e45d94a2c827d7 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 24 Mar 2024 11:40:38 +0530 Subject: [PATCH 130/203] chore: use redis client library (#840) * chore: use appropriate way to calulate slots Signed-off-by: Shubham Gupta * chore: remove unncessary conversion Signed-off-by: Shubham Gupta * chore: improve slaveid calculation Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- k8sutils/cluster-scaling.go | 48 ++++++++++--------------------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index e5e86726c..f95163758 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -86,33 +86,22 @@ func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logg redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() - redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() + + redisSlots, err := redisClient.ClusterSlots(ctx).Result() if err != nil { - logger.Error(err, "Failed to Get Cluster Info") + logger.Error(err, "Failed to Get Cluster Slots") return "" } - - // Split the Redis cluster info into lines - lines := strings.Split(redisClusterInfo, "\n") - // Iterate through all lines - for _, line := range lines { - if strings.Contains(line, "master") && strings.Contains(line, "connected") { // Check if this line is a master node - parts := strings.Fields(line) - if parts[0] == nodeID { // Check if this is the node we're interested in - for _, conn := range parts[8:] { - slotRange := strings.Split(conn, "-") - if len(slotRange) < 2 { - totalSlots = totalSlots + 1 - } else { - start, _ := strconv.Atoi(slotRange[0]) - end, _ := strconv.Atoi(slotRange[1]) - totalSlots = totalSlots + end - start + 1 - } - } + for _, slot := range redisSlots { + for _, node := range slot.Nodes { + if node.ID == nodeID { + // Each slot range is a continuous block managed by the node + totalSlots += slot.End - slot.Start + 1 break } } } + logger.V(1).Info("Total cluster slots to be transferred from", "node", nodeID, "is", totalSlots) return strconv.Itoa(totalSlots) } @@ -270,25 +259,12 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log func getAttachedFollowerNodeIDs(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, masterNodeID string) []string { redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") defer redisClient.Close() - redisClusterInfo, err := redisClient.ClusterNodes(ctx).Result() + + slaveIDs, err := redisClient.ClusterSlaves(ctx, masterNodeID).Result() if err != nil { - logger.Error(err, "Failed to Get Cluster Info") + logger.Error(err, "Failed to get attached follower node IDs", "masterNodeID", masterNodeID) return nil } - - slaveIDs := []string{} - // Split the Redis cluster info into lines - lines := strings.Split(redisClusterInfo, "\n") - - for _, line := range lines { - if strings.Contains(line, "slave") && strings.Contains(line, "connected") { - parts := strings.Fields(line) - if len(parts) >= 3 && parts[3] == masterNodeID { - slaveIDs = append(slaveIDs, parts[0]) - } - } - } - logger.V(1).Info("Slaves Nodes attached to", "node", masterNodeID, "are", slaveIDs) return slaveIDs } From a521613535558fb9c09948d23c1a195f95bc0a6c Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Mon, 25 Mar 2024 09:14:08 +0530 Subject: [PATCH 131/203] test: Show Operator Failed Logs (#843) Signed-off-by: Shubham Gupta --- .../acl-user/redis-cluster/chainsaw-test.yaml | 7 +++++ .../v1beta2/ha-failover/chainsaw-test.yaml | 30 ++++++++++++++++++- .../setup/redis-cluster/chainsaw-test.yaml | 10 ++++++- .../redis-replication/chainsaw-test.yaml | 7 +++++ .../setup/redis-sentinel/chainsaw-test.yaml | 9 +++++- 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml index 46bf2141c..f83bfe75f 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml @@ -25,6 +25,13 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Sleep for five minutes try: diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml index f4fd45914..3fb05ca44 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml @@ -11,6 +11,13 @@ spec: file: sentinel.yaml - create: file: cli-pod.yaml + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Sleep for 3 minutes try: @@ -25,6 +32,13 @@ spec: kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 sentinel master myMaster | grep -A 1 'flags' | tail -n 1 check: ($stdout=='master'): true + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs # New created cluster, the first pod is master - name: Terminate the redis-replication-0 pod @@ -33,6 +47,13 @@ spec: timeout: 10s content: | kubectl --namespace ${NAMESPACE} delete pod redis-replication-0 + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Sleep for 3 minutes try: @@ -46,4 +67,11 @@ spec: content: | kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 sentinel master myMaster | grep -A 1 'flags' | tail -n 1 check: - ($stdout=='master'): true \ No newline at end of file + ($stdout=='master'): true + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index f9f8b5130..c036ab288 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -17,6 +17,13 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Sleep for five minutes try: @@ -127,4 +134,5 @@ spec: content: | kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 check: - ($stdout=='OK'): true \ No newline at end of file + ($stdout=='OK'): true + diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml index bd117a79b..ff7822ce7 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml @@ -15,6 +15,13 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Ping Replicated Cluster try: diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml index 5e2472bb1..c3a26553d 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml @@ -12,4 +12,11 @@ spec: - assert: file: ready-sts.yaml - assert: - file: ready-svc.yaml \ No newline at end of file + file: ready-svc.yaml + catch: + - description: Redis Operator Logs + podLogs: + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs \ No newline at end of file From a6d372d1b40fcf73fa252e75a6e7c61bbdec4944 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:34:01 +0800 Subject: [PATCH 132/203] chore(deps): bump github.com/onsi/ginkgo/v2 from 2.16.0 to 2.17.1 (#844) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.16.0 to 2.17.1. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.16.0...v2.17.1) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 245bbcb6d..1854b9982 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,8 @@ go 1.21 require ( github.com/banzaicloud/k8s-objectmatcher v1.8.0 github.com/go-logr/logr v1.4.1 - github.com/onsi/ginkgo/v2 v2.16.0 + github.com/go-redis/redismock/v9 v9.2.0 + github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 @@ -31,7 +32,6 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-redis/redismock/v9 v9.2.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect diff --git a/go.sum b/go.sum index 0ba4a0e12..8fdecd9d3 100644 --- a/go.sum +++ b/go.sum @@ -155,11 +155,15 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM= -github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= +github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= @@ -323,6 +327,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From aeba01968b15ecc63e9d477f102d9d62df550eb6 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Fri, 29 Mar 2024 08:06:55 +0530 Subject: [PATCH 133/203] test(client): Add Redis Mock Test code (#842) * test(client) : Add Redis Mock Test code Signed-off-by: Shubham Gupta * test(client): Add for followers node id's Signed-off-by: Shubham Gupta * test: cover checkAttachedSlave Signed-off-by: Shubham Gupta * test: Add redis server role Signed-off-by: Shubham Gupta * test: add redis operator pod logs Signed-off-by: Shubham Gupta * chore: add log statement Signed-off-by: Shubham Gupta * chore: fix logs Signed-off-by: Shubham Gupta * test: fix unit test Signed-off-by: Shubham Gupta * fix: return data Signed-off-by: Shubham Gupta * fix the role Signed-off-by: Shubham Gupta * chore: remove comment Signed-off-by: Shubham Gupta * refactor: move logger to params Signed-off-by: Shubham Gupta * test: Add test Get statefulset Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- controllers/rediscluster_controller.go | 4 +- controllers/redisreplication_controller.go | 2 +- k8sutils/cluster-scaling.go | 27 ++-- k8sutils/cluster-scaling_test.go | 166 +++++++++++++++++++++ k8sutils/redis-cluster.go | 5 +- k8sutils/redis-replication.go | 12 +- k8sutils/redis-sentinel.go | 15 +- k8sutils/redis-standalone.go | 10 +- k8sutils/redis.go | 76 +++++----- k8sutils/redis_test.go | 149 ++++++++++++++++++ k8sutils/statefulset.go | 15 +- k8sutils/statefulset_test.go | 97 ++++++++++++ 12 files changed, 504 insertions(+), 74 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 3cc478f93..c540e47e4 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -132,7 +132,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } - redisLeaderInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-leader", r.K8sClient) + redisLeaderInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-leader") if err != nil { if errors.IsNotFound(err) { return ctrl.Result{RequeueAfter: time.Second * 60}, nil @@ -164,7 +164,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } } - redisFollowerInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name+"-follower", r.K8sClient) + redisFollowerInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-follower") if err != nil { if errors.IsNotFound(err) { return ctrl.Result{RequeueAfter: time.Second * 60}, nil diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index d6f9b85cb..a57308e80 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -66,7 +66,7 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req // Set Pod distruptiuon Budget Later - redisReplicationInfo, err := k8sutils.GetStatefulSet(instance.Namespace, instance.ObjectMeta.Name, r.K8sClient) + redisReplicationInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index f95163758..da68c44a8 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -17,6 +17,9 @@ import ( // NOTE: when all slot been transferred, the node become slave of the first master node. func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, remove bool) { ctx := context.TODO() + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() + var cmd []string currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") @@ -62,7 +65,7 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re cmd = append(cmd, transferNodeID) // Cluster Slots - slot := getRedisClusterSlots(ctx, client, logger, cr, removeNodeID) + slot := getRedisClusterSlots(ctx, redisClient, logger, removeNodeID) cmd = append(cmd, "--cluster-slots") cmd = append(cmd, slot) @@ -81,12 +84,9 @@ func ReshardRedisCluster(client kubernetes.Interface, logger logr.Logger, cr *re } } -func getRedisClusterSlots(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeID string) string { +func getRedisClusterSlots(ctx context.Context, redisClient *redis.Client, logger logr.Logger, nodeID string) string { totalSlots := 0 - redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") - defer redisClient.Close() - redisSlots, err := redisClient.ClusterSlots(ctx).Result() if err != nil { logger.Error(err, "Failed to Get Cluster Slots") @@ -168,6 +168,8 @@ func RebalanceRedisClusterEmptyMasters(client kubernetes.Interface, logger logr. func CheckIfEmptyMasters(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { totalRedisLeaderNodes := CheckRedisNodeCount(ctx, client, logger, cr, "leader") + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() for i := 0; i < int(totalRedisLeaderNodes); i++ { pod := RedisDetails{ @@ -175,7 +177,7 @@ func CheckIfEmptyMasters(ctx context.Context, client kubernetes.Interface, logge Namespace: cr.Namespace, } podNodeID := getRedisNodeID(ctx, client, logger, cr, pod) - podSlots := getRedisClusterSlots(ctx, client, logger, cr, podNodeID) + podSlots := getRedisClusterSlots(ctx, redisClient, logger, podNodeID) if podSlots == "0" || podSlots == "" { logger.V(1).Info("Found Empty Redis Leader Node", "pod", pod) @@ -256,10 +258,7 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log } // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader -func getAttachedFollowerNodeIDs(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, masterNodeID string) []string { - redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") - defer redisClient.Close() - +func getAttachedFollowerNodeIDs(ctx context.Context, redisClient *redis.Client, logger logr.Logger, masterNodeID string) []string { slaveIDs, err := redisClient.ClusterSlaves(ctx, masterNodeID).Result() if err != nil { logger.Error(err, "Failed to get attached follower node IDs", "masterNodeID", masterNodeID) @@ -272,6 +271,8 @@ func getAttachedFollowerNodeIDs(ctx context.Context, client kubernetes.Interface // Remove redis follower node would remove all follower nodes of last leader node using redis-cli func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) { var cmd []string + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") existingPod := RedisDetails{ @@ -296,7 +297,7 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) lastLeaderPodNodeID := getRedisNodeID(ctx, client, logger, cr, lastLeaderPod) - followerNodeIDs := getAttachedFollowerNodeIDs(ctx, client, logger, cr, lastLeaderPodNodeID) + followerNodeIDs := getAttachedFollowerNodeIDs(ctx, redisClient, logger, lastLeaderPodNodeID) cmd = append(cmd, "--cluster", "del-node") if *cr.Spec.ClusterVersion == "v7" { @@ -316,6 +317,8 @@ func RemoveRedisFollowerNodesFromCluster(ctx context.Context, client kubernetes. // Remove redis cluster node would remove last node to the existing redis cluster using redis-cli func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, removePod RedisDetails) { var cmd []string + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() // currentRedisCount := CheckRedisNodeCount(ctx, client, logger, cr, "leader") existingPod := RedisDetails{ @@ -350,7 +353,7 @@ func RemoveRedisNodeFromCluster(ctx context.Context, client kubernetes.Interface cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) logger.V(1).Info("Redis cluster leader remove command is", "Command", cmd) - if getRedisClusterSlots(ctx, client, logger, cr, removePodNodeID) != "0" { + if getRedisClusterSlots(ctx, redisClient, logger, removePodNodeID) != "0" { logger.V(1).Info("Skipping execution remove leader not empty", "cmd", cmd) } executeCommand(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") diff --git a/k8sutils/cluster-scaling_test.go b/k8sutils/cluster-scaling_test.go index ca8107712..fe1bd3bd0 100644 --- a/k8sutils/cluster-scaling_test.go +++ b/k8sutils/cluster-scaling_test.go @@ -2,6 +2,7 @@ package k8sutils import ( "context" + "fmt" "testing" "github.com/go-logr/logr" @@ -61,3 +62,168 @@ func Test_verifyLeaderPodInfo(t *testing.T) { }) } } + +func Test_getRedisClusterSlots(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + nodeID string + clusterSlots []redis.ClusterSlot + clusterSlotsErr error + expectedResult string + }{ + { + name: "successful slot count", + nodeID: "node123", + clusterSlots: []redis.ClusterSlot{ + {Start: 0, End: 4999, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + {Start: 5000, End: 9999, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + }, + expectedResult: "10000", + }, + { + name: "error fetching cluster slots", + nodeID: "node123", + clusterSlotsErr: redis.ErrClosed, + expectedResult: "", + }, + { + name: "no slots for node", + nodeID: "node999", + clusterSlots: []redis.ClusterSlot{ + {Start: 0, End: 4999, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + }, + expectedResult: "0", + }, + { + name: "slots for multiple nodes", + nodeID: "node123", + clusterSlots: []redis.ClusterSlot{ + {Start: 0, End: 1999, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + {Start: 2000, End: 3999, Nodes: []redis.ClusterNode{{ID: "node456"}}}, + {Start: 4000, End: 5999, Nodes: []redis.ClusterNode{{ID: "node123"}, {ID: "node789"}}}, + }, + expectedResult: "4000", + }, + { + name: "single slot range", + nodeID: "node123", + clusterSlots: []redis.ClusterSlot{ + {Start: 100, End: 100, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + }, + expectedResult: "1", + }, + { + name: "mixed slot ranges", + nodeID: "node123", + clusterSlots: []redis.ClusterSlot{ + {Start: 0, End: 499, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + {Start: 500, End: 999, Nodes: []redis.ClusterNode{{ID: "node123"}, {ID: "node999"}}}, + {Start: 1000, End: 1499, Nodes: []redis.ClusterNode{{ID: "node999"}}}, + {Start: 1500, End: 1999, Nodes: []redis.ClusterNode{{ID: "node123"}}}, + }, + expectedResult: "1500", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.TODO() + client, mock := redismock.NewClientMock() + + if tt.clusterSlotsErr != nil { + mock.ExpectClusterSlots().SetErr(tt.clusterSlotsErr) + } else { + mock.ExpectClusterSlots().SetVal(tt.clusterSlots) + } + + result := getRedisClusterSlots(ctx, client, logger, tt.nodeID) + + assert.Equal(t, tt.expectedResult, result, "Test case: "+tt.name) + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unmet expectations: %s", err) + } + }) + } +} + +func Test_getAttachedFollowerNodeIDs(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + masterNodeID string + slaveNodeIDs []string + clusterSlavesErr error + expectedslaveNodeIDs []string + }{ + { + name: "successful retrieval of slave nodes", + masterNodeID: "master123", + slaveNodeIDs: []string{"slave1", "slave2"}, + expectedslaveNodeIDs: []string{"slave1", "slave2"}, + }, + { + name: "error fetching slave nodes", + masterNodeID: "master123", + clusterSlavesErr: redis.ErrClosed, + expectedslaveNodeIDs: nil, + }, + { + name: "no attached slave nodes", + masterNodeID: "master456", + slaveNodeIDs: []string{}, + expectedslaveNodeIDs: []string{}, + }, + { + name: "nil response for slave nodes", + masterNodeID: "masterNode123", + slaveNodeIDs: nil, + expectedslaveNodeIDs: nil, + clusterSlavesErr: nil, + }, + { + name: "large number of attached slave nodes", + masterNodeID: "master123", + slaveNodeIDs: generateLargeListOfSlaves(1000), // Helper function needed + expectedslaveNodeIDs: generateLargeListOfSlaves(1000), + }, + { + name: "invalid master node ID", + masterNodeID: "invalidMasterID", + slaveNodeIDs: nil, + expectedslaveNodeIDs: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + client, mock := redismock.NewClientMock() + + if tt.clusterSlavesErr != nil { + mock.ExpectClusterSlaves(tt.masterNodeID).SetErr(tt.clusterSlavesErr) + } else { + mock.ExpectClusterSlaves(tt.masterNodeID).SetVal(tt.slaveNodeIDs) + } + + result := getAttachedFollowerNodeIDs(ctx, client, logger, tt.masterNodeID) + + assert.ElementsMatch(t, tt.expectedslaveNodeIDs, result, "Test case: "+tt.name) + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unmet expectations: %s", err) + } + }) + } +} + +func generateLargeListOfSlaves(n int) []string { + var slaves []string + for i := 0; i < n; i++ { + slaves = append(slaves, fmt.Sprintf("slaveNode%d", i)) + } + return slaves +} diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index aae4cf5bf..f3dc5e973 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -270,14 +270,15 @@ func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta2.RedisClu annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( - cr.Namespace, + cl, + logger, + cr.GetNamespace(), objectMetaInfo, generateRedisClusterParams(cr, service.getReplicaCount(cr), service.ExternalConfig, service), redisClusterAsOwner(cr), generateRedisClusterInitContainerParams(cr), generateRedisClusterContainerParams(cl, logger, cr, service.SecurityContext, service.ReadinessProbe, service.LivenessProbe, service.RedisStateFulType), cr.Spec.Sidecars, - cl, ) if err != nil { logger.Error(err, "Cannot create statefulset for Redis", "Setup.Type", service.RedisStateFulType) diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 4a780de06..967c0925d 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -61,14 +61,16 @@ func CreateReplicationRedis(cr *redisv1beta2.RedisReplication, cl kubernetes.Int labels := getRedisLabels(cr.ObjectMeta.Name, replication, "replication", cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) - err := CreateOrUpdateStateFul(cr.Namespace, + err := CreateOrUpdateStateFul( + cl, + logger, + cr.GetNamespace(), objectMetaInfo, generateRedisReplicationParams(cr), redisReplicationAsOwner(cr), generateRedisReplicationInitContainerParams(cr), generateRedisReplicationContainerParams(cr), cr.Spec.Sidecars, - cl, ) if err != nil { logger.Error(err, "Cannot create replication statefulset for Redis") @@ -199,9 +201,9 @@ func generateRedisReplicationInitContainerParams(cr *redisv1beta2.RedisReplicati return initcontainerProp } -func IsRedisReplicationReady(ctx context.Context, logger logr.Logger, ki kubernetes.Interface, di dynamic.Interface, rs *redisv1beta2.RedisSentinel) bool { +func IsRedisReplicationReady(ctx context.Context, logger logr.Logger, client kubernetes.Interface, dClient dynamic.Interface, rs *redisv1beta2.RedisSentinel) bool { // statefulset name the same as the redis replication name - sts, err := GetStatefulSet(rs.Namespace, rs.Spec.RedisSentinelConfig.RedisReplicationName, ki) + sts, err := GetStatefulSet(client, logger, rs.GetNamespace(), rs.Spec.RedisSentinelConfig.RedisReplicationName) if err != nil { return false } @@ -211,7 +213,7 @@ func IsRedisReplicationReady(ctx context.Context, logger logr.Logger, ki kuberne // Enhanced check: When the pod is ready, it may not have been // created as part of a replication cluster, so we should verify // whether there is an actual master node. - if master := getRedisReplicationMasterIP(ctx, ki, logger, rs, di); master == "" { + if master := getRedisReplicationMasterIP(ctx, client, logger, rs, dClient); master == "" { return false } return true diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index ad0c754b6..2c0bf8605 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -68,14 +68,15 @@ func (service RedisSentinelSTS) CreateRedisSentinelSetup(ctx context.Context, cl annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, annotations) err := CreateOrUpdateStateFul( - cr.Namespace, + cl, + logger, + cr.GetNamespace(), objectMetaInfo, generateRedisSentinelParams(cr, service.getSentinelCount(cr), service.ExternalConfig, service.Affinity), redisSentinelAsOwner(cr), generateRedisSentinelInitContainerParams(cr), generateRedisSentinelContainerParams(ctx, client, logger, cr, service.ReadinessProbe, service.LivenessProbe, dcl), cr.Spec.Sidecars, - cl, ) if err != nil { logger.Error(err, "Cannot create Sentinel statefulset for Redis") @@ -324,7 +325,15 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac } else if len(masterPods) == 1 { realMasterPod = masterPods[0] } else { - realMasterPod = checkAttachedSlave(ctx, client, logger, &replicationInstance, masterPods) + for _, podName := range masterPods { + redisClient := configureRedisReplicationClient(client, logger, &replicationInstance, podName) + defer redisClient.Close() + + if checkAttachedSlave(ctx, redisClient, logger, podName) > 0 { + realMasterPod = podName + break + } + } } realMasterInfo := RedisDetails{ diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index a99a45b92..5aae864c8 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -7,10 +7,6 @@ import ( "k8s.io/utils/pointer" ) -//var ( -// enableMetrics bool -//) - // CreateStandaloneService method will create standalone service for Redis func CreateStandaloneService(cr *redisv1beta2.Redis, cl kubernetes.Interface) error { logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name) @@ -60,14 +56,16 @@ func CreateStandaloneRedis(cr *redisv1beta2.Redis, cl kubernetes.Interface) erro labels := getRedisLabels(cr.ObjectMeta.Name, standalone, "standalone", cr.ObjectMeta.Labels) annotations := generateStatefulSetsAnots(cr.ObjectMeta, cr.Spec.KubernetesConfig.IgnoreAnnotations) objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, annotations) - err := CreateOrUpdateStateFul(cr.Namespace, + err := CreateOrUpdateStateFul( + cl, + logger, + cr.GetNamespace(), objectMetaInfo, generateRedisStandaloneParams(cr), redisAsOwner(cr), generateRedisStandaloneInitContainerParams(cr), generateRedisStandaloneContainerParams(cr), cr.Spec.Sidecars, - cl, ) if err != nil { logger.Error(err, "Cannot create standalone statefulset for Redis") diff --git a/k8sutils/redis.go b/k8sutils/redis.go index ee0db0a17..b7f74ef05 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -488,7 +488,7 @@ func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Lo // Get Redis nodes by it's role i.e. master, slave and sentinel func GetRedisNodesByRole(ctx context.Context, cl kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, redisRole string) []string { - statefulset, err := GetStatefulSet(cr.Namespace, cr.Name, cl) + statefulset, err := GetStatefulSet(cl, logger, cr.GetNamespace(), cr.GetName()) if err != nil { logger.Error(err, "Failed to Get the Statefulset of the", "custom resource", cr.Name, "in namespace", cr.Namespace) } @@ -498,7 +498,9 @@ func GetRedisNodesByRole(ctx context.Context, cl kubernetes.Interface, logger lo for i := 0; i < int(replicas); i++ { podName := statefulset.Name + "-" + strconv.Itoa(i) - podRole := checkRedisServerRole(ctx, cl, logger, cr, podName) + redisClient := configureRedisReplicationClient(cl, logger, cr, podName) + defer redisClient.Close() + podRole := checkRedisServerRole(ctx, redisClient, logger, podName) if podRole == redisRole { pods = append(pods, podName) } @@ -508,57 +510,63 @@ func GetRedisNodesByRole(ctx context.Context, cl kubernetes.Interface, logger lo } // Check the Redis Server Role i.e. master, slave and sentinel -func checkRedisServerRole(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, podName string) string { - redisClient := configureRedisReplicationClient(client, logger, cr, podName) - defer redisClient.Close() - info, err := redisClient.Info(ctx, "replication").Result() +func checkRedisServerRole(ctx context.Context, redisClient *redis.Client, logger logr.Logger, podName string) string { + info, err := redisClient.Info(ctx, "Replication").Result() if err != nil { logger.Error(err, "Failed to Get the role Info of the", "redis pod", podName) + return "" } - lines := strings.Split(info, "\r\n") - role := "" for _, line := range lines { if strings.HasPrefix(line, "role:") { - role = strings.TrimPrefix(line, "role:") - break + role := strings.TrimPrefix(line, "role:") + logger.V(1).Info("Role of the Redis Pod", "pod", podName, "role", role) + return role } } - - return role + logger.Error(err, "Failed to find role from Info # Replication in", "redis pod", podName) + return "" } // checkAttachedSlave would return redis pod name which has slave -func checkAttachedSlave(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string) string { - for _, podName := range masterPods { - connected_slaves := "" - redisClient := configureRedisReplicationClient(client, logger, cr, podName) - defer redisClient.Close() - info, err := redisClient.Info(ctx, "replication").Result() - if err != nil { - logger.Error(err, "Failed to Get the connected slaves Info of the", "redis pod", podName) - } - - lines := strings.Split(info, "\r\n") +func checkAttachedSlave(ctx context.Context, redisClient *redis.Client, logger logr.Logger, podName string) int { + info, err := redisClient.Info(ctx, "Replication").Result() + if err != nil { + logger.Error(err, "Failed to get the connected slaves count of the", "redis pod", podName) + return -1 // return -1 if failed to get the connected slaves count + } - for _, line := range lines { - if strings.HasPrefix(line, "connected_slaves:") { - connected_slaves = strings.TrimPrefix(line, "connected_slaves:") - break + lines := strings.Split(info, "\r\n") + for _, line := range lines { + if strings.HasPrefix(line, "connected_slaves:") { + var connected_slaves int + connected_slaves, err = strconv.Atoi(strings.TrimPrefix(line, "connected_slaves:")) + if err != nil { + logger.Error(err, "Failed to convert the connected slaves count of the", "redis pod", podName) + return -1 } - } - - nums, _ := strconv.Atoi(connected_slaves) - if nums > 0 { - return podName + logger.V(1).Info("Connected Slaves of the Redis Pod", "pod", podName, "connected_slaves", connected_slaves) + return connected_slaves } } - return "" + + logger.Error(nil, "Failed to find connected_slaves from Info # Replication in", "redis pod", podName) + return 0 } func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { var realMasterPod string - realMasterPod = checkAttachedSlave(ctx, client, logger, cr, masterPods) + + for _, podName := range masterPods { + redisClient := configureRedisReplicationClient(client, logger, cr, podName) + defer redisClient.Close() + + if checkAttachedSlave(ctx, redisClient, logger, podName) > 0 { + realMasterPod = podName + break + } + } + // realMasterPod = checkAttachedSlave(ctx, client, logger, cr, masterPods) if len(slavePods) < 1 { realMasterPod = masterPods[0] diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 732654592..a1dc9d961 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -1,6 +1,7 @@ package k8sutils import ( + "context" "encoding/csv" "fmt" "strings" @@ -8,7 +9,10 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" mock_utils "github.com/OT-CONTAINER-KIT/redis-operator/mocks/utils" + "github.com/go-logr/logr" "github.com/go-logr/logr/testr" + "github.com/go-redis/redismock/v9" + redis "github.com/redis/go-redis/v9" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -512,3 +516,148 @@ func TestGetContainerID(t *testing.T) { }) } } + +func Test_checkAttachedSlave(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + podName string + infoReturn string + infoErr error + expectedSlaveCount int + }{ + { + name: "no attached slaves", + podName: "pod1", + infoReturn: "# Replication\r\n" + + "role:master\r\n" + + "connected_slaves:0\r\n" + + "master_failover_state:no-failover\r\n" + + "master_replid:7b634a76ebb7d5f07007f1d5aec8abff8200704e\r\n" + + "master_replid2:0000000000000000000000000000000000000000\r\n" + + "master_repl_offset:0\r\n" + + "second_repl_offset:-1\r\n" + + "repl_backlog_active:0\r\n" + + "repl_backlog_size:1048576\r\n" + + "repl_backlog_first_byte_offset:0\r\n" + + "repl_backlog_histlen:0\r\n", + expectedSlaveCount: 0, + }, + { + name: "two attached slaves", + podName: "pod2", + infoReturn: "# Replication\r\n" + + "role:master\r\n" + + "connected_slaves:2\r\n" + + "master_failover_state:no-failover\r\n" + + "master_replid:7b634a76ebb7d5f07007f1d5aec8abff8200704e\r\n" + + "master_replid2:0000000000000000000000000000000000000000\r\n" + + "master_repl_offset:0\r\n" + + "second_repl_offset:-1\r\n" + + "repl_backlog_active:0\r\n" + + "repl_backlog_size:1048576\r\n" + + "repl_backlog_first_byte_offset:0\r\n" + + "repl_backlog_histlen:0\r\n", + expectedSlaveCount: 2, + }, + { + name: "error fetching slave info", + podName: "pod3", + infoReturn: "", + infoErr: redis.ErrClosed, + expectedSlaveCount: -1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.TODO() + client, mock := redismock.NewClientMock() + + if tt.infoErr != nil { + mock.ExpectInfo("Replication").SetErr(tt.infoErr) + } else { + mock.ExpectInfo("Replication").SetVal(tt.infoReturn) + } + + slaveCount := checkAttachedSlave(ctx, client, logger, tt.podName) + assert.Equal(t, tt.expectedSlaveCount, slaveCount, "Test case: "+tt.name) + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unmet expectations: %s", err) + } + }) + } +} + +func Test_checkRedisServerRole(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + podName string + infoReturn string + infoErr error + expectedResult string + }{ + { + name: "redis master role", + podName: "pod1", + infoReturn: "# Replication\r\n" + + "role:master\r\n" + + "connected_slaves:0\r\n" + + "master_failover_state:no-failover\r\n" + + "master_replid:7b634a76ebb7d5f07007f1d5aec8abff8200704e\r\n" + + "master_replid2:0000000000000000000000000000000000000000\r\n" + + "master_repl_offset:0\r\n" + + "second_repl_offset:-1\r\n" + + "repl_backlog_active:0\r\n" + + "repl_backlog_size:1048576\r\n" + + "repl_backlog_first_byte_offset:0\r\n" + + "repl_backlog_histlen:0\r\n", + expectedResult: "master", + }, + { + name: "redis slave role", + podName: "pod2", + infoReturn: "# Replication\r\n" + + "role:slave\r\n" + + "connected_slaves:0\r\n" + + "master_failover_state:no-failover\r\n" + + "master_replid:7b634a76ebb7d5f07007f1d5aec8abff8200704e\r\n" + + "master_replid2:0000000000000000000000000000000000000000\r\n" + + "master_repl_offset:0\r\n" + + "second_repl_offset:-1\r\n" + + "repl_backlog_active:0\r\n" + + "repl_backlog_size:1048576\r\n" + + "repl_backlog_first_byte_offset:0\r\n" + + "repl_backlog_histlen:0\r\n", + expectedResult: "slave", + }, + { + name: "error fetching role info", + podName: "pod3", + infoErr: redis.ErrClosed, + expectedResult: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.TODO() + client, mock := redismock.NewClientMock() + + if tt.infoErr != nil { + mock.ExpectInfo("Replication").SetErr(tt.infoErr) + } else { + mock.ExpectInfo("Replication").SetVal(tt.infoReturn) + } + + role := checkRedisServerRole(ctx, client, logger, tt.podName) + assert.Equal(t, tt.expectedResult, role, "Test case: "+tt.name) + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unmet expectations: %s", err) + } + }) + } +} diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index b732a3afc..5492b7216 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -95,9 +95,8 @@ type initContainerParameters struct { } // CreateOrUpdateStateFul method will create or update Redis service -func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params statefulSetParameters, ownerDef metav1.OwnerReference, initcontainerParams initContainerParameters, containerParams containerParameters, sidecars *[]redisv1beta2.Sidecar, cl kubernetes.Interface) error { - logger := statefulSetLogger(namespace, stsMeta.Name) - storedStateful, err := GetStatefulSet(namespace, stsMeta.Name, cl) +func CreateOrUpdateStateFul(cl kubernetes.Interface, logger logr.Logger, namespace string, stsMeta metav1.ObjectMeta, params statefulSetParameters, ownerDef metav1.OwnerReference, initcontainerParams initContainerParameters, containerParams containerParameters, sidecars *[]redisv1beta2.Sidecar) error { + storedStateful, err := GetStatefulSet(cl, logger, namespace, stsMeta.Name) statefulSetDef := generateStatefulSetsDef(stsMeta, params, ownerDef, initcontainerParams, containerParams, getSidecars(sidecars)) if err != nil { if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil { //nolint @@ -105,7 +104,7 @@ func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, params return err } if apierrors.IsNotFound(err) { - return createStatefulSet(namespace, statefulSetDef, cl) + return createStatefulSet(cl, logger, namespace, statefulSetDef) } return err } @@ -688,8 +687,7 @@ func getEnvironmentVariables(role string, enabledPassword *bool, secretName *str } // createStatefulSet is a method to create statefulset in Kubernetes -func createStatefulSet(namespace string, stateful *appsv1.StatefulSet, cl kubernetes.Interface) error { - logger := statefulSetLogger(stateful.Namespace, stateful.Name) +func createStatefulSet(cl kubernetes.Interface, logger logr.Logger, namespace string, stateful *appsv1.StatefulSet) error { _, err := cl.AppsV1().StatefulSets(namespace).Create(context.TODO(), stateful, metav1.CreateOptions{}) if err != nil { logger.Error(err, "Redis stateful creation failed") @@ -726,12 +724,11 @@ func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateS } // GetStateFulSet is a method to get statefulset in Kubernetes -func GetStatefulSet(namespace string, stateful string, cl kubernetes.Interface) (*appsv1.StatefulSet, error) { - logger := statefulSetLogger(namespace, stateful) +func GetStatefulSet(cl kubernetes.Interface, logger logr.Logger, namespace string, name string) (*appsv1.StatefulSet, error) { getOpts := metav1.GetOptions{ TypeMeta: generateMetaInformation("StatefulSet", "apps/v1"), } - statefulInfo, err := cl.AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, getOpts) + statefulInfo, err := cl.AppsV1().StatefulSets(namespace).Get(context.TODO(), name, getOpts) if err != nil { logger.V(1).Info("Redis statefulset get action failed") return nil, err diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 879c3242e..bdc8d430d 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -6,8 +6,12 @@ import ( common "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/go-logr/logr" "github.com/stretchr/testify/assert" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sClientFake "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/pointer" ) @@ -186,6 +190,99 @@ func TestGetVolumeMount(t *testing.T) { } } +func Test_GetStatefulSet(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + sts appsv1.StatefulSet + stsName string + stsNamespace string + present bool + }{ + { + name: "StatefulSet present", + sts: appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + }, + stsName: "test-sts", + stsNamespace: "test-ns", + present: true, + }, + { + name: "StatefulSet not present", + sts: appsv1.StatefulSet{}, + stsName: "test-sts", + stsNamespace: "test-ns", + present: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + client := k8sClientFake.NewSimpleClientset(test.sts.DeepCopy()) + _, err := GetStatefulSet(client, logger, test.stsNamespace, test.stsName) + if test.present { + assert.Nil(t, err) + } else { + assert.NotNil(t, err) + } + }) + } +} + +func Test_createStatefulSet(t *testing.T) { + logger := logr.Discard() + + tests := []struct { + name string + sts appsv1.StatefulSet + present bool + }{ + { + name: "StatefulSet present", + sts: appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + }, + + present: true, + }, + { + name: "StatefulSet not present", + sts: appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + }, + present: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var client *k8sClientFake.Clientset + if test.present { + client = k8sClientFake.NewSimpleClientset(test.sts.DeepCopy()) + } else { + client = k8sClientFake.NewSimpleClientset() + } + err := createStatefulSet(client, logger, test.sts.GetNamespace(), &test.sts) + if test.present { + assert.NotNil(t, err) + } else { + assert.Nil(t, err) + } + }) + } +} + func TestGenerateTLSEnvironmentVariables(t *testing.T) { tlsConfig := &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ From bf1a5a90dfbb645ed9c9c6ebd57b4dddaeb94813 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Fri, 29 Mar 2024 13:32:31 +0100 Subject: [PATCH 134/203] Remove useless comments (#761) Signed-off-by: Mathieu Cesbron --- controllers/redis_controller.go | 1 - controllers/rediscluster_controller.go | 1 - controllers/redissentinel_controller.go | 1 - 3 files changed, 3 deletions(-) diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index e14bf8cd5..9524cc240 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -40,7 +40,6 @@ type RedisReconciler struct { Scheme *runtime.Scheme } -// Reconcile is part of the main kubernetes reconciliation loop which aims func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name) reqLogger.Info("Reconciling opstree redis controller") diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index c540e47e4..7cf371721 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -42,7 +42,6 @@ type RedisClusterReconciler struct { Scheme *runtime.Scheme } -// Reconcile is part of the main kubernetes reconciliation loop func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name) reqLogger.Info("Reconciling opstree redis Cluster controller") diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index ff2292f29..2bb206139 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -24,7 +24,6 @@ type RedisSentinelReconciler struct { Scheme *runtime.Scheme } -// Reconcile is part of the main kubernetes reconciliation loop which aims func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name) reqLogger.Info("Reconciling opstree redis controller") From 1c2dc012a158bbf9563d73af2e4e15de4f491882 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 30 Mar 2024 00:21:46 +0530 Subject: [PATCH 135/203] chore(deps): bump k8s.io/client-go from 0.28.2 to 0.29.3 (#851) * chore(deps): bump k8s.io/client-go from 0.28.2 to 0.29.3 Signed-off-by: Shubham Gupta * fix: remove deprecated method Signed-off-by: Shubham Gupta * bump : notify Signed-off-by: Shubham Gupta * make codegen Signed-off-by: drivebyer --------- Signed-off-by: Shubham Gupta Signed-off-by: drivebyer Co-authored-by: drivebyer --- api/v1beta2/rediscluster_default.go | 6 +- .../redis.redis.opstreelabs.in_redis.yaml | 802 +++++++++-- ...is.redis.opstreelabs.in_redisclusters.yaml | 1246 +++++++++++++++-- ...edis.opstreelabs.in_redisreplications.yaml | 802 +++++++++-- ...s.redis.opstreelabs.in_redissentinels.yaml | 324 ++++- go.mod | 30 +- go.sum | 67 +- k8sutils/finalizer.go | 1 + k8sutils/finalizers_test.go | 20 +- k8sutils/labels_test.go | 8 +- k8sutils/redis-cluster.go | 4 +- k8sutils/redis-cluster_test.go | 74 +- k8sutils/redis-replication.go | 6 +- k8sutils/redis-replication_test.go | 40 +- k8sutils/redis-sentinel.go | 4 +- k8sutils/redis-sentinel_test.go | 28 +- k8sutils/redis-standalone.go | 6 +- k8sutils/redis-standalone_test.go | 40 +- k8sutils/redis_test.go | 22 +- k8sutils/statefulset.go | 4 +- k8sutils/statefulset_test.go | 43 +- 21 files changed, 3013 insertions(+), 564 deletions(-) diff --git a/api/v1beta2/rediscluster_default.go b/api/v1beta2/rediscluster_default.go index 9b6c16ad1..4d0d9792d 100644 --- a/api/v1beta2/rediscluster_default.go +++ b/api/v1beta2/rediscluster_default.go @@ -1,13 +1,13 @@ package v1beta2 -import "k8s.io/utils/pointer" +import "k8s.io/utils/ptr" // SetDefault sets default values for the RedisCluster object. func (r *RedisCluster) SetDefault() { if r.Spec.Port == nil { - r.Spec.Port = pointer.Int(6379) + r.Spec.Port = ptr.To(6379) } if r.Spec.RedisExporter != nil && r.Spec.RedisExporter.Port == nil { - r.Spec.RedisExporter.Port = pointer.Int(9121) + r.Spec.RedisExporter.Port = ptr.To(9121) } } diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index 396696ccd..f4c87f468 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -344,7 +344,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -393,6 +394,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -502,7 +541,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -547,6 +587,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -649,7 +726,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -698,6 +776,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -807,7 +923,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -852,6 +969,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -1809,30 +1963,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1908,6 +2038,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -2056,6 +2206,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -2707,32 +2893,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2821,6 +2981,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -3220,6 +3406,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4236,7 +4529,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4285,6 +4579,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4394,7 +4726,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4439,6 +4772,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -4541,7 +4911,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4590,6 +4961,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4699,7 +5108,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4744,6 +5154,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -6224,30 +6671,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6323,6 +6746,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -6471,6 +6914,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -7122,32 +7601,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7236,6 +7689,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -7635,6 +8114,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index b781c15ef..025c80d57 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -720,7 +720,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -770,6 +771,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -882,7 +925,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -931,6 +975,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1040,7 +1122,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1090,6 +1173,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1202,7 +1327,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -1251,6 +1377,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1731,7 +1895,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1781,6 +1946,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1893,7 +2100,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -1942,6 +2150,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2051,7 +2297,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -2101,6 +2348,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2213,7 +2502,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2262,6 +2552,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -3008,30 +3336,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -3107,6 +3411,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -3255,6 +3579,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -3906,32 +4266,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -4020,6 +4354,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -4419,6 +4779,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -6243,7 +6710,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -6293,6 +6761,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6405,7 +6915,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -6454,6 +6965,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6563,7 +7112,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -6613,6 +7163,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6725,7 +7317,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -6774,6 +7367,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7426,7 +8057,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7476,6 +8108,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7588,7 +8262,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -7637,6 +8312,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7746,7 +8459,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7796,6 +8510,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7908,7 +8664,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -7957,6 +8714,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -8786,30 +9581,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -8885,6 +9656,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -9033,6 +9824,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -9160,30 +9987,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -9259,6 +10062,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -9407,6 +10230,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -10058,32 +10917,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -10172,6 +11005,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -10571,6 +11430,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index c52f9a10a..e130d18c2 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -343,7 +343,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -392,6 +393,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -501,7 +540,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -546,6 +586,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -648,7 +725,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -697,6 +775,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -806,7 +922,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -851,6 +968,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -1811,30 +1965,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1910,6 +2040,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -2058,6 +2208,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -2709,32 +2895,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2823,6 +2983,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -3222,6 +3408,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4238,7 +4531,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4287,6 +4581,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4396,7 +4728,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4441,6 +4774,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -4543,7 +4913,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4592,6 +4963,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4701,7 +5110,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4746,6 +5156,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -6229,30 +6676,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6328,6 +6751,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -6476,6 +6919,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -7127,32 +7606,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7241,6 +7694,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -7640,6 +8119,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index d0ce64fbe..6be2efd14 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -343,7 +343,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -392,6 +393,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -501,7 +540,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -546,6 +586,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -648,7 +725,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -697,6 +775,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -806,7 +922,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -851,6 +968,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -2001,7 +2155,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2050,6 +2205,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2159,7 +2352,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2204,6 +2398,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -2306,7 +2537,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2355,6 +2587,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2464,7 +2734,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2509,6 +2780,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the diff --git a/go.mod b/go.mod index 1854b9982..6d4f5beb7 100644 --- a/go.mod +++ b/go.mod @@ -11,10 +11,10 @@ require ( github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 - k8s.io/api v0.28.2 - k8s.io/apimachinery v0.28.2 - k8s.io/client-go v0.28.2 - k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 + k8s.io/api v0.29.3 + k8s.io/apimachinery v0.29.3 + k8s.io/client-go v0.29.3 + k8s.io/utils v0.0.0-20230726121419-3b25d923346b sigs.k8s.io/controller-runtime v0.16.2 ) @@ -24,10 +24,10 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/zapr v1.2.4 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -35,12 +35,13 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -50,6 +51,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect @@ -60,7 +62,7 @@ require ( go.uber.org/zap v1.25.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect @@ -72,11 +74,11 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.28.0 // indirect - k8s.io/component-base v0.28.1 // indirect - k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect + k8s.io/apiextensions-apiserver v0.29.0 // indirect + k8s.io/component-base v0.29.0 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 8fdecd9d3..cc7047fbc 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -46,13 +46,13 @@ github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= @@ -90,16 +90,15 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -113,6 +112,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -154,6 +155,7 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -243,8 +245,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -264,7 +266,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -315,8 +316,6 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -340,35 +339,35 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= -k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= +k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= -k8s.io/component-base v0.28.1/go.mod h1:jI11OyhbX21Qtbav7JkhehyBsIRfnO8oEgoAR12ArIU= +k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= +k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s= +k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= -k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index 62faf4b7a..c57ad4056 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -183,6 +183,7 @@ func finalizeRedisReplicationPVC(client kubernetes.Interface, logger logr.Logger return nil } +//nolint:unparam func finalizeRedisSentinelPVC(cr *redisv1beta2.RedisSentinel) error { return nil } diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizers_test.go index 5ad37c2ed..eac381cbd 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizers_test.go @@ -16,7 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" k8sClientFake "k8s.io/client-go/kubernetes/fake" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -217,7 +217,7 @@ func TestHandleRedisClusterFinalizer(t *testing.T) { }, }, Spec: v1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.ClusterStorage{ Storage: api.Storage{ KeepAfterDelete: false, @@ -247,7 +247,7 @@ func TestHandleRedisClusterFinalizer(t *testing.T) { }, }, Spec: v1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.ClusterStorage{ Storage: api.Storage{ KeepAfterDelete: true, @@ -331,7 +331,7 @@ func TestHandleRedisReplicationFinalizer(t *testing.T) { }, }, Spec: v1beta2.RedisReplicationSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.Storage{ Storage: api.Storage{ KeepAfterDelete: false, @@ -379,7 +379,7 @@ func TestHandleRedisReplicationFinalizer(t *testing.T) { }, }, Spec: v1beta2.RedisReplicationSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.Storage{ Storage: api.Storage{ KeepAfterDelete: false, @@ -427,7 +427,7 @@ func TestHandleRedisReplicationFinalizer(t *testing.T) { }, }, Spec: v1beta2.RedisReplicationSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.Storage{ Storage: api.Storage{ KeepAfterDelete: true, @@ -651,7 +651,7 @@ func TestFinalizeRedisReplicationPVC(t *testing.T) { Namespace: "redis", }, Spec: v1beta2.RedisReplicationSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), }, }, existingPVCs: []*corev1.PersistentVolumeClaim{ @@ -685,7 +685,7 @@ func TestFinalizeRedisReplicationPVC(t *testing.T) { Namespace: "redis", }, Spec: v1beta2.RedisReplicationSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), }, }, expectError: false, @@ -735,7 +735,7 @@ func TestFinalizeRedisClusterPVC(t *testing.T) { Namespace: "redis", }, Spec: v1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.ClusterStorage{ NodeConfVolume: true, }, @@ -753,7 +753,7 @@ func TestFinalizeRedisClusterPVC(t *testing.T) { Namespace: "redis", }, Spec: v1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), + Size: ptr.To(int32(3)), Storage: &v1beta2.ClusterStorage{ NodeConfVolume: false, }, diff --git a/k8sutils/labels_test.go b/k8sutils/labels_test.go index 3331a1784..8d5488a6a 100644 --- a/k8sutils/labels_test.go +++ b/k8sutils/labels_test.go @@ -6,7 +6,7 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func Test_generateMetaInformation(t *testing.T) { @@ -313,7 +313,7 @@ func TestRedisClusterAsOwner(t *testing.T) { Kind: "RedisCluster", Name: "test-redis-cluster", UID: "abcdef", - Controller: pointer.Bool(true), + Controller: ptr.To(true), } result := redisClusterAsOwner(clusterObj) @@ -340,7 +340,7 @@ func TestRedisReplicationAsOwner(t *testing.T) { Kind: "RedisReplication", Name: "test-redis-replication", UID: "ghijkl", - Controller: pointer.Bool(true), + Controller: ptr.To(true), } result := redisReplicationAsOwner(replicationObj) @@ -367,7 +367,7 @@ func TestRedisSentinelAsOwner(t *testing.T) { Kind: "RedisSentinel", Name: "test-redis-sentinel", UID: "mnopqr", - Controller: pointer.Bool(true), + Controller: ptr.To(true), } result := redisSentinelAsOwner(sentinelObj) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index f3dc5e973..4716f8412 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -12,7 +12,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) // RedisClusterSTS is a interface to call Redis Statefulset function @@ -295,7 +295,7 @@ func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta2.Re var epp exporterPortProvider if cr.Spec.RedisExporter != nil { epp = func() (port int, enable bool) { - defaultP := pointer.Int(redisExporterPort) + defaultP := ptr.To(redisExporterPort) return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled } } else { diff --git a/k8sutils/redis-cluster_test.go b/k8sutils/redis-cluster_test.go index ff7e83672..1d6ad8a9b 100644 --- a/k8sutils/redis-cluster_test.go +++ b/k8sutils/redis-cluster_test.go @@ -13,19 +13,19 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/client-go/kubernetes/fake" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func Test_generateRedisClusterParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-cluster.yaml") expectedLeaderSTS := statefulSetParameters{ - Replicas: pointer.Int32(3), + Replicas: ptr.To(int32(3)), ClusterMode: true, NodeConfVolume: true, PodSecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointer.Int64(1000), - FSGroup: pointer.Int64(1000), + RunAsUser: ptr.To(int64(1000)), + FSGroup: ptr.To(int64(1000)), }, PriorityClassName: "high-priority", Affinity: &corev1.Affinity{ @@ -59,9 +59,9 @@ func Test_generateRedisClusterParams(t *testing.T) { }, PersistentVolumeClaim: corev1.PersistentVolumeClaim{ Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: pointer.String("standard"), + StorageClassName: ptr.To("standard"), AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("1Gi"), }, @@ -70,9 +70,9 @@ func Test_generateRedisClusterParams(t *testing.T) { }, NodeConfPersistentVolumeClaim: corev1.PersistentVolumeClaim{ Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: pointer.String("standard"), + StorageClassName: ptr.To("standard"), AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("1Gi"), }, @@ -81,17 +81,17 @@ func Test_generateRedisClusterParams(t *testing.T) { }, EnableMetrics: true, ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, - ExternalConfig: pointer.String("redis-external-config-leader"), - ServiceAccountName: pointer.String("redis-sa"), + ExternalConfig: ptr.To("redis-external-config-leader"), + ServiceAccountName: ptr.To("redis-sa"), IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, } expectedFollowerSTS := statefulSetParameters{ - Replicas: pointer.Int32(3), + Replicas: ptr.To(int32(3)), ClusterMode: true, NodeConfVolume: true, PodSecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointer.Int64(1000), - FSGroup: pointer.Int64(1000), + RunAsUser: ptr.To(int64(1000)), + FSGroup: ptr.To(int64(1000)), }, PriorityClassName: "high-priority", Affinity: &corev1.Affinity{ @@ -125,9 +125,9 @@ func Test_generateRedisClusterParams(t *testing.T) { }, PersistentVolumeClaim: corev1.PersistentVolumeClaim{ Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: pointer.String("standard"), + StorageClassName: ptr.To("standard"), AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("1Gi"), }, @@ -136,9 +136,9 @@ func Test_generateRedisClusterParams(t *testing.T) { }, NodeConfPersistentVolumeClaim: corev1.PersistentVolumeClaim{ Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: pointer.String("standard"), + StorageClassName: ptr.To("standard"), AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("1Gi"), }, @@ -147,8 +147,8 @@ func Test_generateRedisClusterParams(t *testing.T) { }, EnableMetrics: true, ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, - ExternalConfig: pointer.String("redis-external-config-follower"), - ServiceAccountName: pointer.String("redis-sa"), + ExternalConfig: ptr.To("redis-external-config-follower"), + ServiceAccountName: ptr.To("redis-sa"), IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, } @@ -206,10 +206,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { }, }, SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(1000), - RunAsGroup: pointer.Int64(1000), - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), + RunAsUser: ptr.To(int64(1000)), + RunAsGroup: ptr.To(int64(1000)), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, Add: []corev1.Capability{"NET_BIND_SERVICE"}, @@ -256,10 +256,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { }, }, Role: "cluster", - EnabledPassword: pointer.Bool(true), - SecretName: pointer.String("redis-secret"), - SecretKey: pointer.String("password"), - PersistenceEnabled: pointer.Bool(true), + EnabledPassword: ptr.To(true), + SecretName: ptr.To("redis-secret"), + SecretKey: ptr.To("password"), + PersistenceEnabled: ptr.To(true), TLSConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "ca.key", @@ -319,10 +319,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { }, }, SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(1000), - RunAsGroup: pointer.Int64(1000), - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), + RunAsUser: ptr.To(int64(1000)), + RunAsGroup: ptr.To(int64(1000)), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, Add: []corev1.Capability{"NET_BIND_SERVICE"}, @@ -369,10 +369,10 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { }, }, Role: "cluster", - EnabledPassword: pointer.Bool(true), - SecretName: pointer.String("redis-secret"), - SecretKey: pointer.String("password"), - PersistenceEnabled: pointer.Bool(true), + EnabledPassword: ptr.To(true), + SecretName: ptr.To("redis-secret"), + SecretKey: ptr.To("password"), + PersistenceEnabled: ptr.To(true), TLSConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "ca.key", @@ -440,7 +440,7 @@ func Test_generateRedisClusterContainerParams(t *testing.T) { func Test_generateRedisClusterInitContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-cluster.yaml") expected := initContainerParameters{ - Enabled: pointer.Bool(true), + Enabled: ptr.To(true), Image: "quay.io/opstree/redis-operator-restore:latest", ImagePullPolicy: corev1.PullPolicy("Always"), Resources: &corev1.ResourceRequirements{ @@ -456,7 +456,7 @@ func Test_generateRedisClusterInitContainerParams(t *testing.T) { Role: "cluster", Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, Arguments: []string{"--restore-from", "redis-cluster-restore"}, - PersistenceEnabled: pointer.Bool(true), + PersistenceEnabled: ptr.To(true), AdditionalEnvVariable: &[]corev1.EnvVar{ { Name: "CLUSTER_NAME", diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 967c0925d..9bef5a9eb 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -8,7 +8,7 @@ import ( "github.com/go-logr/logr" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) // CreateReplicationService method will create replication service for Redis @@ -18,7 +18,7 @@ func CreateReplicationService(cr *redisv1beta2.RedisReplication, cl kubernetes.I var epp exporterPortProvider if cr.Spec.RedisExporter != nil { epp = func() (port int, enable bool) { - defaultP := pointer.Int(redisExporterPort) + defaultP := ptr.To(redisExporterPort) return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled } } else { @@ -125,7 +125,7 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - Port: pointer.Int(6379), + Port: ptr.To(6379), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars diff --git a/k8sutils/redis-replication_test.go b/k8sutils/redis-replication_test.go index 57765acba..acde9df5c 100644 --- a/k8sutils/redis-replication_test.go +++ b/k8sutils/redis-replication_test.go @@ -11,21 +11,21 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func Test_generateRedisReplicationParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") expected := statefulSetParameters{ - Replicas: pointer.Int32(3), + Replicas: ptr.To(int32(3)), ClusterMode: false, NodeConfVolume: false, NodeSelector: map[string]string{ "node-role.kubernetes.io/infra": "worker", }, PodSecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointer.Int64(1000), - FSGroup: pointer.Int64(1000), + RunAsUser: ptr.To(int64(1000)), + FSGroup: ptr.To(int64(1000)), }, PriorityClassName: "high-priority", Affinity: &corev1.Affinity{ @@ -59,9 +59,9 @@ func Test_generateRedisReplicationParams(t *testing.T) { }, PersistentVolumeClaim: corev1.PersistentVolumeClaim{ Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: pointer.String("standard"), + StorageClassName: ptr.To("standard"), AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("1Gi"), }, @@ -70,9 +70,9 @@ func Test_generateRedisReplicationParams(t *testing.T) { }, EnableMetrics: true, ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, - ExternalConfig: pointer.String("redis-external-config"), - ServiceAccountName: pointer.String("redis-sa"), - TerminationGracePeriodSeconds: pointer.Int64(30), + ExternalConfig: ptr.To("redis-external-config"), + ServiceAccountName: ptr.To("redis-sa"), + TerminationGracePeriodSeconds: ptr.To(int64(30)), IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, } @@ -95,7 +95,7 @@ func Test_generateRedisReplicationContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") expected := containerParameters{ Image: "quay.io/opstree/redis:v7.0.12", - Port: pointer.Int(6379), + Port: ptr.To(6379), ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), Resources: &corev1.ResourceRequirements{ Requests: corev1.ResourceList{ @@ -108,10 +108,10 @@ func Test_generateRedisReplicationContainerParams(t *testing.T) { }, }, SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(1000), - RunAsGroup: pointer.Int64(1000), - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), + RunAsUser: ptr.To(int64(1000)), + RunAsGroup: ptr.To(int64(1000)), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, Add: []corev1.Capability{"NET_BIND_SERVICE"}, @@ -158,10 +158,10 @@ func Test_generateRedisReplicationContainerParams(t *testing.T) { }, }, Role: "replication", - EnabledPassword: pointer.Bool(true), - SecretName: pointer.String("redis-secret"), - SecretKey: pointer.String("password"), - PersistenceEnabled: pointer.Bool(true), + EnabledPassword: ptr.To(true), + SecretName: ptr.To("redis-secret"), + SecretKey: ptr.To("password"), + PersistenceEnabled: ptr.To(true), TLSConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "ca.key", @@ -225,7 +225,7 @@ func Test_generateRedisReplicationContainerParams(t *testing.T) { func Test_generateRedisReplicationInitContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-replication.yaml") expected := initContainerParameters{ - Enabled: pointer.Bool(true), + Enabled: ptr.To(true), Image: "quay.io/opstree/redis-operator-restore:latest", ImagePullPolicy: corev1.PullPolicy("Always"), Resources: &corev1.ResourceRequirements{ @@ -241,7 +241,7 @@ func Test_generateRedisReplicationInitContainerParams(t *testing.T) { Role: "replication", Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, Arguments: []string{"--restore-from", "redis-replication-restore"}, - PersistenceEnabled: pointer.Bool(true), + PersistenceEnabled: ptr.To(true), AdditionalEnvVariable: &[]corev1.EnvVar{ { Name: "CLUSTER_NAME", diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 2c0bf8605..7b9eaeaa4 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -14,7 +14,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) // RedisSentinelSTS is a interface to call Redis Statefulset function @@ -198,7 +198,7 @@ func (service RedisSentinelService) CreateRedisSentinelService(cr *redisv1beta2. var epp exporterPortProvider if cr.Spec.RedisExporter != nil { epp = func() (port int, enable bool) { - defaultP := pointer.Int(redisExporterPort) + defaultP := ptr.To(redisExporterPort) return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled } } else { diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index 98cee4ee9..473f8786a 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -17,21 +17,21 @@ import ( "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/client-go/dynamic/fake" "k8s.io/client-go/kubernetes" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func Test_generateRedisSentinelParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-sentinel.yaml") expected := statefulSetParameters{ - Replicas: pointer.Int32(3), + Replicas: ptr.To(int32(3)), ClusterMode: false, NodeConfVolume: false, NodeSelector: map[string]string{ "node-role.kubernetes.io/infra": "worker", }, PodSecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointer.Int64(1000), - FSGroup: pointer.Int64(1000), + RunAsUser: ptr.To(int64(1000)), + FSGroup: ptr.To(int64(1000)), }, PriorityClassName: "high-priority", Affinity: &corev1.Affinity{ @@ -65,8 +65,8 @@ func Test_generateRedisSentinelParams(t *testing.T) { }, EnableMetrics: true, ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, - ServiceAccountName: pointer.String("redis-sa"), - TerminationGracePeriodSeconds: pointer.Int64(30), + ServiceAccountName: ptr.To("redis-sa"), + TerminationGracePeriodSeconds: ptr.To(int64(30)), IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, } @@ -101,10 +101,10 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { }, }, SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(1000), - RunAsGroup: pointer.Int64(1000), - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), + RunAsUser: ptr.To(int64(1000)), + RunAsGroup: ptr.To(int64(1000)), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, Add: []corev1.Capability{"NET_BIND_SERVICE"}, @@ -151,9 +151,9 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { }, }, Role: "sentinel", - EnabledPassword: pointer.Bool(true), - SecretName: pointer.String("redis-secret"), - SecretKey: pointer.String("password"), + EnabledPassword: ptr.To(true), + SecretName: ptr.To("redis-secret"), + SecretKey: ptr.To("password"), TLSConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "ca.key", @@ -195,7 +195,7 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { func Test_generateRedisSentinelInitContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-sentinel.yaml") expected := initContainerParameters{ - Enabled: pointer.Bool(true), + Enabled: ptr.To(true), Image: "quay.io/opstree/redis-operator-restore:latest", ImagePullPolicy: corev1.PullPolicy("Always"), Resources: &corev1.ResourceRequirements{ diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 5aae864c8..7f76d191a 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -4,7 +4,7 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "k8s.io/client-go/kubernetes" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) // CreateStandaloneService method will create standalone service for Redis @@ -14,7 +14,7 @@ func CreateStandaloneService(cr *redisv1beta2.Redis, cl kubernetes.Interface) er var epp exporterPortProvider if cr.Spec.RedisExporter != nil { epp = func() (port int, enable bool) { - defaultP := pointer.Int(redisExporterPort) + defaultP := ptr.To(redisExporterPort) return *util.Coalesce(cr.Spec.RedisExporter.Port, defaultP), cr.Spec.RedisExporter.Enabled } } else { @@ -121,7 +121,7 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - Port: pointer.Int(6379), + Port: ptr.To(6379), } if cr.Spec.EnvVars != nil { diff --git a/k8sutils/redis-standalone_test.go b/k8sutils/redis-standalone_test.go index e7eebe882..2637df54f 100644 --- a/k8sutils/redis-standalone_test.go +++ b/k8sutils/redis-standalone_test.go @@ -11,13 +11,13 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/util/yaml" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func Test_generateRedisStandaloneParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") expected := statefulSetParameters{ - Replicas: pointer.Int32(1), + Replicas: ptr.To(int32(1)), ClusterMode: false, NodeConfVolume: false, // Metadata: metav1.ObjectMeta{ @@ -32,8 +32,8 @@ func Test_generateRedisStandaloneParams(t *testing.T) { "node-role.kubernetes.io/infra": "worker", }, PodSecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointer.Int64(1000), - FSGroup: pointer.Int64(1000), + RunAsUser: ptr.To(int64(1000)), + FSGroup: ptr.To(int64(1000)), }, PriorityClassName: "high-priority", Affinity: &corev1.Affinity{ @@ -67,9 +67,9 @@ func Test_generateRedisStandaloneParams(t *testing.T) { }, PersistentVolumeClaim: corev1.PersistentVolumeClaim{ Spec: corev1.PersistentVolumeClaimSpec{ - StorageClassName: pointer.String("standard"), + StorageClassName: ptr.To("standard"), AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse("1Gi"), }, @@ -78,9 +78,9 @@ func Test_generateRedisStandaloneParams(t *testing.T) { }, EnableMetrics: true, ImagePullSecrets: &[]corev1.LocalObjectReference{{Name: "mysecret"}}, - ExternalConfig: pointer.String("redis-external-config"), - ServiceAccountName: pointer.String("redis-sa"), - TerminationGracePeriodSeconds: pointer.Int64(30), + ExternalConfig: ptr.To("redis-external-config"), + ServiceAccountName: ptr.To("redis-sa"), + TerminationGracePeriodSeconds: ptr.To(int64(30)), IgnoreAnnotations: []string{"opstreelabs.in/ignore"}, } @@ -103,7 +103,7 @@ func Test_generateRedisStandaloneContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") expected := containerParameters{ Image: "quay.io/opstree/redis:v7.0.12", - Port: pointer.Int(6379), + Port: ptr.To(6379), ImagePullPolicy: corev1.PullPolicy("IfNotPresent"), Resources: &corev1.ResourceRequirements{ Requests: corev1.ResourceList{ @@ -116,10 +116,10 @@ func Test_generateRedisStandaloneContainerParams(t *testing.T) { }, }, SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointer.Int64(1000), - RunAsGroup: pointer.Int64(1000), - RunAsNonRoot: pointer.Bool(true), - ReadOnlyRootFilesystem: pointer.Bool(true), + RunAsUser: ptr.To(int64(1000)), + RunAsGroup: ptr.To(int64(1000)), + RunAsNonRoot: ptr.To(true), + ReadOnlyRootFilesystem: ptr.To(true), Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{"ALL"}, Add: []corev1.Capability{"NET_BIND_SERVICE"}, @@ -166,10 +166,10 @@ func Test_generateRedisStandaloneContainerParams(t *testing.T) { }, }, Role: "standalone", - EnabledPassword: pointer.Bool(true), - SecretName: pointer.String("redis-secret"), - SecretKey: pointer.String("password"), - PersistenceEnabled: pointer.Bool(true), + EnabledPassword: ptr.To(true), + SecretName: ptr.To("redis-secret"), + SecretKey: ptr.To("password"), + PersistenceEnabled: ptr.To(true), TLSConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "ca.key", @@ -233,7 +233,7 @@ func Test_generateRedisStandaloneContainerParams(t *testing.T) { func Test_generateRedisStandaloneInitContainerParams(t *testing.T) { path := filepath.Join("..", "tests", "testdata", "redis-standalone.yaml") expected := initContainerParameters{ - Enabled: pointer.Bool(true), + Enabled: ptr.To(true), Image: "quay.io/opstree/redis-operator-restore:latest", ImagePullPolicy: corev1.PullPolicy("Always"), Resources: &corev1.ResourceRequirements{ @@ -249,7 +249,7 @@ func Test_generateRedisStandaloneInitContainerParams(t *testing.T) { Role: "standalone", Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, Arguments: []string{"--restore-from", "redis-standalone-restore"}, - PersistenceEnabled: pointer.Bool(true), + PersistenceEnabled: ptr.To(true), AdditionalEnvVariable: &[]corev1.EnvVar{ { Name: "CLUSTER_NAME", diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index a1dc9d961..9b5adfecf 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -17,7 +17,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sClientFake "k8s.io/client-go/kubernetes/fake" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func TestCheckRedisNodePresence(t *testing.T) { @@ -273,9 +273,9 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { Namespace: "default", }, Spec: redisv1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), - ClusterVersion: pointer.String("v7"), - Port: pointer.Int(6379), + Size: ptr.To(int32(3)), + ClusterVersion: ptr.To("v7"), + Port: ptr.To(6379), }, }, expectedCommands: []string{ @@ -294,8 +294,8 @@ func TestCreateMultipleLeaderRedisCommand(t *testing.T) { Namespace: "default", }, Spec: redisv1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), - Port: pointer.Int(6379), + Size: ptr.To(int32(3)), + Port: ptr.To(6379), }, }, expectedCommands: []string{ @@ -364,9 +364,9 @@ func TestCreateRedisReplicationCommand(t *testing.T) { Namespace: "default", }, Spec: redisv1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), - ClusterVersion: pointer.String("v7"), - Port: pointer.Int(6379), + Size: ptr.To(int32(3)), + ClusterVersion: ptr.To("v7"), + Port: ptr.To(6379), }, }, leaderPod: RedisDetails{ @@ -392,8 +392,8 @@ func TestCreateRedisReplicationCommand(t *testing.T) { Namespace: "default", }, Spec: redisv1beta2.RedisClusterSpec{ - Size: pointer.Int32(3), - Port: pointer.Int(6379), + Size: ptr.To(int32(3)), + Port: ptr.To(6379), }, }, leaderPod: RedisDetails{ diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 5492b7216..788851be1 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -22,7 +22,7 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" "k8s.io/utils/env" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) const ( @@ -478,7 +478,7 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { Ports: []corev1.ContainerPort{ { Name: redisExporterPortName, - ContainerPort: int32(*util.Coalesce(params.RedisExporterPort, pointer.Int(redisExporterPort))), + ContainerPort: int32(*util.Coalesce(params.RedisExporterPort, ptr.To(redisExporterPort))), Protocol: corev1.ProtocolTCP, }, }, diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index bdc8d430d..0c0c75491 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -12,7 +12,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8sClientFake "k8s.io/client-go/kubernetes/fake" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) func TestGetVolumeMount(t *testing.T) { @@ -40,7 +40,7 @@ func TestGetVolumeMount(t *testing.T) { }, { name: "2. Persistence enabled with cluster mode and node conf", - persistenceEnabled: pointer.Bool(true), + persistenceEnabled: ptr.To(true), clusterMode: true, nodeConfVolume: true, externalConfig: nil, @@ -60,10 +60,10 @@ func TestGetVolumeMount(t *testing.T) { }, { name: "3. Persistence enabled with cluster mode and external config", - persistenceEnabled: pointer.Bool(true), + persistenceEnabled: ptr.To(true), clusterMode: true, nodeConfVolume: false, - externalConfig: pointer.String("some-config"), + externalConfig: ptr.To("some-config"), mountpath: []corev1.VolumeMount{}, tlsConfig: nil, aclConfig: nil, @@ -80,7 +80,7 @@ func TestGetVolumeMount(t *testing.T) { }, { name: "4. Persistence enabled, cluster mode false, node conf true, no tls/acl, with mountpath", - persistenceEnabled: pointer.Bool(true), + persistenceEnabled: ptr.To(true), clusterMode: false, nodeConfVolume: true, externalConfig: nil, @@ -118,7 +118,7 @@ func TestGetVolumeMount(t *testing.T) { }, { name: "7. Everything enabled except externalConfig", - persistenceEnabled: pointer.Bool(true), + persistenceEnabled: ptr.To(true), clusterMode: true, nodeConfVolume: true, externalConfig: nil, @@ -143,7 +143,7 @@ func TestGetVolumeMount(t *testing.T) { persistenceEnabled: nil, clusterMode: false, nodeConfVolume: false, - externalConfig: pointer.String("some-config"), + externalConfig: ptr.To("some-config"), mountpath: []corev1.VolumeMount{}, tlsConfig: nil, aclConfig: nil, @@ -151,7 +151,7 @@ func TestGetVolumeMount(t *testing.T) { }, { name: "9. Persistence enabled, cluster mode true, node conf true, only acl enabled", - persistenceEnabled: pointer.Bool(true), + persistenceEnabled: ptr.To(true), clusterMode: true, nodeConfVolume: true, externalConfig: nil, @@ -166,7 +166,7 @@ func TestGetVolumeMount(t *testing.T) { }, { name: "10. Persistence enabled, cluster mode false, node conf false, only tls enabled with mountpath", - persistenceEnabled: pointer.Bool(true), + persistenceEnabled: ptr.To(true), clusterMode: false, nodeConfVolume: false, externalConfig: nil, @@ -265,7 +265,8 @@ func Test_createStatefulSet(t *testing.T) { }, } - for _, test := range tests { + for i := range tests { + test := tests[i] t.Run(test.name, func(t *testing.T) { var client *k8sClientFake.Clientset if test.present { @@ -333,10 +334,10 @@ func TestGetEnvironmentVariables(t *testing.T) { { name: "Test with role sentinel, metrics true, password true, persistence true, exporter env, tls enabled, acl enabled and env var", role: "sentinel", - enabledPassword: pointer.Bool(true), - secretName: pointer.String("test-secret"), - secretKey: pointer.String("test-key"), - persistenceEnabled: pointer.Bool(true), + enabledPassword: ptr.To(true), + secretName: ptr.To("test-secret"), + secretKey: ptr.To("test-key"), + persistenceEnabled: ptr.To(true), tlsConfig: &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ CaKeyFile: "test_ca.crt", @@ -355,7 +356,7 @@ func TestGetEnvironmentVariables(t *testing.T) { envVar: &[]corev1.EnvVar{ {Name: "TEST_ENV", Value: "test-value"}, }, - clusterVersion: pointer.String("v6"), + clusterVersion: ptr.To("v6"), expectedEnvironment: []corev1.EnvVar{ {Name: "ACL_MODE", Value: "true"}, {Name: "PERSISTENCE_ENABLED", Value: "true"}, @@ -402,7 +403,7 @@ func TestGetEnvironmentVariables(t *testing.T) { enabledPassword: nil, secretName: nil, secretKey: nil, - persistenceEnabled: pointer.Bool(false), + persistenceEnabled: ptr.To(false), tlsConfig: nil, aclConfig: nil, envVar: nil, @@ -415,16 +416,16 @@ func TestGetEnvironmentVariables(t *testing.T) { { name: "Test with role cluster, metrics true, password true, persistence true, exporter env, tls nil, acl enabled and env var", role: "cluster", - enabledPassword: pointer.Bool(true), - secretName: pointer.String("test-secret"), - secretKey: pointer.String("test-key"), - persistenceEnabled: pointer.Bool(true), + enabledPassword: ptr.To(true), + secretName: ptr.To("test-secret"), + secretKey: ptr.To("test-key"), + persistenceEnabled: ptr.To(true), tlsConfig: nil, aclConfig: &redisv1beta2.ACLConfig{}, envVar: &[]corev1.EnvVar{ {Name: "TEST_ENV", Value: "test-value"}, }, - port: pointer.Int(6380), + port: ptr.To(6380), expectedEnvironment: []corev1.EnvVar{ {Name: "ACL_MODE", Value: "true"}, {Name: "PERSISTENCE_ENABLED", Value: "true"}, From ab45fe06d956cf7f4f7714a50e22a0035dbe29ae Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 30 Mar 2024 07:36:53 +0530 Subject: [PATCH 136/203] chore(deps): bump sigs.k8s.io/controller-runtime from 0.16.2 to 0.17.2 (#852) * chore(deps): bump k8s.io/client-go from 0.28.2 to 0.29.3 Signed-off-by: Shubham Gupta * bump : notify Signed-off-by: Shubham Gupta * chore: remove unused code Signed-off-by: Shubham Gupta * chore(deps): bump sigs.k8s.io/controller-runtime from 0.16.2 to 0.17.2 Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/release-images.yaml | 5 +- go.mod | 55 +++++---- go.sum | 168 ++++++++++++-------------- k8sutils/finalizer.go | 8 -- 4 files changed, 105 insertions(+), 131 deletions(-) diff --git a/.github/workflows/release-images.yaml b/.github/workflows/release-images.yaml index d8a6c722f..d956d2cb7 100644 --- a/.github/workflows/release-images.yaml +++ b/.github/workflows/release-images.yaml @@ -1,5 +1,4 @@ # name: Release container images - # on: # pull_request: # types: [closed] @@ -26,7 +25,7 @@ # - name: Set up QEMU # uses: docker/setup-qemu-action@v3 - + # - name: Login to Quay.io # uses: docker/login-action@v3 # with: @@ -51,7 +50,7 @@ # uses: actions/checkout@v2 # - name: Run Trivy vulnerability scanner for arm64 image # uses: aquasecurity/trivy-action@master - + # - name: Run Trivy vulnerability scanner for multi-arch image # uses: aquasecurity/trivy-action@master # with: diff --git a/go.mod b/go.mod index 6d4f5beb7..818aa00dd 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,8 @@ require ( k8s.io/api v0.29.3 k8s.io/apimachinery v0.29.3 k8s.io/client-go v0.29.3 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b - sigs.k8s.io/controller-runtime v0.16.2 + k8s.io/utils v0.0.0-20240310230437-4693a0247e57 + sigs.k8s.io/controller-runtime v0.17.2 ) require ( @@ -24,14 +24,14 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/emicklei/go-restful/v3 v3.12.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/zapr v1.2.4 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -40,44 +40,43 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/imdario/mergo v0.3.16 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.51.1 // indirect + github.com/prometheus/procfs v0.13.0 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.25.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect + golang.org/x/net v0.22.0 // indirect + golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.17.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.19.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.29.0 // indirect - k8s.io/component-base v0.29.0 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/apiextensions-apiserver v0.29.3 // indirect + k8s.io/component-base v0.29.3 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index cc7047fbc..71ba88c4d 100644 --- a/go.sum +++ b/go.sum @@ -9,9 +9,6 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/banzaicloud/k8s-objectmatcher v1.8.0 h1:Nugn25elKtPMTA2br+JgHNeSQ04sc05MDPmpJnd1N2A= github.com/banzaicloud/k8s-objectmatcher v1.8.0/go.mod h1:p2LSNAjlECf07fbhDyebTkPUIYnU05G+WfGgkTmgeMg= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= @@ -25,7 +22,6 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -35,15 +31,15 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk= +github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -51,22 +47,20 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw= github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= @@ -80,7 +74,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -90,6 +83,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -98,6 +93,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -108,8 +104,8 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -117,9 +113,8 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -129,9 +124,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -141,8 +134,6 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -170,90 +161,80 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.51.1 h1:eIjN50Bwglz6a/c3hAgSMcofL3nD+nFQkV6Dd4DsQCw= +github.com/prometheus/common v0.51.1/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= +github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o= +github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -264,20 +245,23 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -288,9 +272,9 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -299,8 +283,8 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= @@ -316,10 +300,11 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -331,7 +316,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -341,27 +325,27 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= -k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= -k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc= +k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= +k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= -k8s.io/component-base v0.29.0 h1:T7rjd5wvLnPBV1vC4zWd/iWRbV8Mdxs+nGaoaFzGw3s= -k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M= +k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= +k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo= +k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= +sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index c57ad4056..ff3ade1ba 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -82,9 +82,6 @@ func HandleRedisReplicationFinalizer(ctrlclient client.Client, k8sClient kuberne func HandleRedisSentinelFinalizer(ctrlclient client.Client, logger logr.Logger, cr *redisv1beta2.RedisSentinel) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisSentinelFinalizer) { - if err := finalizeRedisSentinelPVC(cr); err != nil { - return err - } controllerutil.RemoveFinalizer(cr, RedisSentinelFinalizer) if err := ctrlclient.Update(context.TODO(), cr); err != nil { logger.Error(err, "Could not remove finalizer "+RedisSentinelFinalizer) @@ -182,8 +179,3 @@ func finalizeRedisReplicationPVC(client kubernetes.Interface, logger logr.Logger } return nil } - -//nolint:unparam -func finalizeRedisSentinelPVC(cr *redisv1beta2.RedisSentinel) error { - return nil -} From eb1cc0d3dca6ae19b8b7c110452a798008716140 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 30 Mar 2024 21:34:27 +0800 Subject: [PATCH 137/203] feat: add redisreplication status masterNode (#849) * feat: add redisreplication status masterNode Signed-off-by: drivebyer * fix e2e Signed-off-by: drivebyer * fix lint Signed-off-by: drivebyer * fix lint Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- api/v1beta1/redisreplication_types.go | 4 ++- api/v1beta2/redisreplication_types.go | 4 ++- ...edis.opstreelabs.in_redisreplications.yaml | 6 ++++ controllers/redisreplication_controller.go | 26 +++++++++++++-- controllers/redissentinel_controller.go | 12 +++++++ k8sutils/redis.go | 32 ++++++++----------- .../redis-replication/chainsaw-test.yaml | 16 ++-------- .../redis-replication/ready-replication.yaml | 8 +++++ 8 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml diff --git a/api/v1beta1/redisreplication_types.go b/api/v1beta1/redisreplication_types.go index 4cca92403..d4be20456 100644 --- a/api/v1beta1/redisreplication_types.go +++ b/api/v1beta1/redisreplication_types.go @@ -31,7 +31,9 @@ func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { } // RedisStatus defines the observed state of Redis -type RedisReplicationStatus struct{} +type RedisReplicationStatus struct { + MasterNode string `json:"masterNode,omitempty"` +} // +kubebuilder:object:root=true // +kubebuilder:subresource:status diff --git a/api/v1beta2/redisreplication_types.go b/api/v1beta2/redisreplication_types.go index 59248fb55..90bf70796 100644 --- a/api/v1beta2/redisreplication_types.go +++ b/api/v1beta2/redisreplication_types.go @@ -36,7 +36,9 @@ func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { } // RedisStatus defines the observed state of Redis -type RedisReplicationStatus struct{} +type RedisReplicationStatus struct { + MasterNode string `json:"masterNode,omitempty"` +} // +kubebuilder:object:root=true // +kubebuilder:subresource:status diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index e130d18c2..eb09d428f 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -4127,6 +4127,9 @@ spec: type: object status: description: RedisStatus defines the observed state of Redis + properties: + masterNode: + type: string type: object required: - spec @@ -8841,6 +8844,9 @@ spec: type: object status: description: RedisStatus defines the observed state of Redis + properties: + masterNode: + type: string type: object required: - spec diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index a57308e80..98a2b9fac 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -77,19 +77,39 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{RequeueAfter: time.Second * 60}, nil } - if len(k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master")) > int(leaderReplicas) { + var realMaster string + masterNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master") + if len(masterNodes) > int(leaderReplicas) { reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) - masterNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master") slaveNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "slave") - err := k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, slaveNodes) + realMaster = k8sutils.GetRedisReplicationRealMaster(ctx, r.K8sClient, r.Log, instance, masterNodes) + if len(slaveNodes) == 0 { + realMaster = masterNodes[0] + } + err := k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, realMaster) if err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } } + realMaster = k8sutils.GetRedisReplicationRealMaster(ctx, r.K8sClient, r.Log, instance, masterNodes) + if err := r.UpdateRedisReplicationMaster(ctx, instance, realMaster); err != nil { + return ctrl.Result{}, err + } reqLogger.Info("Will reconcile redis operator in again 10 seconds") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } +func (r *RedisReplicationReconciler) UpdateRedisReplicationMaster(ctx context.Context, instance *redisv1beta2.RedisReplication, masterNode string) error { + if instance.Status.MasterNode == masterNode { + return nil + } + instance.Status.MasterNode = masterNode + if err := r.Client.Status().Update(ctx, instance); err != nil { + return err + } + return nil +} + // SetupWithManager sets up the controller with the Manager. func (r *RedisReplicationReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 2bb206139..831dfaf16 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -11,8 +11,11 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/util/workqueue" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" ) // RedisSentinelReconciler reconciles a RedisSentinel object @@ -83,5 +86,14 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques func (r *RedisSentinelReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&redisv1beta2.RedisSentinel{}). + Watches(&redisv1beta2.RedisReplication{}, &handler.Funcs{ + CreateFunc: nil, + UpdateFunc: func(ctx context.Context, event event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) { + _ = event.ObjectNew.GetName() + _ = event.ObjectNew.GetNamespace() + }, + DeleteFunc: nil, + GenericFunc: nil, + }). Complete(r) } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index b7f74ef05..bb983084c 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -554,25 +554,7 @@ func checkAttachedSlave(ctx context.Context, redisClient *redis.Client, logger l return 0 } -func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string, slavePods []string) error { - var realMasterPod string - - for _, podName := range masterPods { - redisClient := configureRedisReplicationClient(client, logger, cr, podName) - defer redisClient.Close() - - if checkAttachedSlave(ctx, redisClient, logger, podName) > 0 { - realMasterPod = podName - break - } - } - // realMasterPod = checkAttachedSlave(ctx, client, logger, cr, masterPods) - - if len(slavePods) < 1 { - realMasterPod = masterPods[0] - logger.V(1).Info("No Master Node Found with attached slave promoting the following pod to master", "pod", masterPods[0]) - } - +func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string, realMasterPod string) error { logger.V(1).Info("Redis Master Node is set to", "pod", realMasterPod) realMasterInfo := RedisDetails{ PodName: realMasterPod, @@ -596,3 +578,15 @@ func CreateMasterSlaveReplication(ctx context.Context, client kubernetes.Interfa return nil } + +func GetRedisReplicationRealMaster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, masterPods []string) string { + for _, podName := range masterPods { + redisClient := configureRedisReplicationClient(client, logger, cr, podName) + defer redisClient.Close() + + if checkAttachedSlave(ctx, redisClient, logger, podName) > 0 { + return podName + } + } + return "" +} diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml index ff7822ce7..0b536b458 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml @@ -15,6 +15,8 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml + - assert: + file: ready-replication.yaml catch: - description: Redis Operator Logs podLogs: @@ -51,16 +53,4 @@ spec: content: | kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 check: - ($stdout=='OK'): true - # - script: - # timeout: 10s - # content: | - # kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 set foo-1 bar-1 - # check: - # ($stdout==`READONLY You can't write against a read only replica.`): true - # - script: - # timeout: 10s - # content: | - # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 set foo-2 bar-2 - # check: - # ($stdout==`READONLY You can't write against a read only replica.`): true \ No newline at end of file + ($stdout=='OK'): true \ No newline at end of file diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml new file mode 100644 index 000000000..f3a13d647 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: redis-replication +status: + # by default, the first pod is being selected as master + masterNode: redis-replication-0 \ No newline at end of file From 80a26a948621ffa25742b8999fb8efe5593861f3 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sat, 30 Mar 2024 21:09:22 +0530 Subject: [PATCH 138/203] ci: Validate Test Yaml (#854) * ci: Validate Test Yaml Signed-off-by: Shubham Gupta * test: fix yaml intendation Signed-off-by: Shubham Gupta * test: fix yaml via yamlfix Signed-off-by: Shubham Gupta * add line for fun Signed-off-by: Shubham Gupta * feat: run yamlfix in parallel Signed-off-by: Shubham Gupta * chore: fix script Signed-off-by: Shubham Gupta * fix: use root Signed-off-by: Shubham Gupta * fix: add yaml lint configuration Signed-off-by: Shubham Gupta * fix: changes Signed-off-by: Shubham Gupta * fix: config Signed-off-by: Shubham Gupta * ci: chainsaw example Signed-off-by: Shubham Gupta * fix: long lines Signed-off-by: Shubham Gupta * test: example validation Signed-off-by: Shubham Gupta * fix secrets Signed-off-by: Shubham Gupta * chore: add comment Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- .github/workflows/e2e-chainsaw.yml | 12 + .yamllint.yml | 9 + hack/yaml-fixer.sh | 29 ++ tests/_config/chainsaw-configuration.yaml | 2 +- tests/_config/kind-config.yaml | 15 +- tests/_config/kuttl-test.yaml | 6 +- .../acl-user/redis-cluster/acl-secret.yaml | 2 +- .../acl-user/redis-cluster/chainsaw-test.yaml | 282 ++++++----- .../acl-user/redis-cluster/cluster.yaml | 7 +- .../acl-user/redis-cluster/ready-cluster.yaml | 1 + .../acl-user/redis-cluster/ready-pvc.yaml | 39 +- .../acl-user/redis-cluster/ready-sts.yaml | 3 +- .../acl-user/redis-cluster/ready-svc.yaml | 39 +- .../v1beta2/ha-failover/chainsaw-test.yaml | 37 +- .../v1beta2/ha-failover/cli-pod.yaml | 13 +- .../v1beta2/ha-failover/replication.yaml | 4 +- .../v1beta2/ha-failover/sentinel.yaml | 6 +- .../ha-setup/secured/fully-secured/random | 1 + .../replication-password/chainsaw-test.yaml | 95 ++-- .../replication-password/cli-pod.yaml | 13 +- .../replication-password/password.yaml | 4 +- .../ready-replication-pvc.yaml | 10 +- .../ready-replication-sts.yaml | 5 +- .../ready-replication-svc.yaml | 21 +- .../replication-password/ready-secret.yaml | 4 +- .../ready-sentinel-sts.yaml | 7 +- .../ready-sentinel-svc.yaml | 19 +- .../replication-password/replication.yaml | 4 +- .../replication-password/sentinel.yaml | 10 +- .../sentinel-password/chainsaw-test.yaml | 108 ++-- .../sentinel-password/cli-pod.yaml | 13 +- .../ready-replication-pvc.yaml | 10 +- .../ready-replication-sts.yaml | 5 +- .../ready-replication-svc.yaml | 21 +- .../sentinel-password/ready-sentinel-sts.yaml | 7 +- .../sentinel-password/ready-sentinel-svc.yaml | 19 +- .../sentinel-password/replication.yaml | 4 +- .../sentinel-password/sentinel.yaml | 6 +- .../ha-setup/unsecured/chainsaw-test.yaml | 83 ++-- .../v1beta2/ha-setup/unsecured/cli-pod.yaml | 13 +- .../unsecured/ready-replication-pvc.yaml | 10 +- .../unsecured/ready-replication-sts.yaml | 5 +- .../unsecured/ready-replication-svc.yaml | 21 +- .../unsecured/ready-sentinel-sts.yaml | 7 +- .../unsecured/ready-sentinel-svc.yaml | 19 +- .../ha-setup/unsecured/replication.yaml | 4 +- .../v1beta2/ha-setup/unsecured/sentinel.yaml | 6 +- .../redis-cluster/chainsaw-test.yaml | 290 +++++------ .../hostnetwork/redis-cluster/cluster.yaml | 9 +- .../redis-cluster/ready-cluster.yaml | 1 + .../hostnetwork/redis-cluster/ready-pod.yaml | 87 ++-- .../hostnetwork/redis-cluster/ready-pvc.yaml | 39 +- .../hostnetwork/redis-cluster/ready-sts.yaml | 3 +- .../hostnetwork/redis-cluster/ready-svc.yaml | 39 +- .../redis-cluster/chainsaw-test.yaml | 26 +- .../ignore-annots/redis-cluster/cluster.yaml | 12 +- .../redis-cluster/ignore-annots-sts.yaml | 9 +- .../redis-cluster/ready-cluster.yaml | 3 +- .../redis-cluster/ready-pvc.yaml | 39 +- .../redis-cluster/ready-sts.yaml | 5 +- .../redis-standalone/chainsaw-test.yaml | 26 +- .../redis-standalone/ignore-annots-sts.yaml | 5 +- .../redis-standalone/ready-pvc.yaml | 4 +- .../redis-standalone/ready-standalone.yaml | 3 +- .../redis-standalone/ready-sts.yaml | 3 +- .../redis-standalone/standalone.yaml | 10 +- .../keep-pvc/redis-cluster/chainsaw-test.yaml | 53 +- .../keep-pvc/redis-cluster/cluster.yaml | 7 +- .../keep-pvc/redis-cluster/ready-cluster.yaml | 1 + .../keep-pvc/redis-cluster/ready-pvc.yaml | 39 +- .../keep-pvc/redis-cluster/ready-sts.yaml | 3 +- .../keep-pvc/redis-cluster/ready-svc.yaml | 39 +- .../redis-replication/chainsaw-test.yaml | 49 +- .../keep-pvc/redis-replication/ready-pvc.yaml | 10 +- .../keep-pvc/redis-replication/ready-sts.yaml | 5 +- .../keep-pvc/redis-replication/ready-svc.yaml | 21 +- .../redis-replication/replication.yaml | 4 +- .../redis-standalone/chainsaw-test.yaml | 49 +- .../keep-pvc/redis-standalone/ready-pvc.yaml | 4 +- .../keep-pvc/redis-standalone/ready-sts.yaml | 1 + .../keep-pvc/redis-standalone/ready-svc.yaml | 21 +- .../keep-pvc/redis-standalone/standalone.yaml | 5 +- .../nodeport/redis-cluster/chainsaw-test.yaml | 242 +++++---- .../nodeport/redis-cluster/cluster.yaml | 7 +- .../nodeport/redis-cluster/ready-cluster.yaml | 1 + .../nodeport/redis-cluster/ready-pvc.yaml | 39 +- .../nodeport/redis-cluster/ready-sts.yaml | 3 +- .../nodeport/redis-cluster/ready-svc.yaml | 37 +- .../password/redis-cluster/chainsaw-test.yaml | 456 +++++++++-------- .../password/redis-cluster/cluster.yaml | 7 +- .../password/redis-cluster/ready-cluster.yaml | 1 + .../password/redis-cluster/ready-pvc.yaml | 39 +- .../password/redis-cluster/ready-sts.yaml | 3 +- .../password/redis-cluster/ready-svc.yaml | 39 +- .../redis-replication/chainsaw-test.yaml | 177 ++++--- .../password/redis-replication/ready-pvc.yaml | 10 +- .../password/redis-replication/ready-sts.yaml | 5 +- .../password/redis-replication/ready-svc.yaml | 21 +- .../redis-replication/replication.yaml | 4 +- .../redis-standalone/chainsaw-test.yaml | 89 ++-- .../password/redis-standalone/ready-pvc.yaml | 4 +- .../password/redis-standalone/ready-sts.yaml | 1 + .../password/redis-standalone/ready-svc.yaml | 21 +- .../password/redis-standalone/standalone.yaml | 5 +- .../pvc-name/redis-cluster/chainsaw-test.yaml | 10 +- .../pvc-name/redis-cluster/cluster.yaml | 7 +- .../pvc-name/redis-cluster/ready-cluster.yaml | 1 + .../pvc-name/redis-cluster/ready-pvc.yaml | 39 +- .../pvc-name/redis-cluster/ready-sts.yaml | 3 +- .../pvc-name/redis-cluster/ready-svc.yaml | 39 +- .../scaling/redis-cluster/chainsaw-test.yaml | 469 ++++++++++-------- .../redis-cluster/cluster-scale-up.yaml | 7 +- .../scaling/redis-cluster/cluster.yaml | 7 +- .../redis-cluster/ready-cluster-scale-up.yaml | 3 +- .../scaling/redis-cluster/ready-cluster.yaml | 3 +- .../redis-cluster/ready-sts-scale-up.yaml | 1 + .../scaling/redis-cluster/ready-sts.yaml | 3 +- .../setup/redis-cluster/chainsaw-test.yaml | 268 +++++----- .../v1beta2/setup/redis-cluster/cluster.yaml | 7 +- .../setup/redis-cluster/ready-cluster.yaml | 1 + .../setup/redis-cluster/ready-pvc.yaml | 39 +- .../setup/redis-cluster/ready-sts.yaml | 3 +- .../setup/redis-cluster/ready-svc.yaml | 39 +- .../redis-replication/chainsaw-test.yaml | 100 ++-- .../setup/redis-replication/ready-pvc.yaml | 10 +- .../redis-replication/ready-replication.yaml | 2 +- .../setup/redis-replication/ready-sts.yaml | 5 +- .../setup/redis-replication/ready-svc.yaml | 21 +- .../setup/redis-replication/replication.yaml | 4 +- .../setup/redis-sentinel/chainsaw-test.yaml | 24 +- .../setup/redis-sentinel/ready-sts.yaml | 7 +- .../setup/redis-sentinel/ready-svc.yaml | 19 +- .../setup/redis-sentinel/sentinel.yaml | 2 +- .../teardown/redis-cluster/chainsaw-test.yaml | 1 - .../teardown/redis-cluster/cluster.yaml | 7 +- .../teardown/redis-cluster/ready-cluster.yaml | 1 + .../teardown/redis-cluster/ready-pvc.yaml | 39 +- .../teardown/redis-cluster/ready-sts.yaml | 3 +- .../teardown/redis-cluster/ready-svc.yaml | 39 +- .../redis-replication/chainsaw-test.yaml | 3 +- .../teardown/redis-replication/ready-pvc.yaml | 10 +- .../teardown/redis-replication/ready-sts.yaml | 5 +- .../teardown/redis-replication/ready-svc.yaml | 21 +- .../redis-replication/replication.yaml | 4 +- .../redis-sentinel/chainsaw-test.yaml | 4 +- .../teardown/redis-sentinel/ready-sts.yaml | 7 +- .../teardown/redis-sentinel/ready-svc.yaml | 19 +- .../teardown/redis-sentinel/sentinel.yaml | 2 +- .../redis-standalone/chainsaw-test.yaml | 3 +- .../teardown/redis-standalone/ready-pvc.yaml | 4 +- .../teardown/redis-standalone/ready-sts.yaml | 1 + .../teardown/redis-standalone/ready-svc.yaml | 21 +- .../teardown/redis-standalone/standalone.yaml | 5 +- tests/e2e/v1beta1/setup/00-install.yaml | 8 +- tests/e2e/v1beta1/setup/cluster.yaml | 5 +- .../e2e/v1beta1/setup/ready-cluster-sts.yaml | 3 +- tests/e2e/v1beta1/setup/ready-cluster.yaml | 1 + tests/testdata/redis-cluster.yaml | 59 ++- tests/testdata/redis-replication.yaml | 36 +- tests/testdata/redis-sentinel.yaml | 34 +- tests/testdata/redis-standalone.yaml | 36 +- tests/testdata/secrets/ca.crt | 2 +- tests/testdata/secrets/tls.crt | 2 +- tests/testdata/secrets/tls.key | 2 +- 164 files changed, 2376 insertions(+), 2349 deletions(-) create mode 100644 .yamllint.yml create mode 100755 hack/yaml-fixer.sh diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index c939d6815..a3e75a3dc 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -9,6 +9,18 @@ on: - master jobs: + + validate-yaml: + name: Validate YAML + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install yamllint + run: sudo apt-get install -y yamllint + - name: Lint YAML files + run: yamllint --strict ./tests/ + test: name: ${{ matrix.testpath }} runs-on: ubuntu-latest diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 000000000..5d83d60f3 --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,9 @@ +extends: default + +rules: + line-length: + max: 200 + level: warning + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + comments-indentation: disable diff --git a/hack/yaml-fixer.sh b/hack/yaml-fixer.sh new file mode 100755 index 000000000..1989fa939 --- /dev/null +++ b/hack/yaml-fixer.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +export YAMLFIX_LINE_LENGTH="150" + +# This script is used to fix the yaml files in the repository. +# Note: yamlfix utility doesn't seems to be much mature idk but it is fixing the .crt .tls .ca extenstion present in testdata + +DIR="" + +if [ -n "$1" ]; then + DIR="$1" +fi + +if which yamlfix >/dev/null; then + echo "yamlfix version is." "$(yamlfix --version)" +else + echo "yamlfix is not installed. Please install it using 'pip install yamlfix'" + exit 0 +fi + + +# Since yamlfix is not able to search in a directory recursively +# run in parallel so stdout is mixed up +if [ -n "$DIR" ]; then + echo "------------------------------" + echo "Fixing all YAML files in the directory and its subdirectories: $DIR" + find "$DIR" \( -name '*.yml' -o -name '*.yaml' \) -type f -print0 | xargs -0 -P 4 -I {} yamlfix "{}" + echo "yamlfix has been applied to all YAML files in $DIR and its subdirectories." +fi diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml index 2259297c9..c5318ce00 100644 --- a/tests/_config/chainsaw-configuration.yaml +++ b/tests/_config/chainsaw-configuration.yaml @@ -1,5 +1,5 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Configuration metadata: diff --git a/tests/_config/kind-config.yaml b/tests/_config/kind-config.yaml index 5553b6587..0b89ed05c 100644 --- a/tests/_config/kind-config.yaml +++ b/tests/_config/kind-config.yaml @@ -1,11 +1,12 @@ +--- kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 name: kind nodes: -- role: control-plane -- role: worker -- role: worker -- role: worker -- role: worker -- role: worker -- role: worker \ No newline at end of file + - role: control-plane + - role: worker + - role: worker + - role: worker + - role: worker + - role: worker + - role: worker diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml index 8e560ef77..e64c01a54 100644 --- a/tests/_config/kuttl-test.yaml +++ b/tests/_config/kuttl-test.yaml @@ -1,7 +1,8 @@ +--- apiVersion: kuttl.dev/v1beta1 kind: TestSuite startKIND: false -kindConfig: "./kind-config.yaml" +kindConfig: ./kind-config.yaml parallel: 1 timeout: 1200 testDirs: @@ -10,5 +11,4 @@ testDirs: - tests/e2e/v1beta2/ignore-annots - tests/e2e/v1beta2/scaling - tests/e2e/v1beta2/hostnetwork -suppress : - - events \ No newline at end of file +suppress: [events] diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml index 675db6f1c..46441f262 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/acl-secret.yaml @@ -6,6 +6,6 @@ metadata: type: Opaque stringData: # yamllint disable-line rule:line-length - user.acl: | + user.acl: |- user opstree on ~* &* +@all >abc@123 user buildpiper on ~* &* +@all >abc@123 diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml index f83bfe75f..92a6da4b8 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/chainsaw-test.yaml @@ -1,144 +1,158 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-setup spec: steps: - - try: - - apply: - file: acl-secret.yaml - - assert: - resource: - apiVersion: v1 - kind: Secret - metadata: - name: acl-secret - - apply: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - catch: - - description: Redis Operator Logs - podLogs: + - try: + - apply: + file: acl-secret.yaml + - assert: + resource: + apiVersion: v1 + kind: Secret + metadata: + name: acl-secret + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + catch: + - description: Redis Operator Logs + podLogs: namespace: redis-operator-system selector: control-plane=redis-operator container: manager - tail: -1 # tail all logs - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Cluster Nodes - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Check Cluster Slots Coverage - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - - name: Try saving a key With Password - try: - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-0 bar-0 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-1 bar-1 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-2 bar-2 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-3 bar-3 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-4 bar-4 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-5 bar-5 - check: - ($stdout=='OK'): true \ No newline at end of file + tail: -1 # tail all logs + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Cluster Nodes + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Check Cluster Slots Coverage + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - name: Try saving a key With Password + try: + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 --user opstree --pass abc@123 set foo-5 bar-5 + check: + ($stdout=='OK'): true diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml index 6c231d87b..e01010516 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -37,14 +38,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml index e8af234a6..90b2bf06f 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml index 3fb05ca44..81716a6ee 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml @@ -1,3 +1,4 @@ +--- apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: @@ -14,16 +15,14 @@ spec: catch: - description: Redis Operator Logs podLogs: - namespace: redis-operator-system - selector: control-plane=redis-operator - container: manager - tail: -1 # tail all logs - + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Sleep for 3 minutes try: - sleep: duration: 3m - - name: Test sentinel monitoring try: - script: @@ -35,10 +34,10 @@ spec: catch: - description: Redis Operator Logs podLogs: - namespace: redis-operator-system - selector: control-plane=redis-operator - container: manager - tail: -1 # tail all logs + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs # New created cluster, the first pod is master - name: Terminate the redis-replication-0 pod @@ -50,16 +49,14 @@ spec: catch: - description: Redis Operator Logs podLogs: - namespace: redis-operator-system - selector: control-plane=redis-operator - container: manager - tail: -1 # tail all logs - + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs - name: Sleep for 3 minutes try: - sleep: duration: 3m - - name: Test sentinel monitoring try: - script: @@ -71,7 +68,7 @@ spec: catch: - description: Redis Operator Logs podLogs: - namespace: redis-operator-system - selector: control-plane=redis-operator - container: manager - tail: -1 # tail all logs \ No newline at end of file + namespace: redis-operator-system + selector: control-plane=redis-operator + container: manager + tail: -1 # tail all logs diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml index e8501253e..e3049d88b 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/cli-pod.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -6,9 +7,9 @@ metadata: app: redis spec: containers: - - name: redis - image: redis:alpine - resources: - limits: - cpu: 200m - memory: 500Mi + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml index 3fb33dcac..bf7c7e7b4 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/replication.yaml @@ -21,7 +21,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml index 955066544..994b5626a 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/sentinel.yaml @@ -9,8 +9,8 @@ spec: runAsUser: 1000 fsGroup: 1000 redisSentinelConfig: - redisReplicationName : redis-replication - quorum: "1" + redisReplicationName: redis-replication + quorum: '1' kubernetesConfig: image: quay.io/opstree/redis-sentinel:latest imagePullPolicy: Always @@ -20,4 +20,4 @@ spec: memory: 128Mi limits: cpu: 101m - memory: 128Mi \ No newline at end of file + memory: 128Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random index e69de29bb..8b1378917 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/fully-secured/random @@ -0,0 +1 @@ + diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml index 29a5487a2..434cb2a84 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/chainsaw-test.yaml @@ -1,56 +1,53 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-ha-setup-partial-secured-replication spec: steps: - - try: - - create: - file: secret.yaml - - assert: - file: secret.yaml - - apply: - file: replication.yaml - - assert: - file: ready-replication-sts.yaml - - assert: - file: ready-replication-svc.yaml - - assert: - file: ready-replication-pvc.yaml - - create: - file: password.yaml - - apply: - file: sentinel.yaml - - assert: - file: ready-sentinel-sts.yaml - - assert: - file: ready-sentinel-svc.yaml - - create: - file: cli-pod.yaml - - assert: - file: cli-pod.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Replicated Service from Cli Pod - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 -a Opstree@1234 ping - check: - ($stdout=='PONG'): true - - - name: Ping Sentinel Service from Cli Pod - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping - check: - ($stdout=='PONG'): true + - try: + - create: + file: secret.yaml + - assert: + file: secret.yaml + - apply: + file: replication.yaml + - assert: + file: ready-replication-sts.yaml + - assert: + file: ready-replication-svc.yaml + - assert: + file: ready-replication-pvc.yaml + - create: + file: password.yaml + - apply: + file: sentinel.yaml + - assert: + file: ready-sentinel-sts.yaml + - assert: + file: ready-sentinel-svc.yaml + - create: + file: cli-pod.yaml + - assert: + file: cli-pod.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Replicated Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - name: Ping Sentinel Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping + check: + ($stdout=='PONG'): true diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml index e8501253e..e3049d88b 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/cli-pod.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -6,9 +7,9 @@ metadata: app: redis spec: containers: - - name: redis - image: redis:alpine - resources: - limits: - cpu: 200m - memory: 500Mi + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml index 346addd89..d2411ff46 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/password.yaml @@ -2,7 +2,7 @@ apiVersion: v1 kind: Secret metadata: - name: redis-replication-secret + name: redis-replication-secret stringData: - redis-replication-password: "Opstree@1234" + redis-replication-password: Opstree@1234 type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-replication-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml index de09d2654..c6ee0b3ab 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-secret.yaml @@ -2,5 +2,5 @@ apiVersion: v1 kind: Secret metadata: - name: redis-replication-secret -type: Opaque \ No newline at end of file + name: redis-replication-secret +type: Opaque diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml index 28ed1dace..782908c01 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -24,7 +25,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -32,4 +33,4 @@ spec: role: sentinel status: readyReplicas: 1 - replicas: 1 \ No newline at end of file + replicas: 1 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml index 4ce66a032..5f0556616 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/ready-sentinel-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -66,9 +67,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml index cde71e67e..155811686 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/replication.yaml @@ -24,7 +24,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml index 2cc5040c6..02fca1f8e 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/replication-password/sentinel.yaml @@ -1,5 +1,5 @@ +--- # yaml-language-server: $schema=../../../../../../../../config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml - apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisSentinel metadata: @@ -10,10 +10,10 @@ spec: runAsUser: 1000 fsGroup: 1000 redisSentinelConfig: - redisReplicationName : redis-replication - quorum: "1" + redisReplicationName: redis-replication + quorum: '1' redisReplicationPassword: - secretKeyRef: + secretKeyRef: name: redis-replication-secret key: redis-replication-password kubernetesConfig: @@ -25,4 +25,4 @@ spec: memory: 128Mi limits: cpu: 101m - memory: 128Mi \ No newline at end of file + memory: 128Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml index 834f7caef..f9ad51130 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/chainsaw-test.yaml @@ -1,63 +1,59 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-ha-setup-partial-secured-sentinel spec: steps: - - try: - - apply: - file: replication.yaml - - assert: - file: ready-replication-sts.yaml - - assert: - file: ready-replication-svc.yaml - - assert: - file: ready-replication-pvc.yaml - - create: - file: secret.yaml - - assert: - file: secret.yaml - - apply: - file: sentinel.yaml - - assert: - file: ready-sentinel-sts.yaml - - assert: - file: ready-sentinel-svc.yaml - - create: - file: cli-pod.yaml - - assert: - file: cli-pod.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Replicated Service from Cli Pod - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Ping Sentinel Service from Cli Pod With password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 -a Opstree@1234 ping - check: - ($stdout=='PONG'): true - - - name: Ping Sentinel Service from Cli Pod Without password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true \ No newline at end of file + - try: + - apply: + file: replication.yaml + - assert: + file: ready-replication-sts.yaml + - assert: + file: ready-replication-svc.yaml + - assert: + file: ready-replication-pvc.yaml + - create: + file: secret.yaml + - assert: + file: secret.yaml + - apply: + file: sentinel.yaml + - assert: + file: ready-sentinel-sts.yaml + - assert: + file: ready-sentinel-svc.yaml + - create: + file: cli-pod.yaml + - assert: + file: cli-pod.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Replicated Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Ping Sentinel Service from Cli Pod With password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 -a Opstree@1234 ping + check: + ($stdout=='PONG'): true + - name: Ping Sentinel Service from Cli Pod Without password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml index e8501253e..e3049d88b 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/cli-pod.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -6,9 +7,9 @@ metadata: app: redis spec: containers: - - name: redis - image: redis:alpine - resources: - limits: - cpu: 200m - memory: 500Mi + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-replication-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml index 28ed1dace..782908c01 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -24,7 +25,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -32,4 +33,4 @@ spec: role: sentinel status: readyReplicas: 1 - replicas: 1 \ No newline at end of file + replicas: 1 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml index 4ce66a032..5f0556616 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/ready-sentinel-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -66,9 +67,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml index 3fb33dcac..bf7c7e7b4 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/replication.yaml @@ -21,7 +21,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml index bd350a122..345287bcd 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/secured/partially-secured/sentinel-password/sentinel.yaml @@ -9,8 +9,8 @@ spec: runAsUser: 1000 fsGroup: 1000 redisSentinelConfig: - redisReplicationName : redis-replication - quorum: "1" + redisReplicationName: redis-replication + quorum: '1' kubernetesConfig: image: quay.io/opstree/redis-sentinel:latest imagePullPolicy: Always @@ -23,4 +23,4 @@ spec: memory: 128Mi limits: cpu: 101m - memory: 128Mi \ No newline at end of file + memory: 128Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml index 897524046..e0c31e0ea 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/chainsaw-test.yaml @@ -1,50 +1,47 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-ha-setup-unsecured spec: steps: - - try: - - apply: - file: replication.yaml - - assert: - file: ready-replication-sts.yaml - - assert: - file: ready-replication-svc.yaml - - assert: - file: ready-replication-pvc.yaml - - apply: - file: sentinel.yaml - - assert: - file: ready-sentinel-sts.yaml - - assert: - file: ready-sentinel-svc.yaml - - create: - file: cli-pod.yaml - - assert: - file: cli-pod.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Replicated Service from Cli Pod - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Ping Sentinel Service from Cli Pod - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping - check: - ($stdout=='PONG'): true + - try: + - apply: + file: replication.yaml + - assert: + file: ready-replication-sts.yaml + - assert: + file: ready-replication-svc.yaml + - assert: + file: ready-replication-pvc.yaml + - apply: + file: sentinel.yaml + - assert: + file: ready-sentinel-sts.yaml + - assert: + file: ready-sentinel-svc.yaml + - create: + file: cli-pod.yaml + - assert: + file: cli-pod.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Replicated Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-replication.${NAMESPACE}.svc -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Ping Sentinel Service from Cli Pod + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 ping + check: + ($stdout=='PONG'): true diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml index e8501253e..e3049d88b 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/cli-pod.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: Pod metadata: @@ -6,9 +7,9 @@ metadata: app: redis spec: containers: - - name: redis - image: redis:alpine - resources: - limits: - cpu: 200m - memory: 500Mi + - name: redis + image: redis:alpine + resources: + limits: + cpu: 200m + memory: 500Mi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-replication-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml index 28ed1dace..782908c01 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -24,7 +25,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -32,4 +33,4 @@ spec: role: sentinel status: readyReplicas: 1 - replicas: 1 \ No newline at end of file + replicas: 1 diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml index 4ce66a032..5f0556616 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/ready-sentinel-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -66,9 +67,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml index 3fb33dcac..bf7c7e7b4 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/replication.yaml @@ -21,7 +21,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml index 955066544..994b5626a 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-setup/unsecured/sentinel.yaml @@ -9,8 +9,8 @@ spec: runAsUser: 1000 fsGroup: 1000 redisSentinelConfig: - redisReplicationName : redis-replication - quorum: "1" + redisReplicationName: redis-replication + quorum: '1' kubernetesConfig: image: quay.io/opstree/redis-sentinel:latest imagePullPolicy: Always @@ -20,4 +20,4 @@ spec: memory: 128Mi limits: cpu: 101m - memory: 128Mi \ No newline at end of file + memory: 128Mi diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml index 92f2d2793..c3a37ab9c 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/chainsaw-test.yaml @@ -1,152 +1,152 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: host-network spec: steps: - - name: Setup redis cluster on host network - try: - - apply: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - assert: - file: ready-pod.yaml - - - name: Install Redis Cli - try: - - script: - timeout: 5m - content: | - sudo apt install redis-tools -y - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Redis Cluster from every node - try: - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping - check: - ($stdout=='PONG'): true - - - name: Curl Exporter from every node - try: - - script: - timeout: 30s - content: | - # - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - - name: Try saving a key from every node - try: - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-0 bar-0 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-1 bar-1 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-2 bar-2 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-3 bar-3 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-4 bar-4 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-5 bar-5 - check: - ($stdout=='OK'): true \ No newline at end of file + - name: Setup redis cluster on host network + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: ready-pod.yaml + - name: Install Redis Cli + try: + - script: + timeout: 5m + content: | + sudo apt install redis-tools -y + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Redis Cluster from every node + try: + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 ping + check: + ($stdout=='PONG'): true + - name: Curl Exporter from every node + try: + - script: + timeout: 30s + content: > + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | + xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | + xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | + xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | + xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | + xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | + xargs -I {} curl -s http://{}:9122/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - name: Try saving a key from every node + try: + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 1 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 2 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 3 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 4 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 5 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl get node -o wide | grep 'worker' | awk '{print $6}' | head -n 6 | tail -n 1 | xargs -I {} redis-cli -h {} -c -p 6380 set foo-5 bar-5 + check: + ($stdout=='OK'): true diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml index 687044052..05dadf043 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -6,7 +7,7 @@ spec: hostNetwork: true port: 6380 clusterSize: 3 - clusterVersion: v6 # hostNetwork only works with v6 + clusterVersion: v6 # hostNetwork only works with v6 persistenceEnabled: true podSecurityContext: runAsUser: 1000 @@ -37,14 +38,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml index b26382e6d..2b383ec8b 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pod.yaml @@ -1,8 +1,9 @@ +--- apiVersion: v1 kind: Pod metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 name: redis-cluster-v1beta2-leader-0 spec: @@ -10,17 +11,17 @@ spec: - name: redis-cluster-v1beta2-leader env: - name: PERSISTENCE_ENABLED - value: "true" + value: 'true' - name: REDIS_ADDR - value: "redis://localhost:6379" + value: redis://localhost:6379 - name: REDIS_MAJOR_VERSION - value: "v6" + value: v6 - name: REDIS_PORT - value: "6380" + value: '6380' - name: SERVER_MODE - value: "cluster" + value: cluster - name: SETUP_MODE - value: "cluster" + value: cluster - name: redis-exporter hostNetwork: true status: @@ -30,7 +31,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 name: redis-cluster-v1beta2-leader-1 spec: @@ -38,17 +39,17 @@ spec: - name: redis-cluster-v1beta2-leader env: - name: PERSISTENCE_ENABLED - value: "true" + value: 'true' - name: REDIS_ADDR - value: "redis://localhost:6379" + value: redis://localhost:6379 - name: REDIS_MAJOR_VERSION - value: "v6" + value: v6 - name: REDIS_PORT - value: "6380" + value: '6380' - name: SERVER_MODE - value: "cluster" + value: cluster - name: SETUP_MODE - value: "cluster" + value: cluster - name: redis-exporter hostNetwork: true status: @@ -58,7 +59,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 name: redis-cluster-v1beta2-leader-2 spec: @@ -66,17 +67,17 @@ spec: - name: redis-cluster-v1beta2-leader env: - name: PERSISTENCE_ENABLED - value: "true" + value: 'true' - name: REDIS_ADDR - value: "redis://localhost:6379" + value: redis://localhost:6379 - name: REDIS_MAJOR_VERSION - value: "v6" + value: v6 - name: REDIS_PORT - value: "6380" + value: '6380' - name: SERVER_MODE - value: "cluster" + value: cluster - name: SETUP_MODE - value: "cluster" + value: cluster - name: redis-exporter hostNetwork: true status: @@ -86,7 +87,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 name: redis-cluster-v1beta2-follower-0 spec: @@ -94,17 +95,17 @@ spec: - name: redis-cluster-v1beta2-follower env: - name: PERSISTENCE_ENABLED - value: "true" + value: 'true' - name: REDIS_ADDR - value: "redis://localhost:6379" + value: redis://localhost:6379 - name: REDIS_MAJOR_VERSION - value: "v6" + value: v6 - name: REDIS_PORT - value: "6380" + value: '6380' - name: SERVER_MODE - value: "cluster" + value: cluster - name: SETUP_MODE - value: "cluster" + value: cluster - name: redis-exporter hostNetwork: true status: @@ -114,7 +115,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 name: redis-cluster-v1beta2-follower-1 spec: @@ -122,17 +123,17 @@ spec: - name: redis-cluster-v1beta2-follower env: - name: PERSISTENCE_ENABLED - value: "true" + value: 'true' - name: REDIS_ADDR - value: "redis://localhost:6379" + value: redis://localhost:6379 - name: REDIS_MAJOR_VERSION - value: "v6" + value: v6 - name: REDIS_PORT - value: "6380" + value: '6380' - name: SERVER_MODE - value: "cluster" + value: cluster - name: SETUP_MODE - value: "cluster" + value: cluster - name: redis-exporter hostNetwork: true status: @@ -142,7 +143,7 @@ apiVersion: v1 kind: Pod metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 name: redis-cluster-v1beta2-follower-2 spec: @@ -150,18 +151,18 @@ spec: - name: redis-cluster-v1beta2-follower env: - name: PERSISTENCE_ENABLED - value: "true" + value: 'true' - name: REDIS_ADDR - value: "redis://localhost:6379" + value: redis://localhost:6379 - name: REDIS_MAJOR_VERSION - value: "v6" + value: v6 - name: REDIS_PORT - value: "6380" + value: '6380' - name: SERVER_MODE - value: "cluster" + value: cluster - name: SETUP_MODE - value: "cluster" + value: cluster - name: redis-exporter hostNetwork: true status: - phase: Running \ No newline at end of file + phase: Running diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml index 1d248a5d5..a438e242f 100644 --- a/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/hostnetwork/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9122" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9122' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9122" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9122' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9122" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9122' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9122" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9122' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9122" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9122' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9122" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9122' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml index f78603de4..a708b0a95 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/chainsaw-test.yaml @@ -1,20 +1,20 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-ignore-annots spec: steps: - - name: Setup Redis Cluster - try: - - create: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-pvc.yaml - - error: - file: ignore-annots-sts.yaml + - name: Setup Redis Cluster + try: + - create: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-pvc.yaml + - error: + file: ignore-annots-sts.yaml diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/cluster.yaml index 9744e4f3a..6d24c9872 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/cluster.yaml @@ -1,9 +1,10 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster-v1beta2 annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value spec: clusterSize: 3 clusterVersion: v7 @@ -12,8 +13,7 @@ spec: runAsUser: 1000 fsGroup: 1000 kubernetesConfig: - ignoreAnnotations: - - "need-ignore-key" + ignoreAnnotations: [need-ignore-key] image: quay.io/opstree/redis:latest imagePullPolicy: Always resources: @@ -27,14 +27,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml index ec4d3c68a..7d8847b55 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ignore-annots-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -7,12 +8,12 @@ metadata: redis_setup_type: cluster role: leader annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value spec: template: metadata: annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value --- apiVersion: apps/v1 kind: StatefulSet @@ -23,9 +24,9 @@ metadata: redis_setup_type: cluster role: follower annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value spec: template: metadata: annotations: - need-ignore-key: "need-ignore-value" \ No newline at end of file + need-ignore-key: need-ignore-value diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml index 186f67d63..fb6f17085 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml @@ -1,9 +1,10 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: name: redis-cluster-v1beta2 annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml index d272d671b..bd107d9b1 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -10,7 +11,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 status: replicas: 3 @@ -28,7 +29,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 status: replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml index 338c32525..3ccb62680 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/chainsaw-test.yaml @@ -1,20 +1,20 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-ignore-annots spec: steps: - - name: Setup Redis Standalone - try: - - create: - file: standalone.yaml - - assert: - file: ready-standalone.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-pvc.yaml - - error: - file: ignore-annots-sts.yaml + - name: Setup Redis Standalone + try: + - create: + file: standalone.yaml + - assert: + file: ready-standalone.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-pvc.yaml + - error: + file: ignore-annots-sts.yaml diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml index ced8a3244..d7754234d 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ignore-annots-sts.yaml @@ -1,11 +1,12 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-standalone-v1beta2 annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value spec: template: metadata: annotations: - need-ignore-key: "need-ignore-value" \ No newline at end of file + need-ignore-key: need-ignore-value diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml index 777fa3656..29ecbfc3d 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: standalone role: standalone status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml index 1e25d81c1..cfc5107ad 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-standalone.yaml @@ -1,6 +1,7 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: name: redis-standalone-v1beta2 annotations: - need-ignore-key: "need-ignore-value" \ No newline at end of file + need-ignore-key: need-ignore-value diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml index 4e95a8910..9c54cdb5f 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -10,7 +11,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 status: replicas: 1 diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/standalone.yaml index 6a940f706..04eed47ed 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/standalone.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-standalone/standalone.yaml @@ -1,16 +1,16 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: name: redis-standalone-v1beta2 annotations: - need-ignore-key: "need-ignore-value" + need-ignore-key: need-ignore-value spec: podSecurityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: - ignoreAnnotations: - - "need-ignore-key" + ignoreAnnotations: [need-ignore-key] image: quay.io/opstree/redis:latest imagePullPolicy: Always resources: @@ -24,7 +24,7 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml index 5ee5221b4..f3639eadc 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/chainsaw-test.yaml @@ -1,34 +1,33 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: keep-pvc spec: steps: - - name: Install - try: - - apply: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - - name: Uninstall - try: - - delete: - ref: - name: redis-cluster-v1beta2 - kind: RedisCluster - apiVersion: redis.redis.opstreelabs.in/v1beta2 - - error: - file: ready-sts.yaml - - error: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml + - name: Install + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - name: Uninstall + try: + - delete: + ref: + name: redis-cluster-v1beta2 + kind: RedisCluster + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml index 126651a37..0fac38be4 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -35,14 +36,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml index e8af234a6..90b2bf06f 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml index 922c98e94..296fa9f7b 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/chainsaw-test.yaml @@ -1,32 +1,31 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: keep-pvc spec: steps: - - name: Install - try: - - apply: - file: replication.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - - name: Uninstall - try: - - delete: - ref: - name: redis-replication - kind: RedisReplication - apiVersion: redis.redis.opstreelabs.in/v1beta2 - - error: - file: ready-sts.yaml - - error: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml \ No newline at end of file + - name: Install + try: + - apply: + file: replication.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - name: Uninstall + try: + - delete: + ref: + name: redis-replication + kind: RedisReplication + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml index 5b3f3c5ac..d7637d0de 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-replication/replication.yaml @@ -22,7 +22,7 @@ spec: keepAfterDelete: true volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml index 130ba36df..2dc6062d7 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/chainsaw-test.yaml @@ -1,32 +1,31 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: keep-pvc spec: steps: - - name: Install - try: - - apply: - file: standalone.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - - name: Uninstall - try: - - delete: - ref: - name: redis-standalone-v1beta2 - kind: Redis - apiVersion: redis.redis.opstreelabs.in/v1beta2 - - error: - file: ready-sts.yaml - - error: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml \ No newline at end of file + - name: Install + try: + - apply: + file: standalone.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - name: Uninstall + try: + - delete: + ref: + name: redis-standalone-v1beta2 + kind: Redis + apiVersion: redis.redis.opstreelabs.in/v1beta2 + - error: + file: ready-sts.yaml + - error: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml index 777fa3656..29ecbfc3d 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: standalone role: standalone status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml index 5402de920..d7941e8ba 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml index 08b416ce2..05965659c 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -35,9 +36,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -67,9 +68,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -93,4 +94,4 @@ spec: role: standalone type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml index 3962ff653..f692af513 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-standalone/standalone.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: @@ -5,7 +6,7 @@ metadata: spec: podSecurityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: image: quay.io/opstree/redis:latest imagePullPolicy: Always @@ -21,7 +22,7 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml index 2ed8bbb82..51161bc06 100644 --- a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/chainsaw-test.yaml @@ -1,130 +1,126 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-nodeport spec: steps: - - name: Setup redis cluster use nodeport - try: - - apply: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Cluster - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Check Cluster - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 - check: - (contains($stdout, '[OK] All 16384 slots covered.')): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 - check: - (contains($stdout, '[OK] All 16384 slots covered.')): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 - check: - (contains($stdout, '[OK] All 16384 slots covered.')): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 - check: - (contains($stdout, '[OK] All 16384 slots covered.')): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 - check: - (contains($stdout, '[OK] All 16384 slots covered.')): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 - check: - (contains($stdout, '[OK] All 16384 slots covered.')): true - - - name: Try saving a key With Password - try: - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 - check: - ($stdout=='OK'): true \ No newline at end of file + - name: Setup redis cluster use nodeport + try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Cluster + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Check Cluster + try: + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - script: + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 + check: + (contains($stdout, '[OK] All 16384 slots covered.')): true + - name: Try saving a key With Password + try: + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: | + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='OK'): true diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml index 805d02a3c..634018552 100644 --- a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -36,14 +37,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml index c56a06bd7..944a19031 100644 --- a/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/nodeport/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml index 1d76bce27..b7974b9db 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/chainsaw-test.yaml @@ -1,223 +1,247 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-password spec: steps: - - try: - - apply: - file: cluster.yaml - - apply: - file: secret.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - assert: - file: secret.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Cluster With Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - - name: Try saving a key With Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 -a Opstree1234 set foo-0 bar-0 - check: - ($stdout=='OK'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 -a Opstree1234 set foo-1 bar-1 - check: - ($stdout=='OK'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 -a Opstree1234 set foo-2 bar-2 - check: - ($stdout=='OK'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 -a Opstree1234 set foo-3 bar-3 - check: - ($stdout=='OK'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 -a Opstree1234 set foo-4 bar-4 - check: - ($stdout=='OK'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 -a Opstree1234 set foo-5 bar-5 - check: - ($stdout=='OK'): true - - - name: Ping Cluster Without Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - - name: Try saving a key Without Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 - check: - ($stdout=='NOAUTH Authentication required.'): true - - - name: Test Redis Exporter - try: - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true \ No newline at end of file + - try: + - apply: + file: cluster.yaml + - apply: + file: secret.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: secret.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Cluster With Password + try: + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - name: Try saving a key With Password + try: + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 -a Opstree1234 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 -a Opstree1234 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 -a Opstree1234 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 -a Opstree1234 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 -a Opstree1234 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 -a Opstree1234 set foo-5 bar-5 + check: + ($stdout=='OK'): true + - name: Ping Cluster Without Password + try: + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - name: Try saving a key Without Password + try: + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='NOAUTH Authentication required.'): true + - name: Test Redis Exporter + try: + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml index 257720a64..64ee82b4e 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -37,14 +38,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml index e8af234a6..90b2bf06f 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml index f15f063ad..5bdd5f8ae 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/chainsaw-test.yaml @@ -1,59 +1,56 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-replication-password spec: steps: - - try: - - apply: - file: replication.yaml - - apply: - file: secret.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - assert: - file: secret.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Replicated Cluster With Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree1234 ping - check: - ($stdout=='PONG'): true - - - name: Try saving a key With Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree1234 set foo-0 bar-0 - check: - ($stdout=='OK'): true + - try: + - apply: + file: replication.yaml + - apply: + file: secret.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: secret.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Replicated Cluster With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree1234 ping + check: + ($stdout=='PONG'): true + - name: Try saving a key With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 -a Opstree1234 set foo-0 bar-0 + check: + ($stdout=='OK'): true # - script: # timeout: 10s # content: | @@ -66,45 +63,43 @@ spec: # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 -a Opstree1234 set foo-2 bar-2 # check: # ($stdout=='READONLY You can't write against a read only replica.'): true - - - name: Ping Replicated Cluster Without Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 ping - check: - ($stdout=='NOAUTH Authentication required.'): true - - - name: Try saving a key Without Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 set foo-1 bar-1 - check: - ($stdout=='NOAUTH Authentication required.'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 set foo-2 bar-2 - check: - ($stdout=='NOAUTH Authentication required.'): true + - name: Ping Replicated Cluster Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 ping + check: + ($stdout=='NOAUTH Authentication required.'): true + - name: Try saving a key Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 set foo-1 bar-1 + check: + ($stdout=='NOAUTH Authentication required.'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 set foo-2 bar-2 + check: + ($stdout=='NOAUTH Authentication required.'): true diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml index 7ee034870..b177f395c 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-replication/replication.yaml @@ -24,7 +24,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml index f6c0c723e..4f378bc59 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/chainsaw-test.yaml @@ -1,53 +1,50 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-replication-password spec: steps: - - try: - - apply: - file: standalone.yaml - - apply: - file: secret.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - assert: - file: secret.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Try saving a key With Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- redis-cli -p 6379 -a Opstree1234 set foo-0 bar-0 - check: - ($stdout=='OK'): true - - - name: Try saving a key Without Password - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- redis-cli -p 6379 set foo-0 bar-0 - check: - ($stdout=='NOAUTH Authentication required.'): true - - - name: Test Redis Exporter - try: - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' - check: - ($stdout=='1'): true \ No newline at end of file + - try: + - apply: + file: standalone.yaml + - apply: + file: secret.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + - assert: + file: secret.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Try saving a key With Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- redis-cli -p 6379 -a Opstree1234 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - name: Try saving a key Without Password + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- redis-cli -p 6379 set foo-0 bar-0 + check: + ($stdout=='NOAUTH Authentication required.'): true + - name: Test Redis Exporter + try: + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} redis-standalone-v1beta2-0 -c redis-standalone-v1beta2 -- + wget -qO- http://localhost:9121/metrics | grep -v '^#' | grep -E '\bredis_up\b' | awk '{print $2}' + check: + ($stdout=='1'): true diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml index 777fa3656..29ecbfc3d 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: standalone role: standalone status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml index 5402de920..d7941e8ba 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml index 275aae8cd..b1f49ac47 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -35,9 +36,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -71,9 +72,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -97,4 +98,4 @@ spec: role: standalone type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml index ad7eed929..1bcca28d4 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-standalone/standalone.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: @@ -5,7 +6,7 @@ metadata: spec: podSecurityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: image: quay.io/opstree/redis:latest imagePullPolicy: Always @@ -34,7 +35,7 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml index a022f9537..db0efcb92 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/chainsaw-test.yaml @@ -8,11 +8,11 @@ spec: - name: Add PVC name environment try: - script: - content: | - kubectl patch deployment redis-operator-redis-operator --namespace redis-operator-system --type json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/env/-", "value": {"name": "OPERATOR_STS_PVC_TEMPLATE_NAME", "value": "data"}}]' + content: > + kubectl patch deployment redis-operator-redis-operator --namespace redis-operator-system --type json + -p='[{"op": "add", "path": "/spec/template/spec/containers/0/env/-", "value": {"name": "OPERATOR_STS_PVC_TEMPLATE_NAME", "value": "data"}}]' - sleep: duration: 1m - - name: redis-cluster-install try: - apply: @@ -25,7 +25,6 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml - - name: redis-cluster-uninstall try: - delete: @@ -41,10 +40,9 @@ spec: file: ready-svc.yaml - error: file: ready-pvc.yaml - - name: Remove PVC name environment try: - script: - content: | + content: |- kubectl patch deployment redis-operator-redis-operator --namespace redis-operator-system --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/env/1"}]' kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml index ecf147104..ccbde1924 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -34,14 +35,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml index 2511fa8d5..c7706058c 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml index e8af234a6..90b2bf06f 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml index 85aa0cb3d..6eafeb05d 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml @@ -1,227 +1,256 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-setup spec: steps: - - name: Create Redis Cluster - try: - - create: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Cluster Nodes - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Check Cluster Slots - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - - name: Scale Redis Cluster - try: - - apply: - file: cluster-scale-up.yaml - - assert: - file: ready-cluster-scale-up.yaml - - assert: - file: ready-sts-scale-up.yaml - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Scaled Cluster Nodes - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Check Scaled Cluster Slots - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true \ No newline at end of file + - name: Create Redis Cluster + try: + - create: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Cluster Nodes + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Check Cluster Slots + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - name: Scale Redis Cluster + try: + - apply: + file: cluster-scale-up.yaml + - assert: + file: ready-cluster-scale-up.yaml + - assert: + file: ready-sts-scale-up.yaml + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Scaled Cluster Nodes + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Check Scaled Cluster Slots + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml index 5f64363e8..ac5e85413 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -34,14 +35,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster.yaml index ecf147104..ccbde1924 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -34,14 +35,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml index 907e75ccc..eb06df309 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -5,4 +6,4 @@ metadata: status: state: Ready readyLeaderReplicas: 6 - readyFollowerReplicas: 6 \ No newline at end of file + readyFollowerReplicas: 6 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml index 3a08c80b6..bc823bbb0 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -5,4 +6,4 @@ metadata: status: state: Ready readyLeaderReplicas: 3 - readyFollowerReplicas: 3 \ No newline at end of file + readyFollowerReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml index 61d865e0f..6de6ae80b 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index c036ab288..7af2381d7 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -1,138 +1,150 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-cluster-setup spec: steps: - - try: - - apply: - file: cluster.yaml - - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - catch: - - description: Redis Operator Logs - podLogs: + - try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + catch: + - description: Redis Operator Logs + podLogs: namespace: redis-operator-system selector: control-plane=redis-operator container: manager - tail: -1 # tail all logs - - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - - name: Ping Cluster - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Check Cluster - try: - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - - - name: Try saving a key With Password - try: - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 - check: - ($stdout=='OK'): true - - script: - timeout: 30s - content: | - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 - check: - ($stdout=='OK'): true - + tail: -1 # tail all logs + - name: Sleep for five minutes + try: + - sleep: + duration: 5m + - name: Ping Cluster + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Check Cluster + try: + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - script: + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' + check: + ($stdout=='[OK] All 16384 slots covered.'): true + - name: Try saving a key With Password + try: + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- + redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- + redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- + redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- + redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- + redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- + redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='OK'): true diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml index ecf147104..ccbde1924 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -34,14 +35,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml index e8af234a6..90b2bf06f 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml index 0b536b458..c74eed234 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/chainsaw-test.yaml @@ -1,56 +1,64 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-replication-setup spec: steps: - - try: - - apply: - file: replication.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - - assert: - file: ready-pvc.yaml - - assert: - file: ready-replication.yaml - catch: - - description: Redis Operator Logs - podLogs: + - try: + - apply: + file: replication.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + - assert: + file: ready-pvc.yaml + catch: + - description: Redis Operator Logs + podLogs: namespace: redis-operator-system selector: control-plane=redis-operator container: manager - tail: -1 # tail all logs - - - name: Ping Replicated Cluster - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 ping - check: - ($stdout=='PONG'): true - - - name: Try saving a key - try: - - script: - timeout: 10s - content: | - kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 - check: - ($stdout=='OK'): true \ No newline at end of file + tail: -1 # tail all logs + - name: Ping Replicated Cluster + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 ping + check: + ($stdout=='PONG'): true + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 ping + check: + ($stdout=='PONG'): true + - name: Try saving a key + try: + - script: + timeout: 10s + content: | + kubectl exec --namespace ${NAMESPACE} redis-replication-0 -- redis-cli -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + # - script: + # timeout: 10s + # content: | + # kubectl exec --namespace ${NAMESPACE} redis-replication-1 -- redis-cli -p 6379 set foo-1 bar-1 + # check: + # ($stdout==`READONLY You can't write against a read only replica.`): true + # - script: + # timeout: 10s + # content: | + # kubectl exec --namespace ${NAMESPACE} redis-replication-2 -- redis-cli -p 6379 set foo-2 bar-2 + # check: + # ($stdout==`READONLY You can't write against a read only replica.`): true diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml index f3a13d647..58db03571 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-replication.yaml @@ -5,4 +5,4 @@ metadata: name: redis-replication status: # by default, the first pod is being selected as master - masterNode: redis-replication-0 \ No newline at end of file + masterNode: redis-replication-0 diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml index 3fb33dcac..bf7c7e7b4 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-replication/replication.yaml @@ -21,7 +21,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml index c3a26553d..4f42a8edd 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/chainsaw-test.yaml @@ -1,22 +1,22 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: name: redis-sentinel-setup spec: steps: - - try: - - apply: - file: sentinel.yaml - - assert: - file: ready-sts.yaml - - assert: - file: ready-svc.yaml - catch: - - description: Redis Operator Logs - podLogs: + - try: + - apply: + file: sentinel.yaml + - assert: + file: ready-sts.yaml + - assert: + file: ready-svc.yaml + catch: + - description: Redis Operator Logs + podLogs: namespace: redis-operator-system selector: control-plane=redis-operator container: manager - tail: -1 # tail all logs \ No newline at end of file + tail: -1 # tail all logs diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml index c6056ab05..c983596f2 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -24,7 +25,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -32,4 +33,4 @@ spec: role: sentinel status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml index 4ce66a032..5f0556616 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -66,9 +67,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml index 7260486a6..2fc9f45fd 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-sentinel/sentinel.yaml @@ -19,4 +19,4 @@ spec: memory: 128Mi limits: cpu: 101m - memory: 128Mi \ No newline at end of file + memory: 128Mi diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml index c0f32993d..9c9970e7d 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/chainsaw-test.yaml @@ -17,7 +17,6 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml - - name: redis-cluster-uninstall try: - delete: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml index ecf147104..ccbde1924 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: @@ -34,14 +35,14 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi nodeConfVolume: true nodeConfVolumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml index 49e754e81..004498aff 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: RedisCluster metadata: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml index a89bfa22a..92097d64b 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -52,8 +50,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -67,8 +64,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -82,14 +78,11 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound - --- - apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -99,8 +92,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -114,8 +106,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -129,8 +120,7 @@ metadata: redis_setup_type: cluster role: leader status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -144,8 +134,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -159,8 +148,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -174,8 +162,7 @@ metadata: redis_setup_type: cluster role: follower status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml index 1053eb784..73545eaab 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -9,9 +10,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml index e8af234a6..90b2bf06f 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -70,9 +71,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-leader @@ -103,9 +104,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -139,9 +140,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -171,9 +172,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-cluster-v1beta2 labels: app: redis-cluster-v1beta2-follower @@ -198,4 +199,4 @@ spec: role: follower type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml index e040a64d2..be97ff7d5 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/chainsaw-test.yaml @@ -1,5 +1,5 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: @@ -17,7 +17,6 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml - - name: redis-replication-uninstall description: Uninstall Redis Replication try: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-pvc.yaml index f57cb3f61..10d9c886c 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -22,8 +22,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound @@ -37,8 +36,7 @@ metadata: redis_setup_type: replication role: replication status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-sts.yaml index f2ac67b1a..7e1712a8e 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -16,4 +17,4 @@ metadata: name: redis-replication status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-svc.yaml index 707a8df9b..3e2e7ccbb 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -32,9 +33,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -62,9 +63,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-replication labels: app: redis-replication @@ -87,4 +88,4 @@ spec: app: redis-replication redis_setup_type: replication role: replication - type: ClusterIP \ No newline at end of file + type: ClusterIP diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml index 7c85e8e03..4e09fea71 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-replication/replication.yaml @@ -32,7 +32,7 @@ spec: storage: volumeClaimTemplate: spec: - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml index 163731940..1f528e011 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/chainsaw-test.yaml @@ -1,5 +1,5 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: @@ -15,7 +15,6 @@ spec: file: ready-sts.yaml - assert: file: ready-svc.yaml - - name: redis-sentinel-uninstall description: Uninstall Redis Sentinel try: @@ -28,4 +27,3 @@ spec: file: ready-sts.yaml - error: file: ready-svc.yaml - diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-sts.yaml index c6056ab05..c983596f2 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-sts.yaml @@ -1,8 +1,9 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -24,7 +25,7 @@ spec: template: metadata: annotations: - redis.opstreelabs.in: "true" + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -32,4 +33,4 @@ spec: role: sentinel status: readyReplicas: 3 - replicas: 3 \ No newline at end of file + replicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-svc.yaml index 4ce66a032..5f0556616 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -34,9 +35,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel @@ -66,9 +67,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-sentinel labels: app: redis-sentinel-sentinel diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml index ca09db7f9..e214fc254 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-sentinel/sentinel.yaml @@ -20,4 +20,4 @@ spec: memory: 128Mi limits: cpu: 101m - memory: 128Mi \ No newline at end of file + memory: 128Mi diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml index 1300c14c6..6b27fd2ce 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/chainsaw-test.yaml @@ -1,5 +1,5 @@ +--- # yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json - apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test metadata: @@ -16,7 +16,6 @@ spec: file: ready-svc.yaml - assert: file: ready-pvc.yaml - - name: redis-standalone-uninstall try: - delete: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml index 5649e1c3b..29ecbfc3d 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-pvc.yaml @@ -1,3 +1,4 @@ +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -7,8 +8,7 @@ metadata: redis_setup_type: standalone role: standalone status: - accessModes: - - ReadWriteOnce + accessModes: [ReadWriteOnce] capacity: storage: 1Gi phase: Bound diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-sts.yaml index 5402de920..d7941e8ba 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-sts.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-svc.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-svc.yaml index 08b416ce2..05965659c 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-svc.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/ready-svc.yaml @@ -1,10 +1,11 @@ +--- apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -35,9 +36,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -67,9 +68,9 @@ apiVersion: v1 kind: Service metadata: annotations: - prometheus.io/port: "9121" - prometheus.io/scrape: "true" - redis.opstreelabs.in: "true" + prometheus.io/port: '9121' + prometheus.io/scrape: 'true' + redis.opstreelabs.in: 'true' redis.opstreelabs.instance: redis-standalone-v1beta2 labels: app: redis-standalone-v1beta2 @@ -93,4 +94,4 @@ spec: role: standalone type: ClusterIP status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/standalone.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/standalone.yaml index c0cc6ded9..aaea4cac7 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/standalone.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-standalone/standalone.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta2 kind: Redis metadata: @@ -5,7 +6,7 @@ metadata: spec: podSecurityContext: runAsUser: 1000 - fsGroup: 1000 + fsGroup: 1000 kubernetesConfig: image: quay.io/opstree/redis:latest imagePullPolicy: Always @@ -20,7 +21,7 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi diff --git a/tests/e2e/v1beta1/setup/00-install.yaml b/tests/e2e/v1beta1/setup/00-install.yaml index 94b166978..05090155c 100644 --- a/tests/e2e/v1beta1/setup/00-install.yaml +++ b/tests/e2e/v1beta1/setup/00-install.yaml @@ -1,7 +1,5 @@ +--- apiVersion: kuttl.dev/v1beta1 kind: TestStep -apply : - - cluster.yaml -assert : - - ready-cluster.yaml - - ready-cluster-sts.yaml \ No newline at end of file +apply: [cluster.yaml] +assert: [ready-cluster.yaml, ready-cluster-sts.yaml] diff --git a/tests/e2e/v1beta1/setup/cluster.yaml b/tests/e2e/v1beta1/setup/cluster.yaml index 6315fc563..fe7a6119f 100644 --- a/tests/e2e/v1beta1/setup/cluster.yaml +++ b/tests/e2e/v1beta1/setup/cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta1 kind: RedisCluster metadata: @@ -34,7 +35,7 @@ spec: volumeClaimTemplate: spec: # storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: - storage: 1Gi \ No newline at end of file + storage: 1Gi diff --git a/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml b/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml index 8c0fec94c..909597dc1 100644 --- a/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml +++ b/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apps/v1 kind: StatefulSet metadata: @@ -5,9 +6,7 @@ metadata: status: replicas: 3 readyReplicas: 3 - --- - apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/tests/e2e/v1beta1/setup/ready-cluster.yaml b/tests/e2e/v1beta1/setup/ready-cluster.yaml index 79a48407b..88a19d87e 100644 --- a/tests/e2e/v1beta1/setup/ready-cluster.yaml +++ b/tests/e2e/v1beta1/setup/ready-cluster.yaml @@ -1,3 +1,4 @@ +--- apiVersion: redis.redis.opstreelabs.in/v1beta1 kind: RedisCluster metadata: diff --git a/tests/testdata/redis-cluster.yaml b/tests/testdata/redis-cluster.yaml index b107d6508..26eee377e 100644 --- a/tests/testdata/redis-cluster.yaml +++ b/tests/testdata/redis-cluster.yaml @@ -7,7 +7,7 @@ metadata: labels: app: redis-cluster annotations: - opstreelabs.in/redis: "true" + opstreelabs.in/redis: 'true' spec: clusterSize: 3 kubernetesConfig: @@ -25,8 +25,7 @@ spec: redisSecret: name: redis-secret key: password - ignoreAnnotations: - - "opstreelabs.in/ignore" + ignoreAnnotations: [opstreelabs.in/ignore] podSecurityContext: runAsUser: 1000 fsGroup: 1000 @@ -37,18 +36,18 @@ spec: runAsNonRoot: true readOnlyRootFilesystem: true capabilities: - drop: [ "ALL" ] - add: [ "NET_BIND_SERVICE" ] + drop: [ALL] + add: [NET_BIND_SERVICE] replicas: 3 redisConfig: additionalRedisConfig: redis-external-config-leader tolerations: - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoSchedule" - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoExecute" + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoExecute affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -56,8 +55,7 @@ spec: - matchExpressions: - key: node-role.kubernetes.io/infra operator: In - values: - - redisLeader + values: [redisLeader] redisFollower: securityContext: runAsUser: 1000 @@ -65,18 +63,18 @@ spec: runAsNonRoot: true readOnlyRootFilesystem: true capabilities: - drop: [ "ALL" ] - add: [ "NET_BIND_SERVICE" ] + drop: [ALL] + add: [NET_BIND_SERVICE] replicas: 3 redisConfig: additionalRedisConfig: redis-external-config-follower tolerations: - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoSchedule" - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoExecute" + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoExecute affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -84,8 +82,7 @@ spec: - matchExpressions: - key: node-role.kubernetes.io/infra operator: In - values: - - redisFollower + values: [redisFollower] redisExporter: enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 @@ -99,7 +96,7 @@ spec: memory: 128Mi env: - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - value: "true" + value: 'true' - name: UI_PROPERTIES_FILE_NAME valueFrom: configMapKeyRef: @@ -116,14 +113,14 @@ spec: nodeConfVolumeClaimTemplate: spec: storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi volumeClaimTemplate: spec: storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi @@ -148,15 +145,15 @@ spec: secretName: redis-tls-cert env: - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" + value: custom_value_1 - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" + value: custom_value_2 initContainer: enabled: true image: quay.io/opstree/redis-operator-restore:latest imagePullPolicy: Always - command: ["/bin/bash", "-c", "/app/restore.bash"] - args: ["--restore-from", "redis-cluster-restore"] + command: [/bin/bash, -c, /app/restore.bash] + args: [--restore-from, redis-cluster-restore] resources: requests: cpu: 100m @@ -174,4 +171,4 @@ spec: valueFrom: secretKeyRef: name: env-secrets - key: CLUSTER_NAMESPACE \ No newline at end of file + key: CLUSTER_NAMESPACE diff --git a/tests/testdata/redis-replication.yaml b/tests/testdata/redis-replication.yaml index 2f695bfe1..4214e2f3c 100644 --- a/tests/testdata/redis-replication.yaml +++ b/tests/testdata/redis-replication.yaml @@ -7,7 +7,7 @@ metadata: labels: app: redis-replication annotations: - opstreelabs.in/redis: "true" + opstreelabs.in/redis: 'true' spec: clusterSize: 3 redisConfig: @@ -21,8 +21,8 @@ spec: runAsNonRoot: true readOnlyRootFilesystem: true capabilities: - drop: ["ALL"] - add: ["NET_BIND_SERVICE"] + drop: [ALL] + add: [NET_BIND_SERVICE] kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent @@ -38,8 +38,7 @@ spec: redisSecret: name: redis-secret key: password - ignoreAnnotations: - - "opstreelabs.in/ignore" + ignoreAnnotations: [opstreelabs.in/ignore] redisExporter: enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 @@ -53,7 +52,7 @@ spec: memory: 128Mi env: - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - value: "true" + value: 'true' - name: UI_PROPERTIES_FILE_NAME valueFrom: configMapKeyRef: @@ -68,7 +67,7 @@ spec: volumeClaimTemplate: spec: storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi @@ -90,15 +89,14 @@ spec: - matchExpressions: - key: node-role.kubernetes.io/infra operator: In - values: - - worker + values: [worker] tolerations: - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoSchedule" - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoExecute" + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoExecute serviceAccountName: redis-sa terminationGracePeriodSeconds: 30 acl: @@ -112,15 +110,15 @@ spec: secretName: redis-tls-cert env: - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" + value: custom_value_1 - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" + value: custom_value_2 initContainer: enabled: true image: quay.io/opstree/redis-operator-restore:latest imagePullPolicy: Always - command: ["/bin/bash", "-c", "/app/restore.bash"] - args: ["--restore-from", "redis-replication-restore"] + command: [/bin/bash, -c, /app/restore.bash] + args: [--restore-from, redis-replication-restore] resources: requests: cpu: 100m diff --git a/tests/testdata/redis-sentinel.yaml b/tests/testdata/redis-sentinel.yaml index 40bf80154..f102f92f2 100644 --- a/tests/testdata/redis-sentinel.yaml +++ b/tests/testdata/redis-sentinel.yaml @@ -7,7 +7,7 @@ metadata: labels: app: redis-sentinel annotations: - opstreelabs.in/redis: "true" + opstreelabs.in/redis: 'true' spec: clusterSize: 3 podSecurityContext: @@ -19,8 +19,8 @@ spec: runAsNonRoot: true readOnlyRootFilesystem: true capabilities: - drop: ["ALL"] - add: ["NET_BIND_SERVICE"] + drop: [ALL] + add: [NET_BIND_SERVICE] kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent @@ -36,8 +36,7 @@ spec: redisSecret: name: redis-secret key: password - ignoreAnnotations: - - "opstreelabs.in/ignore" + ignoreAnnotations: [opstreelabs.in/ignore] redisExporter: enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 @@ -51,7 +50,7 @@ spec: memory: 128Mi env: - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - value: "true" + value: 'true' - name: UI_PROPERTIES_FILE_NAME valueFrom: configMapKeyRef: @@ -72,15 +71,14 @@ spec: - matchExpressions: - key: node-role.kubernetes.io/infra operator: In - values: - - worker + values: [worker] tolerations: - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoSchedule" - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoExecute" + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoExecute serviceAccountName: redis-sa terminationGracePeriodSeconds: 30 TLS: @@ -91,15 +89,15 @@ spec: secretName: redis-tls-cert env: - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" + value: custom_value_1 - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" + value: custom_value_2 initContainer: enabled: true image: quay.io/opstree/redis-operator-restore:latest imagePullPolicy: Always - command: ["/bin/bash", "-c", "/app/restore.bash"] - args: ["--restore-from", "redis-sentinel-restore"] + command: [/bin/bash, -c, /app/restore.bash] + args: [--restore-from, redis-sentinel-restore] resources: requests: cpu: 100m diff --git a/tests/testdata/redis-standalone.yaml b/tests/testdata/redis-standalone.yaml index a3b351259..305d9b9b6 100644 --- a/tests/testdata/redis-standalone.yaml +++ b/tests/testdata/redis-standalone.yaml @@ -7,7 +7,7 @@ metadata: labels: app: redis-standalone annotations: - opstreelabs.in/redis: "true" + opstreelabs.in/redis: 'true' spec: redisConfig: additionalRedisConfig: redis-external-config @@ -20,8 +20,8 @@ spec: runAsNonRoot: true readOnlyRootFilesystem: true capabilities: - drop: ["ALL"] - add: ["NET_BIND_SERVICE"] + drop: [ALL] + add: [NET_BIND_SERVICE] kubernetesConfig: image: quay.io/opstree/redis:v7.0.12 imagePullPolicy: IfNotPresent @@ -37,8 +37,7 @@ spec: redisSecret: name: redis-secret key: password - ignoreAnnotations: - - "opstreelabs.in/ignore" + ignoreAnnotations: [opstreelabs.in/ignore] redisExporter: enabled: true image: quay.io/opstree/redis-exporter:v1.44.0 @@ -52,7 +51,7 @@ spec: memory: 128Mi env: - name: REDIS_EXPORTER_INCL_SYSTEM_METRICS - value: "true" + value: 'true' - name: UI_PROPERTIES_FILE_NAME valueFrom: configMapKeyRef: @@ -67,7 +66,7 @@ spec: volumeClaimTemplate: spec: storageClassName: standard - accessModes: ["ReadWriteOnce"] + accessModes: [ReadWriteOnce] resources: requests: storage: 1Gi @@ -89,15 +88,14 @@ spec: - matchExpressions: - key: node-role.kubernetes.io/infra operator: In - values: - - worker + values: [worker] tolerations: - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoSchedule" - - key: "node-role.kubernetes.io/infra" - operator: "Exists" - effect: "NoExecute" + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/infra + operator: Exists + effect: NoExecute serviceAccountName: redis-sa terminationGracePeriodSeconds: 30 acl: @@ -111,15 +109,15 @@ spec: secretName: redis-tls-cert env: - name: CUSTOM_ENV_VAR_1 - value: "custom_value_1" + value: custom_value_1 - name: CUSTOM_ENV_VAR_2 - value: "custom_value_2" + value: custom_value_2 initContainer: enabled: true image: quay.io/opstree/redis-operator-restore:latest imagePullPolicy: Always - command: ["/bin/bash", "-c", "/app/restore.bash"] - args: ["--restore-from", "redis-standalone-restore"] + command: [/bin/bash, -c, /app/restore.bash] + args: [--restore-from, redis-standalone-restore] resources: requests: cpu: 100m diff --git a/tests/testdata/secrets/ca.crt b/tests/testdata/secrets/ca.crt index 483acebbe..de97d5d33 100644 --- a/tests/testdata/secrets/ca.crt +++ b/tests/testdata/secrets/ca.crt @@ -16,4 +16,4 @@ tkEB4yCOj72p3DmC/bJSa4zp0ng/AoATA7GPmm+l1hEMDLd+mtosMtev0DWDyF0j acrlBvRv4Eq6kFuBBzcPqKC2DuFWIU/ZCBkwn2tScPEf0UjZUXl74k9Taz37Av9Z KQByaF94pYf/7kPRIn2Zw0xXRTJ0wD9bi4Q6YfnN/ntrcs1CNKWb4MMbU2gnz0RN zCjC ------END CERTIFICATE----- +-----END CERTIFICATE----- \ No newline at end of file diff --git a/tests/testdata/secrets/tls.crt b/tests/testdata/secrets/tls.crt index b60b071aa..2f5542cbd 100644 --- a/tests/testdata/secrets/tls.crt +++ b/tests/testdata/secrets/tls.crt @@ -14,4 +14,4 @@ iZ2Iw/MKLJEVxOxNRPzeKE6bHqvO6dijUGrB++XugrGVwMQjMZsJuu6bN7CYRgsA OoRKohDkhaKsW/RkGIYDIxqm+zsPv69PTALlUXJtgnlkvNc6F5Fd5pwuW8TJ/wLe eyQM56RaW2OInIOO4ehJkgRnLdukkECvYEwlZD3RgGFvUIGZFZXDS7FvpzZaUmdz XtNWJjYUsc8d8iljTQ== ------END CERTIFICATE----- +-----END CERTIFICATE----- \ No newline at end of file diff --git a/tests/testdata/secrets/tls.key b/tests/testdata/secrets/tls.key index 485f0189c..97ab91a7a 100644 --- a/tests/testdata/secrets/tls.key +++ b/tests/testdata/secrets/tls.key @@ -25,4 +25,4 @@ qeL1G2ADhqcXR5O0adubBLDP01nqMlYoOr5s2rislpTOmers8eJZ1/p9J2ZNhFow WTwyMda9qjnQvDovPcm5ci1SEjJUCusJKNwoZiU9/xuU1P9t234qmNsmQV5Tpplg aH139Yw8kz7u9z1o2ajO6rG7rQ5qUgYXHgEhIoRnkCfx4uekeaO5lgdwIDR0zC1I BfJBeduDgVHEyYxEU78tprfc ------END PRIVATE KEY----- +-----END PRIVATE KEY----- \ No newline at end of file From 41fd1646e842bc35292dede9f08a244c590e1c54 Mon Sep 17 00:00:00 2001 From: Shubham Gupta <69793468+shubham-cmyk@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:19:36 +0530 Subject: [PATCH 139/203] test: Add unit test (#856) * test: Add unit test Signed-off-by: Shubham Gupta * test: Cover TestCheckRedisCluster Signed-off-by: Shubham Gupta * test: fix coverage Signed-off-by: Shubham Gupta * fix: coverage Signed-off-by: Shubham Gupta * fix: remove print statement Signed-off-by: Shubham Gupta --------- Signed-off-by: Shubham Gupta --- k8sutils/redis-cluster.go | 2 - k8sutils/redis.go | 30 +++--- k8sutils/redis_test.go | 188 ++++++++++++++++++++++++++++++++++++-- k8sutils/secrets.go | 2 + mocks/utils/utils.go | 17 +++- 5 files changed, 210 insertions(+), 29 deletions(-) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 4716f8412..8c182a20d 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -1,7 +1,6 @@ package k8sutils import ( - "fmt" "strconv" "strings" @@ -35,7 +34,6 @@ type RedisClusterService struct { // generateRedisClusterParams generates Redis cluster information func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, externalConfig *string, params RedisClusterSTS) statefulSetParameters { - fmt.Println(cr.Spec.Storage.NodeConfVolume) res := statefulSetParameters{ Replicas: &replicas, ClusterMode: true, diff --git a/k8sutils/redis.go b/k8sutils/redis.go index bb983084c..525677a2e 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -165,8 +165,9 @@ func createRedisReplicationCommand(client kubernetes.Interface, logger logr.Logg pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Failed to retrieve Redis password", "Secret", *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name) + } else { + cmd = append(cmd, "-a", pass) } - cmd = append(cmd, "-a", pass) } cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, leaderPod.PodName)...) @@ -185,7 +186,10 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter leaderCounts := cr.Spec.GetReplicaCounts("leader") followerPerLeader := followerCounts / leaderCounts - nodes := checkRedisCluster(ctx, client, logger, cr) + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() + + nodes := checkRedisCluster(ctx, redisClient, logger) for followerIdx := 0; followerIdx <= int(followerCounts)-1; { for i := 0; i < int(followerPerLeader) && followerIdx <= int(followerCounts)-1; i++ { followerPod := RedisDetails{ @@ -222,18 +226,10 @@ func ExecuteRedisReplicationCommand(ctx context.Context, client kubernetes.Inter } // checkRedisCluster will check the redis cluster have sufficient nodes or not -func checkRedisCluster(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) [][]string { - redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") - defer redisClient.Close() - cmd := redis.NewStringCmd(ctx, "cluster", "nodes") - err := redisClient.Process(ctx, cmd) +func checkRedisCluster(ctx context.Context, redisClient *redis.Client, logger logr.Logger) [][]string { + output, err := redisClient.ClusterNodes(ctx).Result() if err != nil { - logger.Error(err, "Redis command failed with this error") - } - - output, err := cmd.Result() - if err != nil { - logger.Error(err, "Redis command failed with this error") + logger.Error(err, "Error in getting Redis cluster nodes") } logger.V(1).Info("Redis cluster nodes are listed", "Output", output) @@ -298,8 +294,10 @@ func executeFailoverCommand(ctx context.Context, client kubernetes.Interface, lo // CheckRedisNodeCount will check the count of redis nodes func CheckRedisNodeCount(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, nodeType string) int32 { + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() var redisNodeType string - clusterNodes := checkRedisCluster(ctx, client, logger, cr) + clusterNodes := checkRedisCluster(ctx, redisClient, logger) count := len(clusterNodes) switch nodeType { @@ -326,7 +324,9 @@ func CheckRedisNodeCount(ctx context.Context, client kubernetes.Interface, logge // CheckRedisClusterState will check the redis cluster state func CheckRedisClusterState(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) int { - clusterNodes := checkRedisCluster(ctx, client, logger, cr) + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() + clusterNodes := checkRedisCluster(ctx, redisClient, logger) count := 0 for _, node := range clusterNodes { if strings.Contains(node[2], "fail") || strings.Contains(node[7], "disconnected") { diff --git a/k8sutils/redis_test.go b/k8sutils/redis_test.go index 9b5adfecf..941005582 100644 --- a/k8sutils/redis_test.go +++ b/k8sutils/redis_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" mock_utils "github.com/OT-CONTAINER-KIT/redis-operator/mocks/utils" "github.com/go-logr/logr" @@ -16,6 +17,8 @@ import ( "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" k8sClientFake "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/ptr" ) @@ -349,22 +352,84 @@ func TestGetRedisTLSArgs(t *testing.T) { } func TestCreateRedisReplicationCommand(t *testing.T) { + logger := logr.Discard() + type secret struct { + name string + namespace string + key string + } tests := []struct { - name string - redisCluster *redisv1beta2.RedisCluster + name string + redisCluster *redisv1beta2.RedisCluster + secret leaderPod RedisDetails followerPod RedisDetails expectedCommand []string }{ { name: "Test case with cluster version v7", + secret: secret{ + name: "redis-password-secret", + namespace: "default", + key: "password", + }, redisCluster: &redisv1beta2.RedisCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "redis-cluster", Namespace: "default", }, Spec: redisv1beta2.RedisClusterSpec{ - Size: ptr.To(int32(3)), + Size: ptr.To(int32(3)), + KubernetesConfig: redisv1beta2.KubernetesConfig{ + KubernetesConfig: api.KubernetesConfig{ + ExistingPasswordSecret: &api.ExistingPasswordSecret{ + Name: ptr.To("redis-password-secret"), + Key: ptr.To("password"), + }, + }, + }, + ClusterVersion: ptr.To("v7"), + Port: ptr.To(6379), + }, + }, + leaderPod: RedisDetails{ + PodName: "redis-cluster-leader-0", + Namespace: "default", + }, + followerPod: RedisDetails{ + PodName: "redis-cluster-follower-0", + Namespace: "default", + }, + expectedCommand: []string{ + "redis-cli", "--cluster", "add-node", + "redis-cluster-follower-0.redis-cluster-follower-headless.default.svc:6379", + "redis-cluster-leader-0.redis-cluster-leader-headless.default.svc:6379", + "--cluster-slave", + "-a", "password", + }, + }, + { + name: "Test case with cluster version v7 failed to get password", + secret: secret{ + name: "wrong-name", + namespace: "default", + key: "password", + }, + redisCluster: &redisv1beta2.RedisCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "redis-cluster", + Namespace: "default", + }, + Spec: redisv1beta2.RedisClusterSpec{ + Size: ptr.To(int32(3)), + KubernetesConfig: redisv1beta2.KubernetesConfig{ + KubernetesConfig: api.KubernetesConfig{ + ExistingPasswordSecret: &api.ExistingPasswordSecret{ + Name: ptr.To("redis-password-secret"), + Key: ptr.To("password"), + }, + }, + }, ClusterVersion: ptr.To("v7"), Port: ptr.To(6379), }, @@ -415,9 +480,17 @@ func TestCreateRedisReplicationCommand(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - client := mock_utils.CreateFakeClientWithPodIPs(tt.redisCluster) - logger := testr.New(t) + pods := mock_utils.CreateFakeObjectWithPodIPs(tt.redisCluster) + var secret []runtime.Object + if tt.redisCluster.Spec.KubernetesConfig.ExistingPasswordSecret != nil { + secret = mock_utils.CreateFakeObjectWithSecret(tt.secret.name, tt.secret.namespace, tt.secret.key) + } + + var objects []runtime.Object + objects = append(objects, pods...) + objects = append(objects, secret...) + client := fake.NewSimpleClientset(objects...) cmd := createRedisReplicationCommand(client, logger, tt.redisCluster, tt.leaderPod, tt.followerPod) // Assert the command is as expected using testify @@ -568,6 +641,22 @@ func Test_checkAttachedSlave(t *testing.T) { infoErr: redis.ErrClosed, expectedSlaveCount: -1, }, + { + name: "field not found", + podName: "pod2", + infoReturn: "# Replication\r\n" + + "role:master\r\n" + + "master_failover_state:no-failover\r\n" + + "master_replid:7b634a76ebb7d5f07007f1d5aec8abff8200704e\r\n" + + "master_replid2:0000000000000000000000000000000000000000\r\n" + + "master_repl_offset:0\r\n" + + "second_repl_offset:-1\r\n" + + "repl_backlog_active:0\r\n" + + "repl_backlog_size:1048576\r\n" + + "repl_backlog_first_byte_offset:0\r\n" + + "repl_backlog_histlen:0\r\n", + expectedSlaveCount: 0, + }, } for _, tt := range tests { @@ -598,6 +687,7 @@ func Test_checkRedisServerRole(t *testing.T) { podName string infoReturn string infoErr error + shouldFail bool expectedResult string }{ { @@ -635,10 +725,26 @@ func Test_checkRedisServerRole(t *testing.T) { expectedResult: "slave", }, { - name: "error fetching role info", - podName: "pod3", - infoErr: redis.ErrClosed, - expectedResult: "", + name: "error fetching role info", + podName: "pod3", + infoErr: redis.ErrClosed, + shouldFail: true, + }, + { + name: "field not found", + podName: "pod2", + infoReturn: "# Replication\r\n" + + "connected_slaves:0\r\n" + + "master_failover_state:no-failover\r\n" + + "master_replid:7b634a76ebb7d5f07007f1d5aec8abff8200704e\r\n" + + "master_replid2:0000000000000000000000000000000000000000\r\n" + + "master_repl_offset:0\r\n" + + "second_repl_offset:-1\r\n" + + "repl_backlog_active:0\r\n" + + "repl_backlog_size:1048576\r\n" + + "repl_backlog_first_byte_offset:0\r\n" + + "repl_backlog_histlen:0\r\n", + shouldFail: true, }, } @@ -654,10 +760,72 @@ func Test_checkRedisServerRole(t *testing.T) { } role := checkRedisServerRole(ctx, client, logger, tt.podName) - assert.Equal(t, tt.expectedResult, role, "Test case: "+tt.name) + if tt.shouldFail { + assert.Empty(t, role, "Test case: "+tt.name) + } else { + assert.Equal(t, tt.expectedResult, role, "Test case: "+tt.name) + } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unmet expectations: %s", err) } }) } } + +func TestCheckRedisCluster(t *testing.T) { + logger := logr.Discard() // Discard logs + + tests := []struct { + name string + expectError error + clusterNodesOutput string + expectedResult [][]string + }{ + { + name: "Detailed cluster nodes output", + clusterNodesOutput: `07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004,hostname4 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected +67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002,hostname2 master - 0 1426238316232 2 connected 5461-10922 +292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003,hostname3 master - 0 1426238318243 3 connected 10923-16383 +6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005,hostname5 slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected +824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006,hostname6 slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected +e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001,hostname1 myself,master - 0 0 1 connected 0-5460`, + expectedResult: [][]string{ + {"07c37dfeb235213a872192d90877d0cd55635b91", "127.0.0.1:30004@31004,hostname4", "slave", "e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca", "0", "1426238317239", "4", "connected"}, + {"67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1", "127.0.0.1:30002@31002,hostname2", "master", "-", "0", "1426238316232", "2", "connected", "5461-10922"}, + {"292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f", "127.0.0.1:30003@31003,hostname3", "master", "-", "0", "1426238318243", "3", "connected", "10923-16383"}, + {"6ec23923021cf3ffec47632106199cb7f496ce01", "127.0.0.1:30005@31005,hostname5", "slave", "67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1", "0", "1426238316232", "5", "connected"}, + {"824fe116063bc5fcf9f4ffd895bc17aee7731ac3", "127.0.0.1:30006@31006,hostname6", "slave", "292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f", "0", "1426238317741", "6", "connected"}, + {"e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca", "127.0.0.1:30001@31001,hostname1", "myself,master", "-", "0", "0", "1", "connected", "0-5460"}, + }, + }, + { + name: "Error from ClusterNodes", + expectError: redis.ErrClosed, + expectedResult: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + db, mock := redismock.NewClientMock() + + if tc.expectError != nil { + mock.ExpectClusterNodes().SetErr(tc.expectError) + } else { + mock.ExpectClusterNodes().SetVal(tc.clusterNodesOutput) + } + result := checkRedisCluster(context.TODO(), db, logger) + + if tc.expectError != nil { + assert.Nil(t, result) + } else { + assert.ElementsMatch(t, tc.expectedResult, result) + } + + // Ensure all expectations are met + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } + }) + } +} diff --git a/k8sutils/secrets.go b/k8sutils/secrets.go index 40f3853fe..ab86a5960 100644 --- a/k8sutils/secrets.go +++ b/k8sutils/secrets.go @@ -25,9 +25,11 @@ func getRedisPassword(client kubernetes.Interface, logger logr.Logger, namespace } for key, value := range secretName.Data { if key == secretKey { + logger.V(1).Info("Secret key found in the secret", "secretKey", secretKey) return strings.TrimSpace(string(value)), nil } } + logger.Error(errors.New("secret key not found"), "Secret key not found in the secret") return "", nil } diff --git a/mocks/utils/utils.go b/mocks/utils/utils.go index 9c58952fc..b48dad6a2 100644 --- a/mocks/utils/utils.go +++ b/mocks/utils/utils.go @@ -30,7 +30,7 @@ func CreateFakeClientWithPodIPs_LeaderPods(cr *redisv1beta2.RedisCluster) *fake. return fake.NewSimpleClientset(pods...) } -func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { +func CreateFakeObjectWithPodIPs(cr *redisv1beta2.RedisCluster) []runtime.Object { leaderReplicas := cr.Spec.GetReplicaCounts("leader") followerReplicas := cr.Spec.GetReplicaCounts("follower") pods := make([]runtime.Object, leaderReplicas+followerReplicas) @@ -60,7 +60,20 @@ func CreateFakeClientWithPodIPs(cr *redisv1beta2.RedisCluster) *fake.Clientset { } } - return fake.NewSimpleClientset(pods...) + return pods +} + +func CreateFakeObjectWithSecret(name, namespace, key string) []runtime.Object { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Data: map[string][]byte{ + key: []byte("password"), + }, + } + return []runtime.Object{secret} } func CreateFakeClientWithSecrets(cr *redisv1beta2.RedisCluster, secretName, secretKey, secretValue string) *fake.Clientset { From 86945fc2c4557089d4df944b201bae5cc0c4f988 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 2 Apr 2024 02:36:47 +0800 Subject: [PATCH 140/203] refactor: add common AddFinalizer for all api (#858) Signed-off-by: drivebyer --- controllers/redis_controller.go | 2 +- controllers/rediscluster_controller.go | 2 +- controllers/redisreplication_controller.go | 2 +- controllers/redissentinel_controller.go | 2 +- k8sutils/finalizer.go | 35 +- .../{finalizers_test.go => finalizer_test.go} | 334 +++--------------- 6 files changed, 48 insertions(+), 329 deletions(-) rename k8sutils/{finalizers_test.go => finalizer_test.go} (74%) diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index 9524cc240..991c18d48 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -60,7 +60,7 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl return ctrl.Result{}, err } - if err = k8sutils.AddRedisFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddFinalizer(instance, k8sutils.RedisFinalizer, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 7cf371721..8036517e3 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -69,7 +69,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } - if err = k8sutils.AddRedisClusterFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddFinalizer(instance, k8sutils.RedisClusterFinalizer, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 98a2b9fac..4f2c08000 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -51,7 +51,7 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, err } - if err = k8sutils.AddRedisReplicationFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddFinalizer(instance, k8sutils.RedisReplicationFinalizer, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 831dfaf16..a3c4fe53c 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -57,7 +57,7 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{RequeueAfter: time.Second * 60}, err } - if err = k8sutils.AddRedisSentinelFinalizer(instance, r.Client); err != nil { + if err = k8sutils.AddFinalizer(instance, k8sutils.RedisSentinelFinalizer, r.Client); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index ff3ade1ba..075725015 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -92,37 +92,10 @@ func HandleRedisSentinelFinalizer(ctrlclient client.Client, logger logr.Logger, return nil } -// AddRedisFinalizer add finalizer for graceful deletion -func AddRedisFinalizer(cr *redisv1beta2.Redis, cl client.Client) error { - if !controllerutil.ContainsFinalizer(cr, RedisFinalizer) { - controllerutil.AddFinalizer(cr, RedisFinalizer) - return cl.Update(context.TODO(), cr) - } - return nil -} - -// AddRedisClusterFinalizer add finalizer for graceful deletion -func AddRedisClusterFinalizer(cr *redisv1beta2.RedisCluster, cl client.Client) error { - if !controllerutil.ContainsFinalizer(cr, RedisClusterFinalizer) { - controllerutil.AddFinalizer(cr, RedisClusterFinalizer) - return cl.Update(context.TODO(), cr) - } - return nil -} - -// AddRedisReplicationFinalizer add finalizer for graceful deletion -func AddRedisReplicationFinalizer(cr *redisv1beta2.RedisReplication, cl client.Client) error { - if !controllerutil.ContainsFinalizer(cr, RedisReplicationFinalizer) { - controllerutil.AddFinalizer(cr, RedisReplicationFinalizer) - return cl.Update(context.TODO(), cr) - } - return nil -} - -// AddRedisSentinelFinalizer add finalizer for graceful deletion -func AddRedisSentinelFinalizer(cr *redisv1beta2.RedisSentinel, cl client.Client) error { - if !controllerutil.ContainsFinalizer(cr, RedisSentinelFinalizer) { - controllerutil.AddFinalizer(cr, RedisSentinelFinalizer) +// AddFinalizer add finalizer for graceful deletion +func AddFinalizer(cr client.Object, finalizer string, cl client.Client) error { + if !controllerutil.ContainsFinalizer(cr, finalizer) { + controllerutil.AddFinalizer(cr, finalizer) return cl.Update(context.TODO(), cr) } return nil diff --git a/k8sutils/finalizers_test.go b/k8sutils/finalizer_test.go similarity index 74% rename from k8sutils/finalizers_test.go rename to k8sutils/finalizer_test.go index eac381cbd..ab73107fc 100644 --- a/k8sutils/finalizers_test.go +++ b/k8sutils/finalizer_test.go @@ -825,326 +825,72 @@ func helperRedisClusterPVCs(clusterName string, namespace string) []*corev1.Pers return pvcs } -func TestAddRedisFinalizer(t *testing.T) { - fakeFinalizer := "FakeFinalizer" +func TestAddFinalizer(t *testing.T) { + type args struct { + cr *v1beta2.Redis + finalizer string + } tests := []struct { - name string - redisStandalone *v1beta2.Redis - want *v1beta2.Redis - expectError bool + name string + args args + want *v1beta2.Redis + wantErr bool }{ { - name: "Redis CR without finalizer", - redisStandalone: &v1beta2.Redis{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-standalone", - Namespace: "default", + name: "CR without finalizer", + args: args{ + cr: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis", + Namespace: "default", + Finalizers: []string{}, + }, }, + finalizer: RedisFinalizer, }, want: &v1beta2.Redis{ ObjectMeta: metav1.ObjectMeta{ - Name: "redis-standalone", + Name: "test-redis", Namespace: "default", Finalizers: []string{RedisFinalizer}, }, }, - expectError: false, + wantErr: false, }, { - name: "Redis CR with finalizer", - redisStandalone: &v1beta2.Redis{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-standalone", - Namespace: "default", - Finalizers: []string{RedisFinalizer}, + name: "CR with finalizer", + args: args{ + cr: &v1beta2.Redis{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-redis", + Namespace: "default", + Finalizers: []string{RedisFinalizer}, + }, }, + finalizer: RedisFinalizer, }, want: &v1beta2.Redis{ ObjectMeta: metav1.ObjectMeta{ - Name: "redis-standalone", + Name: "test-redis", Namespace: "default", Finalizers: []string{RedisFinalizer}, }, }, - expectError: false, - }, - { - name: "Redis CR with random finalizer", - redisStandalone: &v1beta2.Redis{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-standalone", - Namespace: "default", - Finalizers: []string{fakeFinalizer}, - }, - }, - want: &v1beta2.Redis{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-standalone", - Namespace: "default", - Finalizers: []string{fakeFinalizer, RedisFinalizer}, - }, - }, - expectError: false, - }, - } - - for _, tc := range tests { - mockClient := &mockClient.MockClient{ - UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - return nil - }, - } - t.Run(tc.name, func(t *testing.T) { - err := AddRedisFinalizer(tc.redisStandalone, mockClient) - if tc.expectError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tc.want, tc.redisStandalone) - } - }) - } -} - -func TestAddRedisClusterFinalizer(t *testing.T) { - fakeFinalizer := "FakeFinalizer" - tests := []struct { - name string - redisCluster *v1beta2.RedisCluster - want *v1beta2.RedisCluster - expectError bool - }{ - { - name: "Redis Cluster CR without finalizer", - redisCluster: &v1beta2.RedisCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - }, - }, - want: &v1beta2.RedisCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - Finalizers: []string{RedisClusterFinalizer}, - }, - }, - expectError: false, - }, - { - name: "Redis Cluster CR with finalizer", - redisCluster: &v1beta2.RedisCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - Finalizers: []string{RedisClusterFinalizer}, - }, - }, - want: &v1beta2.RedisCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - Finalizers: []string{RedisClusterFinalizer}, - }, - }, - expectError: false, - }, - { - name: "Redis Cluster CR with random finalizer", - redisCluster: &v1beta2.RedisCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - Finalizers: []string{fakeFinalizer}, - }, - }, - want: &v1beta2.RedisCluster{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - Finalizers: []string{fakeFinalizer, RedisClusterFinalizer}, - }, - }, - expectError: false, + wantErr: false, }, } - - for _, tc := range tests { - mockClient := &mockClient.MockClient{ - UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - return nil - }, - } - t.Run(tc.name, func(t *testing.T) { - err := AddRedisClusterFinalizer(tc.redisCluster, mockClient) - if tc.expectError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tc.want, tc.redisCluster) - } - }) - } -} - -func TestAddRedisReplicationFinalizer(t *testing.T) { - fakeFinalizer := "FakeFinalizer" - tests := []struct { - name string - redisReplication *v1beta2.RedisReplication - want *v1beta2.RedisReplication - expectError bool - }{ - { - name: "Redis Replication CR without finalizer", - redisReplication: &v1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-replication", - Namespace: "default", - }, - }, - want: &v1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-replication", - Namespace: "default", - Finalizers: []string{RedisReplicationFinalizer}, - }, - }, - expectError: false, - }, - { - name: "Redis Replication CR with finalizer", - redisReplication: &v1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-replication", - Namespace: "default", - Finalizers: []string{RedisReplicationFinalizer}, - }, - }, - want: &v1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-replication", - Namespace: "default", - Finalizers: []string{RedisReplicationFinalizer}, - }, - }, - expectError: false, - }, - { - name: "Redis Replication CR with random finalizer", - redisReplication: &v1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-replication", - Namespace: "default", - Finalizers: []string{fakeFinalizer}, - }, - }, - want: &v1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-replication", - Namespace: "default", - Finalizers: []string{fakeFinalizer, RedisReplicationFinalizer}, + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mc := &mockClient.MockClient{ + UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { + return nil }, - }, - expectError: false, - }, - } - - for _, tc := range tests { - mockClient := &mockClient.MockClient{ - UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - return nil - }, - } - t.Run(tc.name, func(t *testing.T) { - err := AddRedisReplicationFinalizer(tc.redisReplication, mockClient) - if tc.expectError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tc.want, tc.redisReplication) } - }) - } -} - -func TestAddRedisSentinelFinalizer(t *testing.T) { - fakeFinalizer := "FakeFinalizer" - tests := []struct { - name string - redisSentinel *v1beta2.RedisSentinel - want *v1beta2.RedisSentinel - expectError bool - }{ - { - name: "Redis Sentinel CR without finalizer", - redisSentinel: &v1beta2.RedisSentinel{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-sentinel", - Namespace: "default", - }, - }, - want: &v1beta2.RedisSentinel{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-sentinel", - Namespace: "default", - Finalizers: []string{RedisSentinelFinalizer}, - }, - }, - expectError: false, - }, - { - name: "Redis Sentinel CR with finalizer", - redisSentinel: &v1beta2.RedisSentinel{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-sentinel", - Namespace: "default", - Finalizers: []string{RedisSentinelFinalizer}, - }, - }, - want: &v1beta2.RedisSentinel{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-sentinel", - Namespace: "default", - Finalizers: []string{RedisSentinelFinalizer}, - }, - }, - expectError: false, - }, - { - name: "Redis Sentinel CR with random finalizer", - redisSentinel: &v1beta2.RedisSentinel{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-sentinel", - Namespace: "default", - Finalizers: []string{fakeFinalizer}, - }, - }, - want: &v1beta2.RedisSentinel{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-sentinel", - Namespace: "default", - Finalizers: []string{fakeFinalizer, RedisSentinelFinalizer}, - }, - }, - expectError: false, - }, - } - - for _, tc := range tests { - mockClient := &mockClient.MockClient{ - UpdateFn: func(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { - return nil - }, - } - t.Run(tc.name, func(t *testing.T) { - err := AddRedisSentinelFinalizer(tc.redisSentinel, mockClient) - if tc.expectError { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tc.want, tc.redisSentinel) + err := AddFinalizer(tt.args.cr, tt.args.finalizer, mc) + if (err != nil) != tt.wantErr { + t.Errorf("AddFinalizer() error = %v, wantErr %v", err, tt.wantErr) } + assert.Equal(t, tt.want.ObjectMeta.Finalizers, tt.args.cr.ObjectMeta.Finalizers) }) } } From a87435680e8197cc433b8e790724fa6a191f3673 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 13 Apr 2024 20:52:48 +0800 Subject: [PATCH 141/203] feat: implement redis cluster ready state (#867) Signed-off-by: drivebyer --- api/status/redis-cluster_status.go | 1 + controllers/rediscluster_controller.go | 11 +++-- k8sutils/redis.go | 48 ++++++++++++++++--- .../setup/redis-cluster/chainsaw-test.yaml | 47 ++---------------- .../setup/redis-cluster/ready-cluster.yaml | 2 + 5 files changed, 56 insertions(+), 53 deletions(-) diff --git a/api/status/redis-cluster_status.go b/api/status/redis-cluster_status.go index d80b6fca0..6ccf24da2 100644 --- a/api/status/redis-cluster_status.go +++ b/api/status/redis-cluster_status.go @@ -11,6 +11,7 @@ const ( // Status Field of the Redis Cluster const ( + // RedisClusterReady means the RedisCluster is ready for use, we use redis-cli --cluster check 127.0.0.1:6379 to check the cluster status RedisClusterReady RedisClusterState = "Ready" RedisClusterInitializing RedisClusterState = "Initializing" RedisClusterBootstrap RedisClusterState = "Bootstrap" diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 8036517e3..c15fbb96b 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -230,16 +230,17 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "") == totalReplicas { k8sutils.CheckIfEmptyMasters(ctx, r.K8sClient, r.Log, instance) } - reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") // Mark the cluster status as ready if all the leader and follower nodes are ready if instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas, r.Dk8sClient) - if err != nil { - return ctrl.Result{}, err + if k8sutils.RedisClusterStatusHealth(ctx, r.K8sClient, r.Log, instance) { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas, r.Dk8sClient) + if err != nil { + return ctrl.Result{}, err + } } } - + reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 525677a2e..1c9002dfc 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -322,6 +322,34 @@ func CheckRedisNodeCount(ctx context.Context, client kubernetes.Interface, logge return int32(count) } +// RedisClusterStatusHealth use `redis-cli --cluster check 127.0.0.1:6379` +func RedisClusterStatusHealth(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) bool { + redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") + defer redisClient.Close() + + cmd := []string{"redis-cli", "--cluster", "check", "127.0.0.1:6379"} + if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { + pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + if err != nil { + logger.Error(err, "Error in getting redis password") + } + cmd = append(cmd, "-a") + cmd = append(cmd, pass) + } + cmd = append(cmd, getRedisTLSArgs(cr.Spec.TLS, cr.ObjectMeta.Name+"-leader-0")...) + out, err := executeCommand1(client, logger, cr, cmd, cr.ObjectMeta.Name+"-leader-0") + if err != nil { + return false + } + // [OK] xxx keys in xxx masters. + // [OK] All nodes agree about slots configuration. + // [OK] All 16384 slots covered. + if strings.Count(out, "[OK]") != 3 { + return false + } + return true +} + // CheckRedisClusterState will check the redis cluster state func CheckRedisClusterState(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) int { redisClient := configureRedisClient(client, logger, cr, cr.ObjectMeta.Name+"-leader-0") @@ -369,6 +397,15 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r // executeCommand will execute the commands in pod func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, cmd []string, podName string) { + execOut, execErr := executeCommand1(client, logger, cr, cmd, podName) + if execErr != nil { + logger.Error(execErr, "Could not execute command", "Command", cmd, "Output", execOut) + return + } + logger.V(1).Info("Successfully executed the command", "Command", cmd, "Output", execOut) +} + +func executeCommand1(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, cmd []string, podName string) (stdout string, stderr error) { var ( execOut bytes.Buffer execErr bytes.Buffer @@ -376,12 +413,12 @@ func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1 config, err := GenerateK8sConfig()() if err != nil { logger.Error(err, "Could not find pod to execute") - return + return "", err } targetContainer, pod := getContainerID(client, logger, cr, podName) if targetContainer < 0 { logger.Error(err, "Could not find pod to execute") - return + return "", err } req := client.CoreV1().RESTClient().Post().Resource("pods").Name(podName).Namespace(cr.Namespace).SubResource("exec") @@ -394,7 +431,7 @@ func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1 exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL()) if err != nil { logger.Error(err, "Failed to init executor") - return + return "", err } err = exec.StreamWithContext(context.Background(), remotecommand.StreamOptions{ @@ -403,10 +440,9 @@ func executeCommand(client kubernetes.Interface, logger logr.Logger, cr *redisv1 Tty: false, }) if err != nil { - logger.Error(err, "Could not execute command", "Command", cmd, "Output", execOut.String(), "Error", execErr.String()) - return + return execOut.String(), fmt.Errorf("execute command with error: %w, stderr: %s", err, execErr.String()) } - logger.V(1).Info("Successfully executed the command", "Command", cmd, "Output", execOut.String()) + return execOut.String(), nil } // getContainerID will return the id of container from pod diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml index 7af2381d7..f3523e67d 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/chainsaw-test.yaml @@ -24,10 +24,11 @@ spec: selector: control-plane=redis-operator container: manager tail: -1 # tail all logs - - name: Sleep for five minutes - try: - - sleep: - duration: 5m + # no need to wait for 5 minutes, when we have ready-cluster.yaml, we can proceed +# - name: Sleep for five minutes +# try: +# - sleep: +# duration: 3m - name: Ping Cluster try: - script: @@ -66,44 +67,6 @@ spec: redis-cli -c -p 6379 ping check: ($stdout=='PONG'): true - - name: Check Cluster - try: - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - name: Try saving a key With Password try: - script: diff --git a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml index 004498aff..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/setup/redis-cluster/ready-cluster.yaml @@ -6,3 +6,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready From 454e88c936567597214c64692a8e2fe9af5ae980 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Sat, 13 Apr 2024 19:35:35 +0530 Subject: [PATCH 142/203] test: Cover func updatestatefulset (#863) * test case for updatestatefulset functions Signed-off-by: Mahesh Kumar * tests: updated TestUpdateStatefulSet Signed-off-by: Mahesh Kumar * fix: failing test Signed-off-by: Shubham Gupta * test: Add one more case Signed-off-by: Shubham Gupta --------- Signed-off-by: Mahesh Kumar Signed-off-by: Shubham Gupta Co-authored-by: opstree Co-authored-by: Shubham Gupta --- .gitignore | 1 + k8sutils/statefulset.go | 5 +- k8sutils/statefulset_test.go | 125 +++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index d360ec637..969487292 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ testbin/* # Output of the go coverage tool, specifically when used with LiteIDE *.out +coverage.html # Kubernetes Generated files - skip generated files, except for vendored files diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 788851be1..53c0afb84 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -209,7 +209,7 @@ func patchStatefulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St logger.Error(err, "Unable to patch redis statefulset with comparison object") return err } - return updateStatefulSet(namespace, newStateful, recreateStateFulSet, cl) + return updateStatefulSet(cl, logger, namespace, newStateful, recreateStateFulSet) } logger.V(1).Info("Reconciliation Complete, no Changes required.") return nil @@ -698,8 +698,7 @@ func createStatefulSet(cl kubernetes.Interface, logger logr.Logger, namespace st } // updateStatefulSet is a method to update statefulset in Kubernetes -func updateStatefulSet(namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool, cl kubernetes.Interface) error { - logger := statefulSetLogger(namespace, stateful.Name) +func updateStatefulSet(cl kubernetes.Interface, logger logr.Logger, namespace string, stateful *appsv1.StatefulSet, recreateStateFulSet bool) error { _, err := cl.AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{}) if recreateStateFulSet { sErr, ok := err.(*apierrors.StatusError) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 0c0c75491..0cc6919c6 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -1,6 +1,7 @@ package k8sutils import ( + "context" "path" "testing" @@ -10,7 +11,9 @@ import ( "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" k8sClientFake "k8s.io/client-go/kubernetes/fake" "k8s.io/utils/ptr" ) @@ -284,6 +287,128 @@ func Test_createStatefulSet(t *testing.T) { } } +func TestUpdateStatefulSet(t *testing.T) { + logger := logr.Discard() + tests := []struct { + name string + existingStsSpec appsv1.StatefulSetSpec + updatedStsSpec appsv1.StatefulSetSpec + recreateSts bool + stsPresent bool + expectErr error + }{ + { + name: "Update StatefulSet without recreate in existing Statefulset", + existingStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(3)), + }, + updatedStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(5)), + }, + recreateSts: false, + stsPresent: true, + }, + { + name: "Update StatefulSet with recreate in existing Statefulset", + existingStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(2)), + }, + updatedStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(4)), + }, + recreateSts: true, + stsPresent: true, + }, + { + name: "Update StatefulSet without recreate StatefulSet is not present", + existingStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(2)), + }, + updatedStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(4)), + }, + recreateSts: false, + stsPresent: false, + expectErr: kerrors.NewNotFound(schema.GroupResource{Group: "apps", Resource: "statefulsets"}, "test-sts"), + }, + { + name: "Update StatefulSet without recreate StatefulSet", + existingStsSpec: appsv1.StatefulSetSpec{ + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "name": "redis", + }, + }, + }, + }, + updatedStsSpec: appsv1.StatefulSetSpec{ + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "name": "redis-standalone", + }, + }, + }, + }, + recreateSts: false, + stsPresent: true, + }, + { + name: "Update StatefulSet failed with Invalid Reason", + existingStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(2)), + }, + updatedStsSpec: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(4)), + }, + recreateSts: true, + stsPresent: false, + expectErr: kerrors.NewNotFound(schema.GroupResource{Group: "apps", Resource: "statefulsets"}, "test-sts"), + }, + } + + assert := assert.New(t) + + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + existingSts := appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + Spec: *test.existingStsSpec.DeepCopy(), + } + updatedSts := appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + Spec: *test.updatedStsSpec.DeepCopy(), + } + var client *k8sClientFake.Clientset + if test.stsPresent { + client = k8sClientFake.NewSimpleClientset(existingSts.DeepCopyObject()) + } else { + client = k8sClientFake.NewSimpleClientset() + } + err := updateStatefulSet(client, logger, updatedSts.GetNamespace(), &updatedSts, test.recreateSts) + if test.expectErr != nil { + assert.Error(err, "Expected Error while updating Statefulset") + assert.Equal(test.expectErr, err) + } else { + assert.NoError(err, "Error while updating Statefulset") + } + if err == nil { + getUpdatedSts, err := client.AppsV1().StatefulSets(updatedSts.GetNamespace()).Get(context.TODO(), updatedSts.GetName(), metav1.GetOptions{}) + assert.NoError(err, "Error getting Updted StatefulSet") + assert.NotEqual(getUpdatedSts.DeepCopy(), existingSts.DeepCopy(), "StatefulSet not updated") + } + }) + } +} + func TestGenerateTLSEnvironmentVariables(t *testing.T) { tlsConfig := &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ From 7b8c3757b20d4a415f2fd80f63b3d5ac4025ddf5 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 16 Apr 2024 21:42:43 +0800 Subject: [PATCH 143/203] ci: validate yaml before run e2e (#873) Signed-off-by: drivebyer --- .github/workflows/e2e-chainsaw.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index a3e75a3dc..a88ab622a 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -22,6 +22,7 @@ jobs: run: yamllint --strict ./tests/ test: + needs: [validate-yaml] name: ${{ matrix.testpath }} runs-on: ubuntu-latest strategy: From 80e7f2fd3b647bfacda8a42f1702c2d21e1e4346 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 16 Apr 2024 21:44:03 +0800 Subject: [PATCH 144/203] fix: redis cluster update as scale out (#872) * fix: redis cluster update as scale out Signed-off-by: drivebyer * add e2e test step && remove unnecessary test assert Signed-off-by: drivebyer * add newline Signed-off-by: drivebyer * add newline Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- api/status/redis-cluster_status.go | 6 +- controllers/rediscluster_controller.go | 10 +- .../scaling/redis-cluster/chainsaw-test.yaml | 257 ++---------------- .../cluster-scale-out-status-00.yaml | 10 + .../cluster-scale-out-status-01.yaml | 10 + .../cluster-scale-out-status-02.yaml | 10 + ....yaml => cluster-scale-out-status-03.yaml} | 1 + ...r-scale-up.yaml => cluster-scale-out.yaml} | 0 ...dy-cluster.yaml => cluster-status-00.yaml} | 1 + .../redis-cluster/ready-sts-scale-up.yaml | 24 -- .../scaling/redis-cluster/ready-sts.yaml | 24 -- 11 files changed, 61 insertions(+), 292 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-00.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-01.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-02.yaml rename tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/{ready-cluster-scale-up.yaml => cluster-scale-out-status-03.yaml} (85%) rename tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/{cluster-scale-up.yaml => cluster-scale-out.yaml} (100%) rename tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/{ready-cluster.yaml => cluster-status-00.yaml} (85%) delete mode 100644 tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml delete mode 100644 tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml diff --git a/api/status/redis-cluster_status.go b/api/status/redis-cluster_status.go index 6ccf24da2..e58c62ea5 100644 --- a/api/status/redis-cluster_status.go +++ b/api/status/redis-cluster_status.go @@ -3,17 +3,17 @@ package status type RedisClusterState string const ( - ReadyClusterReason string = "RedisCluster is ready" InitializingClusterLeaderReason string = "RedisCluster is initializing leaders" InitializingClusterFollowerReason string = "RedisCluster is initializing followers" BootstrapClusterReason string = "RedisCluster is bootstrapping" + ReadyClusterReason string = "RedisCluster is ready" ) // Status Field of the Redis Cluster const ( - // RedisClusterReady means the RedisCluster is ready for use, we use redis-cli --cluster check 127.0.0.1:6379 to check the cluster status - RedisClusterReady RedisClusterState = "Ready" RedisClusterInitializing RedisClusterState = "Initializing" RedisClusterBootstrap RedisClusterState = "Bootstrap" + // RedisClusterReady means the RedisCluster is ready for use, we use redis-cli --cluster check 127.0.0.1:6379 to check the cluster status + RedisClusterReady RedisClusterState = "Ready" // RedisClusterFailed RedisClusterState = "Failed" ) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index c15fbb96b..2b07657b2 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -108,8 +108,9 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Mark the cluster status as initializing if there are no leader or follower nodes - if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, 0, 0, r.Dk8sClient) + if (instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0) || + instance.Status.ReadyLeaderReplicas != leaderReplicas { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, instance.Status.ReadyLeaderReplicas, instance.Status.ReadyFollowerReplicas, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } @@ -141,8 +142,9 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if redisLeaderInfo.Status.ReadyReplicas == leaderReplicas { // Mark the cluster status as initializing if there are no follower nodes - if instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0 { - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, 0, r.Dk8sClient) + if (instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0) || + instance.Status.ReadyFollowerReplicas != followerReplicas { + err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, instance.Status.ReadyFollowerReplicas, r.Dk8sClient) if err != nil { return ctrl.Result{}, err } diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml index 6eafeb05d..73085d4f9 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml @@ -11,246 +11,29 @@ spec: - create: file: cluster.yaml - assert: - file: ready-cluster.yaml - - assert: - file: ready-sts.yaml - - name: Sleep for five minutes - try: - - sleep: - duration: 5m - - name: Ping Cluster Nodes - try: - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - name: Check Cluster Slots - try: - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - name: Scale Redis Cluster + file: cluster-status-00.yaml + + - name: Scale Out Redis Cluster try: - apply: - file: cluster-scale-up.yaml - - assert: - file: ready-cluster-scale-up.yaml + file: cluster-scale-out.yaml + + - name: Check Status 00 + try: - assert: - file: ready-sts-scale-up.yaml - - name: Sleep for five minutes + file: cluster-scale-out-status-00.yaml + + - name: Check Status 01 try: - - sleep: - duration: 5m - - name: Ping Scaled Cluster Nodes + - assert: + file: cluster-scale-out-status-01.yaml + + - name: Check Status 02 try: - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- - redis-cli -c -p 6379 ping - check: - ($stdout=='PONG'): true - - name: Check Scaled Cluster Slots + - assert: + file: cluster-scale-out-status-02.yaml + + - name: Check Status 03 try: - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-3 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered.' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-4 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-5 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-3 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-4 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true - - script: - content: > - kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-5 -- - redis-cli --cluster check 127.0.0.1:6379 | grep 'All 16384 slots covered' - check: - ($stdout=='[OK] All 16384 slots covered.'): true + - assert: + file: cluster-scale-out-status-03.yaml diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-00.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-00.yaml new file mode 100644 index 000000000..911b0b396 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-00.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + state: Initializing + reason: RedisCluster is initializing leaders + readyLeaderReplicas: 3 + readyFollowerReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-01.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-01.yaml new file mode 100644 index 000000000..de83a1cfe --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-01.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + state: Initializing + reason: RedisCluster is initializing followers + readyLeaderReplicas: 6 + readyFollowerReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-02.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-02.yaml new file mode 100644 index 000000000..486807c1d --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-02.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + state: Bootstrap + reason: RedisCluster is bootstrapping + readyLeaderReplicas: 6 + readyFollowerReplicas: 6 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-03.yaml similarity index 85% rename from tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-03.yaml index eb06df309..593fde3e3 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster-scale-up.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out-status-03.yaml @@ -5,5 +5,6 @@ metadata: name: redis-cluster-v1beta2 status: state: Ready + reason: RedisCluster is ready readyLeaderReplicas: 6 readyFollowerReplicas: 6 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out.yaml similarity index 100% rename from tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-up.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-scale-out.yaml diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml similarity index 85% rename from tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml rename to tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml index bc823bbb0..3d3d27ef6 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml @@ -5,5 +5,6 @@ metadata: name: redis-cluster-v1beta2 status: state: Ready + reason: RedisCluster is ready readyLeaderReplicas: 3 readyFollowerReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml deleted file mode 100644 index 6de6ae80b..000000000 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts-scale-up.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-leader - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - replicas: 6 - readyReplicas: 6 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-follower - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - replicas: 6 - readyReplicas: 6 diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml deleted file mode 100644 index 73545eaab..000000000 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/ready-sts.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-leader - labels: - app: redis-cluster-v1beta2-leader - redis_setup_type: cluster - role: leader -status: - replicas: 3 - readyReplicas: 3 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta2-follower - labels: - app: redis-cluster-v1beta2-follower - redis_setup_type: cluster - role: follower -status: - replicas: 3 - readyReplicas: 3 From 15df443f6b4b7eb570593794897cc1e56d2b29c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:07:50 +0800 Subject: [PATCH 145/203] chore(deps): bump k8s.io/api from 0.29.3 to 0.29.4 (#874) Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.29.3 to 0.29.4. - [Commits](https://github.com/kubernetes/api/compare/v0.29.3...v0.29.4) --- updated-dependencies: - dependency-name: k8s.io/api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 818aa00dd..69763fd2d 100644 --- a/go.mod +++ b/go.mod @@ -11,8 +11,8 @@ require ( github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 - k8s.io/api v0.29.3 - k8s.io/apimachinery v0.29.3 + k8s.io/api v0.29.4 + k8s.io/apimachinery v0.29.4 k8s.io/client-go v0.29.3 k8s.io/utils v0.0.0-20240310230437-4693a0247e57 sigs.k8s.io/controller-runtime v0.17.2 @@ -60,7 +60,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/net v0.22.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect diff --git a/go.sum b/go.sum index 71ba88c4d..dc146dfb6 100644 --- a/go.sum +++ b/go.sum @@ -224,8 +224,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= @@ -323,13 +323,13 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/api v0.29.4 h1:WEnF/XdxuCxdG3ayHNRR8yH3cI1B/llkWBma6bq4R3w= +k8s.io/api v0.29.4/go.mod h1:DetSv0t4FBTcEpfA84NJV3g9a7+rSzlUHk5ADAYHUv0= k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q= +k8s.io/apimachinery v0.29.4/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y= k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= From b37366a67015d46a189f9a60f8f98f56e1f6aa57 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Fri, 19 Apr 2024 17:42:19 +0530 Subject: [PATCH 146/203] test: cover func enableRedisMonitoring (#883) Signed-off-by: Mahesh Kumar --- k8sutils/statefulset_test.go | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 0cc6919c6..5e897885c 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -409,6 +409,49 @@ func TestUpdateStatefulSet(t *testing.T) { } } +func TestEnableRedisMonitoring(t *testing.T) { + tests := []struct { + name string + redisExporterParams containerParameters + expectedRedisExporter corev1.Container + }{ + { + name: "Redis Monitoring", + redisExporterParams: containerParameters{ + RedisExporterImage: "redis-exporter:latest", + RedisExporterImagePullPolicy: corev1.PullIfNotPresent, + RedisExporterPort: ptr.To(9121), + }, + expectedRedisExporter: corev1.Container{ + Name: "redis-exporter", + Image: "redis-exporter:latest", + ImagePullPolicy: corev1.PullIfNotPresent, + Env: []corev1.EnvVar{ + { + Name: "REDIS_EXPORTER_WEB_LISTEN_ADDRESS", + Value: ":9121", + }, + }, + Ports: []corev1.ContainerPort{ + { + Name: "redis-exporter", + ContainerPort: 9121, + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + } + + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + redisExporter := enableRedisMonitoring(test.redisExporterParams) + assert.Equal(t, redisExporter, test.expectedRedisExporter, "Redis Exporter Configuration") + }) + } +} + func TestGenerateTLSEnvironmentVariables(t *testing.T) { tlsConfig := &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ From 7999a058f4d3593a1b842165b52dc33e48728f25 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 20 Apr 2024 17:12:08 +0800 Subject: [PATCH 147/203] fix: ClusterSlaves result should be cut (#884) Signed-off-by: drivebyer --- k8sutils/cluster-scaling.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/k8sutils/cluster-scaling.go b/k8sutils/cluster-scaling.go index da68c44a8..4b6edec9e 100644 --- a/k8sutils/cluster-scaling.go +++ b/k8sutils/cluster-scaling.go @@ -259,11 +259,17 @@ func AddRedisNodeToCluster(ctx context.Context, client kubernetes.Interface, log // getAttachedFollowerNodeIDs would return a slice of redis followers attached to a redis leader func getAttachedFollowerNodeIDs(ctx context.Context, redisClient *redis.Client, logger logr.Logger, masterNodeID string) []string { - slaveIDs, err := redisClient.ClusterSlaves(ctx, masterNodeID).Result() + // 3acb029fead40752f432c84f9bed2e639119a573 192.168.84.239:6379@16379,redis-cluster-v1beta2-follower-5 slave e3299968586dd457a8dba04fc6c747cecd38510f 0 1713595736542 6 connected + slaveNodes, err := redisClient.ClusterSlaves(ctx, masterNodeID).Result() if err != nil { logger.Error(err, "Failed to get attached follower node IDs", "masterNodeID", masterNodeID) return nil } + slaveIDs := make([]string, 0, len(slaveNodes)) + for _, slave := range slaveNodes { + stringSlice := strings.Split(slave, " ") + slaveIDs = append(slaveIDs, stringSlice[0]) + } logger.V(1).Info("Slaves Nodes attached to", "node", masterNodeID, "are", slaveIDs) return slaveIDs } From 736836c39ed9d2e0361fe5d72f6f8eff81660972 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 22 Apr 2024 16:41:59 +0800 Subject: [PATCH 148/203] fix: should get the really leader count when scale in (#885) * fix: should get the really leader count when scale in Signed-off-by: drivebyer * fix timeout Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- controllers/rediscluster_controller.go | 18 +++++------------- tests/_config/chainsaw-configuration.yaml | 4 ++-- .../scaling/redis-cluster/chainsaw-test.yaml | 7 +++++++ 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 2b07657b2..d3f6e0df6 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -74,14 +74,10 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } // Check if the cluster is downscaled - if leaderReplicas < instance.Status.ReadyLeaderReplicas { - reqLogger.Info("Redis cluster is downscaling...", "Ready.ReadyLeaderReplicas", instance.Status.ReadyLeaderReplicas, "Expected.ReadyLeaderReplicas", leaderReplicas) - - // loop count times to remove the latest leader/follower pod - count := instance.Status.ReadyLeaderReplicas - leaderReplicas - for i := int32(0); i < count; i++ { - reqLogger.Info("Redis cluster is downscaling", "The times of loop", i) - + if leaderCount := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "leader"); leaderReplicas < leaderCount { + reqLogger.Info("Redis cluster is downscaling...", "Current.LeaderReplicas", leaderCount, "Desired.LeaderReplicas", leaderReplicas) + for shardIdx := leaderCount - 1; shardIdx >= leaderReplicas; shardIdx-- { + reqLogger.Info("Remove the shard", "Shard.Index", shardIdx) // Imp if the last index of leader sts is not leader make it then // check whether the redis is leader or not ? // if not true then make it leader pod @@ -100,11 +96,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Step 3 Rebalance the cluster k8sutils.RebalanceRedisCluster(r.K8sClient, r.Log, instance) reqLogger.Info("Redis cluster is downscaled... Rebalancing the cluster is done") - err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, leaderReplicas, r.Dk8sClient) - if err != nil { - return ctrl.Result{}, err - } - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + return ctrl.Result{RequeueAfter: time.Second * 10}, nil } // Mark the cluster status as initializing if there are no leader or follower nodes diff --git a/tests/_config/chainsaw-configuration.yaml b/tests/_config/chainsaw-configuration.yaml index c5318ce00..3cdac9ba8 100644 --- a/tests/_config/chainsaw-configuration.yaml +++ b/tests/_config/chainsaw-configuration.yaml @@ -9,5 +9,5 @@ spec: timeouts: apply: 5m delete: 5m - assert: 10m - error: 10m + assert: 20m + error: 20m diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml index 73085d4f9..e95ec42cc 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/chainsaw-test.yaml @@ -37,3 +37,10 @@ spec: try: - assert: file: cluster-scale-out-status-03.yaml + + - name: Scale In Redis Cluster + try: + - apply: + file: cluster.yaml + - assert: + file: cluster-status-00.yaml From 80bc4a41c5c8248dcba2b597eeaecc278fe00e41 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Tue, 23 Apr 2024 07:39:19 +0530 Subject: [PATCH 149/203] test: cover generateInitContainerDef (#888) Signed-off-by: Mahesh Kumar --- k8sutils/statefulset_test.go | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 5e897885c..7b0e57d97 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -452,6 +452,72 @@ func TestEnableRedisMonitoring(t *testing.T) { } } +func TestGenerateInitContainerDef(t *testing.T) { + tests := []struct { + name string + initContainerDef initContainerParameters + expectedInitContainerDef []corev1.Container + mountPaths []corev1.VolumeMount + }{ + { + name: "Redis", + initContainerDef: initContainerParameters{ + Image: "redis-init-container:latest", + ImagePullPolicy: corev1.PullAlways, + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + PersistenceEnabled: ptr.To(false), + }, + expectedInitContainerDef: []corev1.Container{ + { + Name: "initRedis", + Image: "redis-init-container:latest", + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + ImagePullPolicy: corev1.PullAlways, + VolumeMounts: getVolumeMount("redisVolume", ptr.To(false), false, false, nil, []corev1.VolumeMount{}, nil, nil), + }, + }, + mountPaths: []corev1.VolumeMount{}, + }, + { + name: "Redis-1", + initContainerDef: initContainerParameters{ + Image: "redis-init-container:latest", + ImagePullPolicy: corev1.PullAlways, + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + PersistenceEnabled: ptr.To(true), + }, + expectedInitContainerDef: []corev1.Container{ + { + Name: "initRedis-1", + Image: "redis-init-container:latest", + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + ImagePullPolicy: corev1.PullAlways, + VolumeMounts: getVolumeMount("Redis-1", ptr.To(true), false, false, nil, []corev1.VolumeMount{ + { + Name: "Redis-1", + MountPath: "/data", + }, + }, nil, nil), + }, + }, + mountPaths: []corev1.VolumeMount{ + { + Name: "Redis-1", + MountPath: "/data", + }, + }, + }, + } + + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + initContainer := generateInitContainerDef(test.name, test.initContainerDef, test.mountPaths) + assert.Equal(t, initContainer, test.expectedInitContainerDef, "Init Container Configuration") + }) + } +} + func TestGenerateTLSEnvironmentVariables(t *testing.T) { tlsConfig := &redisv1beta2.TLSConfig{ TLSConfig: common.TLSConfig{ From f5028bd4bba0f2c016a3d15c362adcfde6771457 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 10:01:12 +0800 Subject: [PATCH 150/203] chore(deps): bump helm/kind-action from 1.9.0 to 1.10.0 (#889) Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/helm/kind-action/releases) - [Commits](https://github.com/helm/kind-action/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: helm/kind-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e-chainsaw.yml | 2 +- .github/workflows/e2e.yaml | 2 +- .github/workflows/validate-example.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml index a88ab622a..cb2b32586 100644 --- a/.github/workflows/e2e-chainsaw.yml +++ b/.github/workflows/e2e-chainsaw.yml @@ -66,7 +66,7 @@ jobs: # uses: shogo82148/actions-setup-redis@v1 - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.9.0 + uses: helm/kind-action@v1.10.0 with: config: tests/_config/kind-config.yaml cluster_name: kind diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 370c15c00..c5bfa34de 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -35,7 +35,7 @@ jobs: sudo mv kubectl /usr/local/bin/ - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.9.0 + uses: helm/kind-action@v1.10.0 with: config: tests/_config/kind-config.yaml cluster_name: kind diff --git a/.github/workflows/validate-example.yaml b/.github/workflows/validate-example.yaml index d6ec8acad..2bfba3120 100644 --- a/.github/workflows/validate-example.yaml +++ b/.github/workflows/validate-example.yaml @@ -28,7 +28,7 @@ jobs: sudo mv kubectl /usr/local/bin/ - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.9.0 + uses: helm/kind-action@v1.10.0 with: cluster_name: kind From 40c4a0d11ecf0d11f7517aa656b6dc2dc5768c58 Mon Sep 17 00:00:00 2001 From: yangw Date: Fri, 26 Apr 2024 17:08:18 +0800 Subject: [PATCH 151/203] refactor: update status if not equal (#900) Signed-off-by: drivebyer --- k8sutils/status.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/k8sutils/status.go b/k8sutils/status.go index 2beb2da91..aa19ea150 100644 --- a/k8sutils/status.go +++ b/k8sutils/status.go @@ -2,8 +2,9 @@ package k8sutils import ( "context" + "reflect" - status "github.com/OT-CONTAINER-KIT/redis-operator/api/status" + "github.com/OT-CONTAINER-KIT/redis-operator/api/status" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -20,13 +21,18 @@ func statusLogger(namespace string, name string) logr.Logger { } // UpdateRedisClusterStatus will update the status of the RedisCluster -func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, status status.RedisClusterState, resaon string, readyLeaderReplicas, readyFollowerReplicas int32, dcl dynamic.Interface) error { +func UpdateRedisClusterStatus(cr *redisv1beta2.RedisCluster, state status.RedisClusterState, reason string, readyLeaderReplicas, readyFollowerReplicas int32, dcl dynamic.Interface) error { logger := statusLogger(cr.Namespace, cr.Name) - cr.Status.State = status - cr.Status.Reason = resaon - cr.Status.ReadyLeaderReplicas = readyLeaderReplicas - cr.Status.ReadyFollowerReplicas = readyFollowerReplicas - + newStatus := redisv1beta2.RedisClusterStatus{ + State: state, + Reason: reason, + ReadyLeaderReplicas: readyLeaderReplicas, + ReadyFollowerReplicas: readyFollowerReplicas, + } + if reflect.DeepEqual(cr.Status, newStatus) { + return nil + } + cr.Status = newStatus gvr := schema.GroupVersionResource{ Group: "redis.redis.opstreelabs.in", Version: "v1beta2", From 3c5373ecd7bf5e6c9139553f8a4ccfadbfe2b6df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:33:14 +0800 Subject: [PATCH 152/203] chore(deps): bump golangci/golangci-lint-action from 4 to 5 (#894) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 4 to 5. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v4...v5) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/operator-ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/operator-ci.yaml index 01e062ffb..b97af383f 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/operator-ci.yaml @@ -50,7 +50,7 @@ jobs: cache: false - name: Run GolangCI-Lint - uses: golangci/golangci-lint-action@v4 + uses: golangci/golangci-lint-action@v5 with: version: v1.54.0 From 4c7b570329b0b44523af6baafe4e4b28703f2e94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:33:43 +0800 Subject: [PATCH 153/203] chore(deps): bump github.com/onsi/gomega from 1.32.0 to 1.33.0 (#881) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.32.0 to 1.33.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.32.0...v1.33.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 69763fd2d..98ae14d1d 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-logr/logr v1.4.1 github.com/go-redis/redismock/v9 v9.2.0 github.com/onsi/ginkgo/v2 v2.17.1 - github.com/onsi/gomega v1.32.0 + github.com/onsi/gomega v1.33.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index dc146dfb6..491677441 100644 --- a/go.sum +++ b/go.sum @@ -159,8 +159,8 @@ github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8 github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk= -github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg= +github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE= +github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= From 9cd2ae947cc3468bcd1ca1bdfe8c8da51f3edc59 Mon Sep 17 00:00:00 2001 From: "Jae Jahng (Jude)" Date: Mon, 29 Apr 2024 16:10:30 +0900 Subject: [PATCH 154/203] fix: exporter can not connect to redis when enable tls (#902) Signed-off-by: wkd-woo --- k8sutils/statefulset.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 53c0afb84..2bbb383df 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -491,6 +491,7 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { func getExporterEnvironmentVariables(params containerParameters) []corev1.EnvVar { var envVars []corev1.EnvVar + redisHost := "redis://localhost:" if params.TLSConfig != nil { envVars = append(envVars, corev1.EnvVar{ Name: "REDIS_EXPORTER_TLS_CLIENT_KEY_FILE", @@ -508,6 +509,7 @@ func getExporterEnvironmentVariables(params containerParameters) []corev1.EnvVar Name: "REDIS_EXPORTER_SKIP_TLS_VERIFICATION", Value: "true", }) + redisHost = "rediss://localhost:" } if params.RedisExporterPort != nil { envVars = append(envVars, corev1.EnvVar{ @@ -518,7 +520,7 @@ func getExporterEnvironmentVariables(params containerParameters) []corev1.EnvVar if params.Port != nil { envVars = append(envVars, corev1.EnvVar{ Name: "REDIS_ADDR", - Value: fmt.Sprintf("redis://localhost:%d", *params.Port), + Value: redisHost + strconv.Itoa(*params.Port), }) } if params.EnabledPassword != nil && *params.EnabledPassword { From f59f71e7b674d61475a257874fde022fe4461a18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:37:02 +0530 Subject: [PATCH 155/203] chore(deps): bump github.com/onsi/ginkgo/v2 from 2.17.1 to 2.17.2 (#903) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.17.1 to 2.17.2. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.17.1...v2.17.2) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 14 +++++++------- go.sum | 35 ++++++++++++++--------------------- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 98ae14d1d..37fec98c9 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/banzaicloud/k8s-objectmatcher v1.8.0 github.com/go-logr/logr v1.4.1 github.com/go-redis/redismock/v9 v9.2.0 - github.com/onsi/ginkgo/v2 v2.17.1 + github.com/onsi/ginkgo/v2 v2.17.2 github.com/onsi/gomega v1.33.0 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 @@ -32,14 +32,14 @@ require ( github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -60,13 +60,13 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/net v0.23.0 // indirect + golang.org/x/net v0.24.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.19.0 // indirect + golang.org/x/tools v0.20.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/go.sum b/go.sum index 491677441..f83f8383f 100644 --- a/go.sum +++ b/go.sum @@ -18,9 +18,6 @@ github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -63,8 +60,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw= github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -101,8 +98,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -112,7 +109,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -155,8 +151,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8= -github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs= +github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= +github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE= @@ -184,7 +180,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -224,8 +219,8 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= @@ -240,7 +235,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -248,12 +242,12 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -273,8 +267,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= -golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -318,7 +312,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 840675c880c78ed78cc99c85f801d119ea06d9b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 13:11:12 +0800 Subject: [PATCH 156/203] chore(deps): bump github.com/onsi/gomega from 1.33.0 to 1.33.1 (#910) Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.33.0 to 1.33.1. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.33.0...v1.33.1) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 37fec98c9..825e76df6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-logr/logr v1.4.1 github.com/go-redis/redismock/v9 v9.2.0 github.com/onsi/ginkgo/v2 v2.17.2 - github.com/onsi/gomega v1.33.0 + github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index f83f8383f..0b865d29b 100644 --- a/go.sum +++ b/go.sum @@ -155,8 +155,8 @@ github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE= -github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= From 95d1f55d5d2143575221d2549d4b0153afc3a682 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 6 May 2024 14:45:02 +0800 Subject: [PATCH 157/203] ci: run e2e after operator ci check (#913) Signed-off-by: drivebyer --- .../workflows/{operator-ci.yaml => ci.yaml} | 81 +++++++++++++++++ .github/workflows/e2e-chainsaw.yml | 88 ------------------- 2 files changed, 81 insertions(+), 88 deletions(-) rename .github/workflows/{operator-ci.yaml => ci.yaml} (55%) delete mode 100644 .github/workflows/e2e-chainsaw.yml diff --git a/.github/workflows/operator-ci.yaml b/.github/workflows/ci.yaml similarity index 55% rename from .github/workflows/operator-ci.yaml rename to .github/workflows/ci.yaml index b97af383f..7d08cc38d 100644 --- a/.github/workflows/operator-ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,6 +22,8 @@ jobs: gotest: name: Go Test runs-on: ubuntu-latest + needs: + - lint steps: - uses: actions/checkout@v4 - name: Set up Go @@ -118,3 +120,82 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GOSEC_OUTPUT: "junit-xml:/github/workspace/gosec-results.xml" + + validate-yaml: + name: Validate YAML + runs-on: ubuntu-latest + needs: + - gotest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install yamllint + run: sudo apt-get install -y yamllint + - name: Lint YAML files + run: yamllint --strict ./tests/ + + e2e-test: + needs: [validate-yaml] + name: ${{ matrix.testpath }} + runs-on: ubuntu-latest + strategy: + matrix: + testpath: + - ./tests/e2e-chainsaw/v1beta2/teardown/ + - ./tests/e2e-chainsaw/v1beta2/setup/ + - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ + - ./tests/e2e-chainsaw/v1beta2/password/ + - ./tests/e2e-chainsaw/v1beta2/ha-setup/ + - ./tests/e2e-chainsaw/v1beta2/ha-failover/ + - ./tests/e2e-chainsaw/v1beta2/nodeport/ + - ./tests/e2e-chainsaw/v1beta2/pvc-name/ + - ./tests/e2e-chainsaw/v1beta2/keep-pvc/ + - ./tests/e2e-chainsaw/v1beta2/acl-user/ + - ./tests/e2e-chainsaw/v1beta2/scaling/ + - ./tests/e2e-chainsaw/v1beta2/ignore-annots/ + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build Dockerfile + run: docker build . --file Dockerfile --tag redis-operator:e2e + + - name: Install chainsaw + uses: kyverno/chainsaw/.github/actions/install@v0.0.9 + with: + release: v0.1.7 + + - name: Check install + run: chainsaw version + + - name: Install kubectl + run: | + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/ + + # - name: Install Redis + # uses: shogo82148/actions-setup-redis@v1 + + - name: Create k8s Kind Cluster + uses: helm/kind-action@v1.10.0 + with: + config: tests/_config/kind-config.yaml + cluster_name: kind + + - name: Load Docker image into Kind + run: | + kubectl cluster-info --context kind-kind + kind load docker-image redis-operator:e2e --name kind + + - name: Install Redis Operator + run: | + make deploy IMG=redis-operator:e2e + + - name: Wait for Redis Operator to be ready + run: | + kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system + + - name: Run chainsaw test + run: chainsaw test --test-dir ${{ matrix.testpath }} --config tests/_config/chainsaw-configuration.yaml diff --git a/.github/workflows/e2e-chainsaw.yml b/.github/workflows/e2e-chainsaw.yml deleted file mode 100644 index cb2b32586..000000000 --- a/.github/workflows/e2e-chainsaw.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: E2E chainsaw tests - -on: - pull_request: - branches: - - master - push: - branches: - - master - -jobs: - - validate-yaml: - name: Validate YAML - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - name: Install yamllint - run: sudo apt-get install -y yamllint - - name: Lint YAML files - run: yamllint --strict ./tests/ - - test: - needs: [validate-yaml] - name: ${{ matrix.testpath }} - runs-on: ubuntu-latest - strategy: - matrix: - testpath: - - ./tests/e2e-chainsaw/v1beta2/teardown/ - - ./tests/e2e-chainsaw/v1beta2/setup/ - - ./tests/e2e-chainsaw/v1beta2/hostnetwork/ - - ./tests/e2e-chainsaw/v1beta2/password/ - - ./tests/e2e-chainsaw/v1beta2/ha-setup/ - - ./tests/e2e-chainsaw/v1beta2/ha-failover/ - - ./tests/e2e-chainsaw/v1beta2/nodeport/ - - ./tests/e2e-chainsaw/v1beta2/pvc-name/ - - ./tests/e2e-chainsaw/v1beta2/keep-pvc/ - - ./tests/e2e-chainsaw/v1beta2/acl-user/ - - ./tests/e2e-chainsaw/v1beta2/scaling/ - - ./tests/e2e-chainsaw/v1beta2/ignore-annots/ - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Build Dockerfile - run: docker build . --file Dockerfile --tag redis-operator:e2e - - - name: Install chainsaw - uses: kyverno/chainsaw/.github/actions/install@v0.0.9 - with: - release: v0.1.7 - - - name: Check install - run: chainsaw version - - - name: Install kubectl - run: | - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x kubectl - sudo mv kubectl /usr/local/bin/ - - # - name: Install Redis - # uses: shogo82148/actions-setup-redis@v1 - - - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.10.0 - with: - config: tests/_config/kind-config.yaml - cluster_name: kind - - - name: Load Docker image into Kind - run: | - kubectl cluster-info --context kind-kind - kind load docker-image redis-operator:e2e --name kind - - - name: Install Redis Operator - run: | - make deploy IMG=redis-operator:e2e - - - name: Wait for Redis Operator to be ready - run: | - kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system - - - name: Run chainsaw test - run: chainsaw test --test-dir ${{ matrix.testpath }} --config tests/_config/chainsaw-configuration.yaml From 4e60683fc52fd2719517030b78156ccbcb6314d2 Mon Sep 17 00:00:00 2001 From: yangw Date: Mon, 6 May 2024 14:55:41 +0800 Subject: [PATCH 158/203] feat: probe use built-in, discarded healthcheck.sh (#907) * feat: probe use built-in, discarded healthcheck.sh Signed-off-by: drivebyer * use shell Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/statefulset.go | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 2bbb383df..918b4d044 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -345,6 +345,9 @@ func createPVCTemplate(volumeName string, stsMeta metav1.ObjectMeta, storageSpec // generateContainerDef generates container definition for Redis func generateContainerDef(name string, containerParams containerParameters, clusterMode, nodeConfVolume, enableMetrics bool, externalConfig, clusterVersion *string, mountpath []corev1.VolumeMount, sidecars []redisv1beta2.Sidecar) []corev1.Container { + sentinelCntr := containerParams.Role == "sentinel" + enableTLS := containerParams.TLSConfig != nil + enableAuth := containerParams.EnabledPassword != nil && *containerParams.EnabledPassword containerDefinition := []corev1.Container{ { Name: name, @@ -363,8 +366,8 @@ func generateContainerDef(name string, containerParams containerParameters, clus containerParams.Port, clusterVersion, ), - ReadinessProbe: getProbeInfo(containerParams.ReadinessProbe), - LivenessProbe: getProbeInfo(containerParams.LivenessProbe), + ReadinessProbe: getProbeInfo(containerParams.ReadinessProbe, sentinelCntr, enableTLS, enableAuth), + LivenessProbe: getProbeInfo(containerParams.LivenessProbe, sentinelCntr, enableTLS, enableAuth), VolumeMounts: getVolumeMount(name, containerParams.PersistenceEnabled, clusterMode, nodeConfVolume, externalConfig, mountpath, containerParams.TLSConfig, containerParams.ACLConfig), }, } @@ -593,7 +596,23 @@ func getVolumeMount(name string, persistenceEnabled *bool, clusterMode bool, nod } // getProbeInfo generate probe for Redis StatefulSet -func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { +func getProbeInfo(probe *commonapi.Probe, sentinel, enableTLS, enableAuth bool) *corev1.Probe { + healthChecker := []string{ + "redis-cli", + "-h", "$(hostname)", + } + if sentinel { + healthChecker = append(healthChecker, "-p", "${SENTINEL_PORT}") + } else { + healthChecker = append(healthChecker, "-p", "${REDIS_PORT}") + } + if enableAuth { + healthChecker = append(healthChecker, "-a", "${REDIS_PASSWORD}") + } + if enableTLS { + healthChecker = append(healthChecker, "--tls", "--cert", "${REDIS_TLS_CERT}", "--key", "${REDIS_TLS_CERT_KEY}", "--cacert", "${REDIS_TLS_CA_KEY}") + } + healthChecker = append(healthChecker, "ping") return &corev1.Probe{ InitialDelaySeconds: probe.InitialDelaySeconds, PeriodSeconds: probe.PeriodSeconds, @@ -602,10 +621,7 @@ func getProbeInfo(probe *commonapi.Probe) *corev1.Probe { SuccessThreshold: probe.SuccessThreshold, ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ - Command: []string{ - "bash", - "/usr/bin/healthcheck.sh", - }, + Command: []string{"sh", "-c", strings.Join(healthChecker, " ")}, }, }, } From 10c1e6bba8db0c80911790238840403d7f1949b1 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 7 May 2024 09:58:02 +0800 Subject: [PATCH 159/203] build: add workflow to publish image to ghcr (#914) * build: add ghcr release process Signed-off-by: drivebyer * fix: env Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/publish-image.yaml | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/publish-image.yaml diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml new file mode 100644 index 000000000..c7e1b44b5 --- /dev/null +++ b/.github/workflows/publish-image.yaml @@ -0,0 +1,46 @@ +name: Publish Image to GitHub Container Registry + +on: + push: + tags: + - 'v*' + +env: + REGISTRY: ghcr.io + REPOSITORY: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up docker buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Env + run: | + echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV + + - name: Build and Push Operator image + uses: docker/build-push-action@v3 + with: + context: . + file: Dockerfile + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:${{ env.TAG }} + ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest + platforms: linux/amd64,linux/arm64 \ No newline at end of file From c02d5a65e4e752eea8869b4c73e00acbaebd0022 Mon Sep 17 00:00:00 2001 From: teocns <59549574+teocns@users.noreply.github.com> Date: Mon, 6 May 2024 21:46:41 -0600 Subject: [PATCH 160/203] fix: runtime panic when `storage` param is empty (#887) * fix runtime panic when storage param is empty Signed-off-by: Teo * Update redis-cluster.go * remove blank * Update redis-cluster.go --------- Signed-off-by: Teo Co-authored-by: yangw --- k8sutils/redis-cluster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 8c182a20d..d16b9308c 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -38,7 +38,6 @@ func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, e Replicas: &replicas, ClusterMode: true, ClusterVersion: cr.Spec.ClusterVersion, - NodeConfVolume: cr.Spec.Storage.NodeConfVolume, NodeSelector: params.NodeSelector, PodSecurityContext: cr.Spec.PodSecurityContext, PriorityClassName: cr.Spec.PriorityClassName, @@ -58,6 +57,7 @@ func generateRedisClusterParams(cr *redisv1beta2.RedisCluster, replicas int32, e } if cr.Spec.Storage != nil { res.PersistentVolumeClaim = cr.Spec.Storage.VolumeClaimTemplate + res.NodeConfVolume = cr.Spec.Storage.NodeConfVolume res.NodeConfPersistentVolumeClaim = cr.Spec.Storage.NodeConfVolumeClaimTemplate } if externalConfig != nil { From c0b3c04c2d10fe0e2f16ac1540b634a79238eb77 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Tue, 7 May 2024 08:28:59 +0200 Subject: [PATCH 161/203] docs: update standalone pod name (#747) Update standalone pod name Signed-off-by: Mathieu Cesbron --- docs/content/en/docs/Getting Started/Standalone/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/en/docs/Getting Started/Standalone/_index.md b/docs/content/en/docs/Getting Started/Standalone/_index.md index ded6f12a9..76d71f9bb 100644 --- a/docs/content/en/docs/Getting Started/Standalone/_index.md +++ b/docs/content/en/docs/Getting Started/Standalone/_index.md @@ -39,7 +39,7 @@ Verify the standalone redis setup by kubectl command line. $ kubectl get pods -n ot-operators ... NAME READY STATUS RESTARTS AGE -redis-standalone-0 2/2 Running 0 56s +redis-0 1/1 Running 0 56s ``` ## YAML Installation From 37ac693c1608e94f96dca3c751ee827c8f925fba Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 7 May 2024 22:54:38 +0800 Subject: [PATCH 162/203] feat: WATCH_NAMESPACE support multi namespace (#919) * feat: WATCH_NAMESPACE support multi namespace Signed-off-by: drivebyer * format Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- main.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 1507e584e..a4c3ef59c 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ package main import ( "flag" "os" + "strings" redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" @@ -86,8 +87,13 @@ func main() { LeaderElectionID: "6cab913b.redis.opstreelabs.in", } - if ns := os.Getenv("WATCH_NAMESPACE"); ns != "" { - options.Cache.DefaultNamespaces = map[string]cache.Config{ns: {}} + if namespaces := strings.TrimSpace(os.Getenv("WATCH_NAMESPACE")); namespaces != "" { + options.Cache.DefaultNamespaces = map[string]cache.Config{} + for _, ns := range strings.Split(namespaces, ",") { + if ns = strings.TrimSpace(ns); ns != "" { + options.Cache.DefaultNamespaces[ns] = cache.Config{} + } + } } mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), options) From a9fa6997f9b4a1a90ce24dee368f3e071637c8c0 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 11 May 2024 13:28:18 +0800 Subject: [PATCH 163/203] fix: runtime panic when delete rediscluster which disable persistent (#922) Signed-off-by: drivebyer --- k8sutils/finalizer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/k8sutils/finalizer.go b/k8sutils/finalizer.go index 075725015..338224698 100644 --- a/k8sutils/finalizer.go +++ b/k8sutils/finalizer.go @@ -25,7 +25,7 @@ const ( func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.Redis) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisFinalizer) { - if !cr.Spec.Storage.KeepAfterDelete { + if cr.Spec.Storage != nil && !cr.Spec.Storage.KeepAfterDelete { if err := finalizeRedisPVC(k8sClient, logger, cr); err != nil { return err } @@ -44,7 +44,7 @@ func HandleRedisFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interfa func HandleRedisClusterFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisClusterFinalizer) { - if !cr.Spec.Storage.KeepAfterDelete { + if cr.Spec.Storage != nil && !cr.Spec.Storage.KeepAfterDelete { if err := finalizeRedisClusterPVC(k8sClient, logger, cr); err != nil { return err } @@ -63,7 +63,7 @@ func HandleRedisClusterFinalizer(ctrlclient client.Client, k8sClient kubernetes. func HandleRedisReplicationFinalizer(ctrlclient client.Client, k8sClient kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication) error { if cr.GetDeletionTimestamp() != nil { if controllerutil.ContainsFinalizer(cr, RedisReplicationFinalizer) { - if !cr.Spec.Storage.KeepAfterDelete { + if cr.Spec.Storage != nil && !cr.Spec.Storage.KeepAfterDelete { if err := finalizeRedisReplicationPVC(k8sClient, logger, cr); err != nil { return err } From 09a80f41a757e41af38ba7c483da7c91f69d83e6 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 14 May 2024 19:22:07 +0800 Subject: [PATCH 164/203] feat: add redis-role label to redis replication (#925) * feat: add redis-role label to redis replication Signed-off-by: drivebyer * fix lint Signed-off-by: drivebyer * fix lint Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- controllers/redisreplication_controller.go | 35 +++++++++- k8sutils/const.go | 6 ++ k8sutils/labels.go | 4 ++ k8sutils/pod.go | 69 +++++++++++++++++++ main.go | 4 +- .../v1beta2/ha-failover/chainsaw-test.yaml | 16 +++-- 6 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 k8sutils/pod.go diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 4f2c08000..9459785db 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -8,6 +8,7 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" @@ -19,6 +20,7 @@ import ( // RedisReplicationReconciler reconciles a RedisReplication object type RedisReplicationReconciler struct { client.Client + k8sutils.Pod K8sClient kubernetes.Interface Dk8sClient dynamic.Interface Log logr.Logger @@ -86,13 +88,15 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req if len(slaveNodes) == 0 { realMaster = masterNodes[0] } - err := k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, realMaster) - if err != nil { + if err = k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, realMaster); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } } realMaster = k8sutils.GetRedisReplicationRealMaster(ctx, r.K8sClient, r.Log, instance, masterNodes) - if err := r.UpdateRedisReplicationMaster(ctx, instance, realMaster); err != nil { + if err = r.UpdateRedisReplicationMaster(ctx, instance, realMaster); err != nil { + return ctrl.Result{}, err + } + if err = r.UpdateRedisPodRoleLabel(ctx, instance, realMaster); err != nil { return ctrl.Result{}, err } reqLogger.Info("Will reconcile redis operator in again 10 seconds") @@ -110,6 +114,31 @@ func (r *RedisReplicationReconciler) UpdateRedisReplicationMaster(ctx context.Co return nil } +func (r *RedisReplicationReconciler) UpdateRedisPodRoleLabel(ctx context.Context, cr *redisv1beta2.RedisReplication, masterNode string) error { + labels := k8sutils.GetRedisReplicationLabels(cr) + pods, err := r.ListPods(ctx, cr.GetNamespace(), labels) + if err != nil { + return err + } + updateRoleLabelFunc := func(ctx context.Context, namespace string, pod corev1.Pod, role string) error { + if pod.Labels[k8sutils.RedisRoleLabelKey] != role { + return r.PatchPodLabels(ctx, namespace, pod.GetName(), map[string]string{k8sutils.RedisRoleLabelKey: role}) + } + return nil + } + for _, pod := range pods.Items { + if masterNode == pod.GetName() { + err = updateRoleLabelFunc(ctx, cr.GetNamespace(), pod, k8sutils.RedisRoleLabelMaster) + } else { + err = updateRoleLabelFunc(ctx, cr.GetNamespace(), pod, k8sutils.RedisRoleLabelSlave) + } + if err != nil { + return err + } + } + return nil +} + // SetupWithManager sets up the controller with the Manager. func (r *RedisReplicationReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/k8sutils/const.go b/k8sutils/const.go index b0377c3be..6bbaaf969 100644 --- a/k8sutils/const.go +++ b/k8sutils/const.go @@ -7,3 +7,9 @@ const ( const ( EnvOperatorSTSPVCTemplateName = "OPERATOR_STS_PVC_TEMPLATE_NAME" ) + +const ( + RedisRoleLabelKey = "redis-role" + RedisRoleLabelMaster = "master" + RedisRoleLabelSlave = "slave" +) diff --git a/k8sutils/labels.go b/k8sutils/labels.go index da3960870..1cd0807b5 100644 --- a/k8sutils/labels.go +++ b/k8sutils/labels.go @@ -149,3 +149,7 @@ func getRedisLabels(name string, st setupType, role string, labels map[string]st } return lbls } + +func GetRedisReplicationLabels(cr *redisv1beta2.RedisReplication) map[string]string { + return getRedisLabels(cr.GetName(), replication, "replication", cr.GetLabels()) +} diff --git a/k8sutils/pod.go b/k8sutils/pod.go new file mode 100644 index 000000000..e52b131fc --- /dev/null +++ b/k8sutils/pod.go @@ -0,0 +1,69 @@ +package k8sutils + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + "github.com/go-logr/logr" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" +) + +type Pod interface { + ListPods(ctx context.Context, namespace string, labels map[string]string) (*corev1.PodList, error) + PatchPodLabels(ctx context.Context, namespace, name string, labels map[string]string) error +} + +type PodService struct { + kubeClient kubernetes.Interface + log logr.Logger +} + +func NewPodService(kubeClient kubernetes.Interface, log logr.Logger) *PodService { + log = log.WithValues("service", "k8s.pod") + return &PodService{ + kubeClient: kubeClient, + log: log, + } +} + +func (s *PodService) ListPods(ctx context.Context, namespace string, labels map[string]string) (*corev1.PodList, error) { + selector := make([]string, 0, len(labels)) + for key, value := range labels { + selector = append(selector, fmt.Sprintf("%s=%s", key, value)) + } + return s.kubeClient.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{ + LabelSelector: strings.Join(selector, ","), + }) +} + +type patchStringValue struct { + Op string `json:"op"` + Path string `json:"path"` + Value interface{} `json:"value"` +} + +func (s *PodService) PatchPodLabels(ctx context.Context, namespace, podName string, labels map[string]string) error { + s.log.Info("Patch pod labels", "namespace", namespace, "podName", podName, "labels", labels) + + var payloads []interface{} + for labelKey, labelValue := range labels { + payload := patchStringValue{ + Op: "replace", + Path: "/metadata/labels/" + labelKey, + Value: labelValue, + } + payloads = append(payloads, payload) + } + payloadBytes, _ := json.Marshal(payloads) + + _, err := s.kubeClient.CoreV1().Pods(namespace).Patch(ctx, podName, types.JSONPatchType, payloadBytes, metav1.PatchOptions{}) + if err != nil { + s.log.Error(err, "Patch pod labels failed", "namespace", namespace, "podName", podName) + } + return err +} diff --git a/main.go b/main.go index a4c3ef59c..a45dfd53a 100644 --- a/main.go +++ b/main.go @@ -134,12 +134,14 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "RedisCluster") os.Exit(1) } + rrLog := ctrl.Log.WithName("controllers").WithName("RedisReplication") if err = (&controllers.RedisReplicationReconciler{ Client: mgr.GetClient(), K8sClient: k8sclient, Dk8sClient: dk8sClient, - Log: ctrl.Log.WithName("controllers").WithName("RedisReplication"), + Log: rrLog, Scheme: mgr.GetScheme(), + Pod: k8sutils.NewPodService(k8sclient, rrLog), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "RedisReplication") os.Exit(1) diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml index 81716a6ee..43b3f04ee 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml @@ -19,18 +19,22 @@ spec: selector: control-plane=redis-operator container: manager tail: -1 # tail all logs + - name: Sleep for 3 minutes try: - sleep: duration: 3m + - name: Test sentinel monitoring try: - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 sentinel master myMaster | grep -A 1 'flags' | tail -n 1 + export MASTER_IP_FROM_SENTINEL=$(kubectl exec --namespace ${NAMESPACE} redis-sentinel-sentinel-0 -- redis-cli -p 26379 sentinel get-master-addr-by-name myMaster | head -n 1); + export MASTER_IP_FROM_LABEL=$(kubectl -n ${NAMESPACE} get pod -l app=redis-replication,redis-role=master,redis_setup_type=replication -o jsonpath='{.items[0].status.podIP}'); + if [ "$MASTER_IP_FROM_SENTINEL" = "$MASTER_IP_FROM_LABEL" ]; then echo "OK"; else echo "FAIL"; fi check: - ($stdout=='master'): true + ($stdout=='OK'): true catch: - description: Redis Operator Logs podLogs: @@ -53,18 +57,22 @@ spec: selector: control-plane=redis-operator container: manager tail: -1 # tail all logs + - name: Sleep for 3 minutes try: - sleep: duration: 3m + - name: Test sentinel monitoring try: - script: timeout: 10s content: | - kubectl exec --namespace ${NAMESPACE} redis -- redis-cli -h redis-sentinel-sentinel.${NAMESPACE}.svc -p 26379 sentinel master myMaster | grep -A 1 'flags' | tail -n 1 + export MASTER_IP_FROM_SENTINEL=$(kubectl exec --namespace ${NAMESPACE} redis-sentinel-sentinel-0 -- redis-cli -p 26379 sentinel get-master-addr-by-name myMaster | head -n 1); + export MASTER_IP_FROM_LABEL=$(kubectl -n ${NAMESPACE} get pod -l app=redis-replication,redis-role=master,redis_setup_type=replication -o jsonpath='{.items[0].status.podIP}'); + if [ $MASTER_IP_FROM_SENTINEL = $MASTER_IP_FROM_LABEL ]; then echo "OK"; else echo "FAIL"; fi check: - ($stdout=='master'): true + ($stdout=='OK'): true catch: - description: Redis Operator Logs podLogs: From fae7db7845f1958c7c8751a90b678af67b1d541e Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 14 May 2024 23:04:10 +0800 Subject: [PATCH 165/203] build: repository name must be lowercase (#926) Signed-off-by: drivebyer --- .github/workflows/publish-image.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml index c7e1b44b5..58f3600cd 100644 --- a/.github/workflows/publish-image.yaml +++ b/.github/workflows/publish-image.yaml @@ -7,7 +7,7 @@ on: env: REGISTRY: ghcr.io - REPOSITORY: ${{ github.repository }} + REPOSITORY: ot-container-kit/redis-operator jobs: build-and-push: From bd1e4faf063f335f0286a9795f3371a786bdf557 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 21 May 2024 20:05:20 +0800 Subject: [PATCH 166/203] fix: check redis replication after handling finalizer (#936) Signed-off-by: drivebyer --- controllers/redissentinel_controller.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index a3c4fe53c..f817abccb 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -45,11 +45,6 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{RequeueAfter: time.Second * 10}, nil } - if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, reqLogger, r.K8sClient, r.Dk8sClient, instance) { - reqLogger.Info("Redis Replication is specified but not ready, so will reconcile again in 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil - } - // Get total Sentinel Replicas // sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel") @@ -61,6 +56,11 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{RequeueAfter: time.Second * 60}, err } + if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, reqLogger, r.K8sClient, r.Dk8sClient, instance) { + reqLogger.Info("Redis Replication is specified but not ready, so will reconcile again in 10 seconds") + return ctrl.Result{RequeueAfter: time.Second * 10}, nil + } + // Create Redis Sentinel err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance, r.K8sClient, r.Dk8sClient) if err != nil { From 14fce7cd7c6b0147aa30e2dc9dbc92afd1ecc17d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 21:07:18 +0800 Subject: [PATCH 167/203] chore(deps): bump github.com/onsi/ginkgo/v2 from 2.17.2 to 2.17.3 (#920) Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.17.2 to 2.17.3. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.17.2...v2.17.3) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 825e76df6..f83d20a98 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/banzaicloud/k8s-objectmatcher v1.8.0 github.com/go-logr/logr v1.4.1 github.com/go-redis/redismock/v9 v9.2.0 - github.com/onsi/ginkgo/v2 v2.17.2 + github.com/onsi/ginkgo/v2 v2.17.3 github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 github.com/redis/go-redis/v9 v9.5.1 diff --git a/go.sum b/go.sum index 0b865d29b..87f29eb56 100644 --- a/go.sum +++ b/go.sum @@ -151,8 +151,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.17.3 h1:oJcvKpIb7/8uLpDDtnQuf18xVnwKp8DTD7DQ6gTd/MU= +github.com/onsi/ginkgo/v2 v2.17.3/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= From deb9cd667c7c4d6de252484b0fb66ce8c69a56a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 21:07:37 +0800 Subject: [PATCH 168/203] chore(deps): bump golangci/golangci-lint-action from 5 to 6 (#916) Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 5 to 6. - [Release notes](https://github.com/golangci/golangci-lint-action/releases) - [Commits](https://github.com/golangci/golangci-lint-action/compare/v5...v6) --- updated-dependencies: - dependency-name: golangci/golangci-lint-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7d08cc38d..b65692fee 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -52,7 +52,7 @@ jobs: cache: false - name: Run GolangCI-Lint - uses: golangci/golangci-lint-action@v5 + uses: golangci/golangci-lint-action@v6 with: version: v1.54.0 From 68d053b51f19eb4bddb8ec8e78bbdad37002b6f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 21:07:51 +0800 Subject: [PATCH 169/203] chore(deps): bump docker/setup-buildx-action from 2 to 3 (#917) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-image.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml index 58f3600cd..71910741f 100644 --- a/.github/workflows/publish-image.yaml +++ b/.github/workflows/publish-image.yaml @@ -21,7 +21,7 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Set up docker buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v1 From 39ed5d0a7c047729281fa80335fe49b7a67fe96d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 21:08:06 +0800 Subject: [PATCH 170/203] chore(deps): bump docker/setup-qemu-action from 2 to 3 (#915) Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 2 to 3. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](https://github.com/docker/setup-qemu-action/compare/v2...v3) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-image.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml index 71910741f..b13b2e43f 100644 --- a/.github/workflows/publish-image.yaml +++ b/.github/workflows/publish-image.yaml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v2 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up docker buildx uses: docker/setup-buildx-action@v3 From d15c80e5466086249f5caaadbb3329cc6af95b1d Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 22 May 2024 09:48:51 +0800 Subject: [PATCH 171/203] fix: return ASAP after handling finalizer (#940) Signed-off-by: drivebyer --- controllers/redis_controller.go | 10 ++++++---- controllers/rediscluster_controller.go | 13 +++++++------ controllers/redisreplication_controller.go | 11 ++++++----- controllers/redissentinel_controller.go | 10 ++++++---- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index 991c18d48..2ac11f27e 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -52,14 +52,16 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl } return ctrl.Result{}, err } + if instance.ObjectMeta.GetDeletionTimestamp() != nil { + if err = k8sutils.HandleRedisFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } if _, found := instance.ObjectMeta.GetAnnotations()["redis.opstreelabs.in/skip-reconcile"]; found { reqLogger.Info("Found annotations redis.opstreelabs.in/skip-reconcile, so skipping reconcile") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } - if err = k8sutils.HandleRedisFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{}, err - } - if err = k8sutils.AddFinalizer(instance, k8sutils.RedisFinalizer, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index d3f6e0df6..fc280c916 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -54,21 +54,22 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } return ctrl.Result{}, err } - instance.SetDefault() - + if instance.ObjectMeta.GetDeletionTimestamp() != nil { + if err = k8sutils.HandleRedisClusterFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } if _, found := instance.ObjectMeta.GetAnnotations()["rediscluster.opstreelabs.in/skip-reconcile"]; found { reqLogger.Info("Found annotations rediscluster.opstreelabs.in/skip-reconcile, so skipping reconcile") return ctrl.Result{RequeueAfter: time.Second * 10}, nil } + instance.SetDefault() leaderReplicas := instance.Spec.GetReplicaCounts("leader") followerReplicas := instance.Spec.GetReplicaCounts("follower") totalReplicas := leaderReplicas + followerReplicas - if err = k8sutils.HandleRedisClusterFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{}, err - } - if err = k8sutils.AddFinalizer(instance, k8sutils.RedisClusterFinalizer, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 9459785db..0473d412a 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -39,7 +39,12 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req } return ctrl.Result{}, err } - + if instance.ObjectMeta.GetDeletionTimestamp() != nil { + if err = k8sutils.HandleRedisReplicationFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } if _, found := instance.ObjectMeta.GetAnnotations()["redisreplication.opstreelabs.in/skip-reconcile"]; found { reqLogger.Info("Found annotations redisreplication.opstreelabs.in/skip-reconcile, so skipping reconcile") return ctrl.Result{RequeueAfter: time.Second * 10}, nil @@ -49,10 +54,6 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req followerReplicas := instance.Spec.GetReplicationCounts("replication") - leaderReplicas totalReplicas := leaderReplicas + followerReplicas - if err = k8sutils.HandleRedisReplicationFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{}, err - } - if err = k8sutils.AddFinalizer(instance, k8sutils.RedisReplicationFinalizer, r.Client); err != nil { return ctrl.Result{}, err } diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index f817abccb..d660e1c12 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -39,6 +39,12 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques } return ctrl.Result{}, err } + if instance.ObjectMeta.GetDeletionTimestamp() != nil { + if err = k8sutils.HandleRedisSentinelFinalizer(r.Client, r.Log, instance); err != nil { + return ctrl.Result{RequeueAfter: time.Second * 60}, err + } + return ctrl.Result{}, nil + } if _, found := instance.ObjectMeta.GetAnnotations()["redissentinel.opstreelabs.in/skip-reconcile"]; found { reqLogger.Info("Found annotations redissentinel.opstreelabs.in/skip-reconcile, so skipping reconcile") @@ -48,10 +54,6 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques // Get total Sentinel Replicas // sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel") - if err = k8sutils.HandleRedisSentinelFinalizer(r.Client, r.Log, instance); err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err - } - if err = k8sutils.AddFinalizer(instance, k8sutils.RedisSentinelFinalizer, r.Client); err != nil { return ctrl.Result{RequeueAfter: time.Second * 60}, err } From e021986de8bf46fa3fb2743e51454a20db1ceeac Mon Sep 17 00:00:00 2001 From: Thomas Montague Date: Wed, 22 May 2024 21:25:51 -0500 Subject: [PATCH 172/203] build: add support for other container engines (#947) Add support for other container engines. Signed-off-by: Thomas Montague --- Makefile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 110a2626c..5bb014d7a 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,8 @@ else GOBIN=$(shell go env GOBIN) endif +CONTAINER_ENGINE ?= docker + all: manager # Run tests @@ -74,15 +76,15 @@ generate: controller-gen $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." docker-create: - docker buildx create --platform "linux/amd64,linux/arm64" --use + ${CONTAINER_ENGINE} buildx create --platform "linux/amd64,linux/arm64" --use # Build the docker image docker-build: - docker buildx build --platform="linux/arm64,linux/amd64" -t ${IMG} . + ${CONTAINER_ENGINE} buildx build --platform="linux/arm64,linux/amd64" -t ${IMG} . # Push the docker image docker-push: - docker buildx build --push --platform="linux/arm64,linux/amd64" -t ${IMG} . + ${CONTAINER_ENGINE} buildx build --push --platform="linux/arm64,linux/amd64" -t ${IMG} . # Download controller-gen locally if necessary CONTROLLER_GEN = $(shell pwd)/bin/controller-gen @@ -119,7 +121,7 @@ bundle: manifests kustomize # Build the bundle image. .PHONY: bundle-build bundle-build: - docker buildx build --platform="linux/arm64,linux/amd64" -f bundle.Dockerfile -t $(BUNDLE_IMG) . + ${CONTAINER_ENGINE} buildx build --platform="linux/arm64,linux/amd64" -f bundle.Dockerfile -t $(BUNDLE_IMG) . # Generate bundle manifests and metadata, then validate generated files. .PHONY: codegen @@ -164,7 +166,7 @@ install-kuttl: .PHONY: e2e-kind-setup e2e-kind-setup: - docker build -t redis-operator:e2e -f Dockerfile . + ${CONTAINER_ENGINE} build -t redis-operator:e2e -f Dockerfile . kind create cluster --config tests/_config/kind-config.yaml kind load docker-image redis-operator:e2e --name kind - make deploy IMG=redis-operator:e2e \ No newline at end of file + make deploy IMG=redis-operator:e2e From 8ba73904429cd186edb07988129534f54c62294d Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 28 May 2024 02:13:24 +0800 Subject: [PATCH 173/203] feat: add redis operator helm chart and release workflow (#941) * copy operator chart from helm-charts repo Signed-off-by: drivebyer * add chart release workflow Signed-off-by: drivebyer * change operator image Signed-off-by: drivebyer --------- Signed-off-by: drivebyer Signed-off-by: drivebyer --- .github/workflows/publish-charts.yaml | 97 + .github/workflows/publish-image.yaml | 1 - charts/redis-operator/.gitignore | 1 + charts/redis-operator/Chart.lock | 6 + charts/redis-operator/Chart.yaml | 28 + charts/redis-operator/crds/redis-cluster.yaml | 11168 ++++++++++++++++ .../crds/redis-replication.yaml | 8271 ++++++++++++ .../redis-operator/crds/redis-sentinel.yaml | 3889 ++++++ charts/redis-operator/crds/redis.yaml | 8265 ++++++++++++ charts/redis-operator/readme.md | 112 + charts/redis-operator/templates/_helpers.tpl | 34 + .../templates/cert-manager.yaml | 43 + .../templates/operator-deployment.yaml | 76 + .../templates/role-binding.yaml | 21 + charts/redis-operator/templates/role.yaml | 126 + .../templates/service-account.yaml | 14 + charts/redis-operator/templates/service.yaml | 20 + charts/redis-operator/values.yaml | 60 + 18 files changed, 32231 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish-charts.yaml create mode 100644 charts/redis-operator/.gitignore create mode 100644 charts/redis-operator/Chart.lock create mode 100644 charts/redis-operator/Chart.yaml create mode 100644 charts/redis-operator/crds/redis-cluster.yaml create mode 100644 charts/redis-operator/crds/redis-replication.yaml create mode 100644 charts/redis-operator/crds/redis-sentinel.yaml create mode 100644 charts/redis-operator/crds/redis.yaml create mode 100644 charts/redis-operator/readme.md create mode 100644 charts/redis-operator/templates/_helpers.tpl create mode 100644 charts/redis-operator/templates/cert-manager.yaml create mode 100644 charts/redis-operator/templates/operator-deployment.yaml create mode 100644 charts/redis-operator/templates/role-binding.yaml create mode 100644 charts/redis-operator/templates/role.yaml create mode 100644 charts/redis-operator/templates/service-account.yaml create mode 100644 charts/redis-operator/templates/service.yaml create mode 100644 charts/redis-operator/values.yaml diff --git a/.github/workflows/publish-charts.yaml b/.github/workflows/publish-charts.yaml new file mode 100644 index 000000000..9a77c29f8 --- /dev/null +++ b/.github/workflows/publish-charts.yaml @@ -0,0 +1,97 @@ +name: Release Charts + +on: + push: + tags: + - "v*.*.*" + +jobs: + release-charts: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + repository: "${{ github.repository_owner }}/redis-operator" + path: "redis-operator" + fetch-depth: 0 + + - name: Checkout helm-charts + uses: actions/checkout@v3 + with: + repository: "${{ github.repository_owner }}/helm-charts" + # use token for helm-charts repo + token: "${{ secrets.HELM_CHARTER_TOKEN }}" + path: "helm-charts" + fetch-depth: 0 + + - name: Get chart version + run: | + echo "chart_version=$(echo ${GITHUB_REF##*/v})" >> $GITHUB_ENV + + - name: Install Helm + uses: azure/setup-helm@v4.2.0 + + - name: Make charts + shell: bash + working-directory: redis-operator + run: | + VERSION=$(echo ${{ env.chart_version }} | cut -c 2-) + sed -i "s/appVersion:.*/appVersion: \"$VERSION\"/g" charts/redis-operator/Chart.yaml + helm repo add jetstack https://charts.jetstack.io + helm repo update + helm dependency update charts/redis-operator + helm package charts/redis-operator -d .cr-release-packages + + - name: Install chart-releaser + uses: helm/chart-releaser-action@v1.5.0 + with: + install_only: true + + # upload charts to helm-charts repos's release + - name: Upload charts + shell: bash + working-directory: redis-operator + run: | + cr upload + env: + # GitHub repository + CR_GIT_REPO: "helm-charts" + # Path to directory with chart packages (default ".cr-release-packages") + CR_PACKAGE_PATH: ".cr-release-packages" + # use token for helm-charts repo + CR_TOKEN: "${{ secrets.HELM_CHARTER_TOKEN }}" + # owner + CR_OWNER: "${{ github.repository_owner }}" + # skip existing charts + CR_SKIP_EXISTING: "true" + + # copy artifacts to helm-charts repo, we need those for update index + - name: Copy artifacts + run: | + cp -r redis-operator/.cr-release-packages helm-charts/ + + - name: Configure Git + working-directory: helm-charts + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + # this step will directly push to the main branch, so make sure you have the right permissions + - name: Update index + working-directory: helm-charts + run: | + cr index --push + env: + # GitHub repository + CR_GIT_REPO: "helm-charts" + # The GitHub pages branch (default "gh-pages") + CR_PAGES_BRANCH: "gh-pages" + # Path to directory with chart packages (default ".cr-release-packages") + CR_PACKAGE_PATH: ".cr-release-packages" + # use token for helm-charts repo + CR_TOKEN: "${{ secrets.HELM_CHARTER_TOKEN }}" + # owner + CR_OWNER: "${{ github.repository_owner }}" + # index path + CR_INDEX_PATH: "index.yaml" \ No newline at end of file diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml index b13b2e43f..03f269996 100644 --- a/.github/workflows/publish-image.yaml +++ b/.github/workflows/publish-image.yaml @@ -12,7 +12,6 @@ env: jobs: build-and-push: runs-on: ubuntu-latest - steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/charts/redis-operator/.gitignore b/charts/redis-operator/.gitignore new file mode 100644 index 000000000..aa1ec1ea0 --- /dev/null +++ b/charts/redis-operator/.gitignore @@ -0,0 +1 @@ +*.tgz diff --git a/charts/redis-operator/Chart.lock b/charts/redis-operator/Chart.lock new file mode 100644 index 000000000..8da343e30 --- /dev/null +++ b/charts/redis-operator/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: cert-manager + repository: https://charts.jetstack.io + version: v1.12.4 +digest: sha256:026d03c56e2f8369b0f7d79f9560d5a33b2c5ae8a7d751213e56e2a0176cb874 +generated: "2023-10-02T14:14:45.164829041+05:30" diff --git a/charts/redis-operator/Chart.yaml b/charts/redis-operator/Chart.yaml new file mode 100644 index 000000000..0dda19878 --- /dev/null +++ b/charts/redis-operator/Chart.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: v2 +version: 0.15.9 +appVersion: "0.15.1" +description: Provides easy redis setup definitions for Kubernetes services, and deployment. +engine: gotpl +maintainers: + - name: iamabhishek-dubey + - name: sandy724 + - name: shubham-cmyk +name: redis-operator +sources: + - https://github.com/OT-CONTAINER-KIT/redis-operator +home: https://github.com/OT-CONTAINER-KIT/redis-operator +icon: https://github.com/OT-CONTAINER-KIT/redis-operator/raw/master/static/redis-operator-logo.svg +keywords: +- operator +- redis +- opstree +- kubernetes +- openshift + +dependencies: + - name: cert-manager + version: v1.12.4 + repository: https://charts.jetstack.io + alias: certmanager + condition: certmanager.enabled \ No newline at end of file diff --git a/charts/redis-operator/crds/redis-cluster.yaml b/charts/redis-operator/crds/redis-cluster.yaml new file mode 100644 index 000000000..bc6203d92 --- /dev/null +++ b/charts/redis-operator/crds/redis-cluster.yaml @@ -0,0 +1,11168 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} + creationTimestamp: null + name: redisclusters.redis.redis.opstreelabs.in +spec: + group: redis.redis.opstreelabs.in + names: + kind: RedisCluster + listKind: RedisClusterList + plural: redisclusters + singular: rediscluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Current cluster node count + jsonPath: .spec.clusterSize + name: ClusterSize + type: integer + - description: Overridden Leader replica count + jsonPath: .spec.redisLeader.CommonAttributes.Replicas + name: LeaderReplicas + type: integer + - description: Overridden Follower replica count + jsonPath: .spec.redisFollower.CommonAttributes.Replicas + name: FollowerReplicas + type: integer + - description: Age of Cluster + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: RedisCluster is the Schema for the redisclusters API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RedisClusterSpec defines the desired state of RedisCluster + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + clusterSize: + format: int32 + type: integer + clusterVersion: + default: v7 + type: string + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + persistenceEnabled: + type: boolean + priorityClassName: + type: string + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + redisFollower: + default: + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: RedisFollower interface will have the redis follower + configuration + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + pdb: + description: RedisPodDisruptionBudget configure a PodDisruptionBudget + on the resource (leader/follower) + properties: + enabled: + type: boolean + maxUnavailable: + format: int32 + type: integer + minAvailable: + format: int32 + type: integer + type: object + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of + Redis + properties: + additionalRedisConfig: + type: string + type: object + replicas: + format: int32 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + redisLeader: + default: + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: RedisLeader interface will have the redis leader configuration + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + pdb: + description: RedisPodDisruptionBudget configure a PodDisruptionBudget + on the resource (leader/follower) + properties: + enabled: + type: boolean + maxUnavailable: + format: int32 + type: integer + minAvailable: + format: int32 + type: integer + type: object + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of + Redis + properties: + additionalRedisConfig: + type: string + type: object + replicas: + format: int32 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be set + for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + name: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + storage: + description: Storage is the inteface to add pvc and pv support in + redis + properties: + volumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage + driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between + this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) are currently + supported.' + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + required: + - clusterSize + - kubernetesConfig + type: object + status: + description: RedisClusterStatus defines the observed state of RedisCluster + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Current cluster node count + jsonPath: .spec.clusterSize + name: ClusterSize + type: integer + - description: Number of ready leader replicas + jsonPath: .status.readyLeaderReplicas + name: ReadyLeaderReplicas + type: integer + - description: Number of ready follower replicas + jsonPath: .status.readyFollowerReplicas + name: ReadyFollowerReplicas + type: integer + - description: The current state of the Redis Cluster + jsonPath: .status.state + name: State + priority: 1 + type: string + - description: Age of Cluster + jsonPath: .metadata.creationTimestamp + name: Age + priority: 1 + type: date + - description: The reason for the current state + jsonPath: .status.reason + name: Reason + priority: 1 + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: RedisCluster is the Schema for the redisclusters API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RedisClusterSpec defines the desired state of RedisCluster + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + acl: + properties: + secret: + description: "Adapts a Secret into a volume. \n The contents of + the target Secret's Data field will be presented in a volume + as files using the keys in the Data field as the file names. + Secret volumes support ownership management and SELinux relabeling." + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + type: object + clusterSize: + format: int32 + type: integer + clusterVersion: + default: v7 + type: string + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + initContainer: + description: InitContainer for each Redis pods + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + persistenceEnabled: + type: boolean + podSecurityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + priorityClassName: + type: string + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + redisFollower: + default: + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: RedisFollower interface will have the redis follower + configuration + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + pdb: + description: RedisPodDisruptionBudget configure a PodDisruptionBudget + on the resource (leader/follower) + properties: + enabled: + type: boolean + maxUnavailable: + format: int32 + type: integer + minAvailable: + format: int32 + type: integer + type: object + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of + Redis + properties: + additionalRedisConfig: + type: string + type: object + replicas: + format: int32 + type: integer + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + redisLeader: + default: + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: RedisLeader interface will have the redis leader configuration + properties: + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + pdb: + description: RedisPodDisruptionBudget configure a PodDisruptionBudget + on the resource (leader/follower) + properties: + enabled: + type: boolean + maxUnavailable: + format: int32 + type: integer + minAvailable: + format: int32 + type: integer + type: object + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of + Redis + properties: + additionalRedisConfig: + type: string + type: object + replicas: + format: int32 + type: integer + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: "Claims lists the names of resources, defined in + spec.resourceClaims, that are used by this container. \n This + is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be set + for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims + of the Pod where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + command: + items: + type: string + type: array + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + name: + type: string + ports: + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: Number of port to expose on the pod's IP + address. This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: Number of port to expose on the host. If + specified, this must be a valid port number, 0 < x < + 65536. If HostNetwork is specified, this must match + ContainerPort. Most containers do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a pod + must have a unique name. Name for the port that can + be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + storage: + description: Node-conf needs to be added only in redis cluster + properties: + nodeConfVolume: + default: false + type: boolean + nodeConfVolumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage + driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between + this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) are currently + supported.' + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + required: + - clusterSize + - kubernetesConfig + type: object + status: + description: RedisClusterStatus defines the observed state of RedisCluster + properties: + readyFollowerReplicas: + default: 0 + format: int32 + type: integer + readyLeaderReplicas: + default: 0 + format: int32 + type: integer + reason: + type: string + state: + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1beta1","v1beta2"] + clientConfig: + service: + namespace: redis-operator + name: webhook-service + path: /convert +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/redis-operator/crds/redis-replication.yaml b/charts/redis-operator/crds/redis-replication.yaml new file mode 100644 index 000000000..1e9fdbf8d --- /dev/null +++ b/charts/redis-operator/crds/redis-replication.yaml @@ -0,0 +1,8271 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} + creationTimestamp: null + name: redisreplications.redis.redis.opstreelabs.in +spec: + group: redis.redis.opstreelabs.in + names: + kind: RedisReplication + listKind: RedisReplicationList + plural: redisreplications + singular: redisreplication + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: Redis is the Schema for the redis API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + clusterSize: + format: int32 + type: integer + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of Redis + properties: + additionalRedisConfig: + type: string + type: object + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + name: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + storage: + description: Storage is the inteface to add pvc and pv support in + redis + properties: + volumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage + driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between + this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) are currently + supported.' + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + tolerations: + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - clusterSize + - kubernetesConfig + type: object + status: + description: RedisStatus defines the observed state of Redis + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - name: v1beta2 + schema: + openAPIV3Schema: + description: Redis is the Schema for the redis API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + acl: + properties: + secret: + description: "Adapts a Secret into a volume. \n The contents of + the target Secret's Data field will be presented in a volume + as files using the keys in the Data field as the file names. + Secret volumes support ownership management and SELinux relabeling." + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + type: object + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + clusterSize: + format: int32 + type: integer + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + initContainer: + description: InitContainer for each Redis pods + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podSecurityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of Redis + properties: + additionalRedisConfig: + type: string + type: object + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + securityContext: + description: SecurityContext holds security configuration that will + be applied to a container. Some fields are present in both SecurityContext + and PodSecurityContext. When both are set, the values in SecurityContext + take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a process + can gain more privileges than its parent process. This bool + directly controls if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation is true always when + the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. Note that this field cannot be set when spec.os.name + is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in privileged + containers are essentially equivalent to root on the host. Defaults + to false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use for + the containers. The default is DefaultProcMount which uses the + container runtime defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. If + seccomp options are provided at both the pod & container level, + the container options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will + be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + command: + items: + type: string + type: array + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + name: + type: string + ports: + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: Number of port to expose on the pod's IP + address. This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: Number of port to expose on the host. If + specified, this must be a valid port number, 0 < x < + 65536. If HostNetwork is specified, this must match + ContainerPort. Most containers do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a pod + must have a unique name. Name for the port that can + be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + storage: + description: Storage is the inteface to add pvc and pv support in + redis + properties: + volumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage + driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between + this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) are currently + supported.' + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - clusterSize + - kubernetesConfig + type: object + status: + description: RedisStatus defines the observed state of Redis + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1beta1","v1beta2"] + clientConfig: + service: + namespace: redis-operator + name: webhook-service + path: /convert +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/redis-operator/crds/redis-sentinel.yaml b/charts/redis-operator/crds/redis-sentinel.yaml new file mode 100644 index 000000000..3fea9d33b --- /dev/null +++ b/charts/redis-operator/crds/redis-sentinel.yaml @@ -0,0 +1,3889 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} + creationTimestamp: null + name: redissentinels.redis.redis.opstreelabs.in +spec: + group: redis.redis.opstreelabs.in + names: + kind: RedisSentinel + listKind: RedisSentinelList + plural: redissentinels + singular: redissentinel + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: Redis is the Schema for the redis API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + clusterSize: + format: int32 + minimum: 1 + type: integer + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + pdb: + description: RedisPodDisruptionBudget configure a PodDisruptionBudget + on the resource (leader/follower) + properties: + enabled: + type: boolean + maxUnavailable: + format: int32 + type: integer + minAvailable: + format: int32 + type: integer + type: object + priorityClassName: + type: string + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisSentinelConfig: + properties: + additionalSentinelConfig: + type: string + downAfterMilliseconds: + default: "30000" + type: string + failoverTimeout: + default: "180000" + type: string + masterGroupName: + default: myMaster + type: string + parallelSyncs: + default: "1" + type: string + quorum: + default: "2" + type: string + redisPort: + default: "6379" + type: string + redisReplicationName: + type: string + required: + - redisReplicationName + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + name: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + tolerations: + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - clusterSize + - kubernetesConfig + type: object + status: + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - name: v1beta2 + schema: + openAPIV3Schema: + description: Redis is the Schema for the redis API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + clusterSize: + default: 3 + format: int32 + minimum: 1 + type: integer + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + initContainer: + description: InitContainer for each Redis pods + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + pdb: + description: RedisPodDisruptionBudget configure a PodDisruptionBudget + on the resource (leader/follower) + properties: + enabled: + type: boolean + maxUnavailable: + format: int32 + type: integer + minAvailable: + format: int32 + type: integer + type: object + podSecurityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + redisSentinelConfig: + properties: + additionalSentinelConfig: + type: string + downAfterMilliseconds: + default: "30000" + type: string + failoverTimeout: + default: "180000" + type: string + masterGroupName: + default: myMaster + type: string + parallelSyncs: + default: "1" + type: string + quorum: + default: "2" + type: string + redisPort: + default: "6379" + type: string + redisReplicationName: + type: string + required: + - redisReplicationName + type: object + securityContext: + description: SecurityContext holds security configuration that will + be applied to a container. Some fields are present in both SecurityContext + and PodSecurityContext. When both are set, the values in SecurityContext + take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a process + can gain more privileges than its parent process. This bool + directly controls if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation is true always when + the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. Note that this field cannot be set when spec.os.name + is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in privileged + containers are essentially equivalent to root on the host. Defaults + to false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use for + the containers. The default is DefaultProcMount which uses the + container runtime defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. If + seccomp options are provided at both the pod & container level, + the container options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will + be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + command: + items: + type: string + type: array + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + name: + type: string + ports: + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: Number of port to expose on the pod's IP + address. This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: Number of port to expose on the host. If + specified, this must be a valid port number, 0 < x < + 65536. If HostNetwork is specified, this must match + ContainerPort. Most containers do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a pod + must have a unique name. Name for the port that can + be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - clusterSize + - kubernetesConfig + type: object + status: + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1beta1","v1beta2"] + clientConfig: + service: + namespace: redis-operator + name: webhook-service + path: /convert +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/redis-operator/crds/redis.yaml b/charts/redis-operator/crds/redis.yaml new file mode 100644 index 000000000..cd7bac22d --- /dev/null +++ b/charts/redis-operator/crds/redis.yaml @@ -0,0 +1,8265 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} + creationTimestamp: null + name: redis.redis.redis.opstreelabs.in +spec: + group: redis.redis.opstreelabs.in + names: + kind: Redis + listKind: RedisList + plural: redis + singular: redis + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: Redis is the Schema for the redis API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RedisSpec defines the desired state of Redis + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + priorityClassName: + type: string + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of Redis + properties: + additionalRedisConfig: + type: string + type: object + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + securityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + name: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + storage: + description: Storage is the inteface to add pvc and pv support in + redis + properties: + volumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage + driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between + this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) are currently + supported.' + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + tolerations: + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - kubernetesConfig + type: object + status: + description: RedisStatus defines the observed state of Redis + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - name: v1beta2 + schema: + openAPIV3Schema: + description: Redis is the Schema for the redis API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RedisSpec defines the desired state of Redis + properties: + TLS: + description: TLS Configuration for redis instances + properties: + ca: + type: string + cert: + type: string + key: + type: string + secret: + description: Reference to secret which contains the certificates + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + required: + - secret + type: object + acl: + properties: + secret: + description: "Adapts a Secret into a volume. \n The contents of + the target Secret's Data field will be presented in a volume + as files using the keys in the Data field as the file names. + Secret volumes support ownership management and SELinux relabeling." + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used to set + permissions on created files by default. Must be an octal + value between 0000 and 0777 or a decimal value between 0 + and 511. YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. Defaults to 0644. + Directories within the path are not affected by this setting. + This might be in conflict with other options that affect + the file mode, like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and content + is the value. If specified, the listed keys will be projected + into the specified paths, and unlisted keys will not be + present. If a key is specified which is not present in the + Secret, the volume setup will error unless it is marked + optional. Paths must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used to set + permissions on this file. Must be an octal value between + 0000 and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON requires + decimal values for mode bits. If not specified, the + volume defaultMode will be used. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: path is the relative path of the file to + map the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret or + its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in the + pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + type: object + affinity: + description: Affinity is a group of affinity scheduling rules. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + env: + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded using + the previously defined environment variables in the container + and any service environment variables. If a variable cannot + be resolved, the reference in the input string will be unchanged. + Double $$ are reduced to a single $, which allows for escaping + the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the + string literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + initContainer: + description: InitContainer for each Redis pods + properties: + args: + items: + type: string + type: array + command: + items: + type: string + type: array + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + service: + description: ServiceConfig define the type of service to be created + and its annotations + properties: + annotations: + additionalProperties: + type: string + type: object + serviceType: + enum: + - LoadBalancer + - NodePort + - ClusterIP + type: string + type: object + updateStrategy: + description: StatefulSetUpdateStrategy indicates the strategy + that the StatefulSet controller will use to perform updates. + It includes any additional parameters necessary to perform the + update for the indicated strategy. + properties: + rollingUpdate: + description: RollingUpdate is used to communicate parameters + when Type is RollingUpdateStatefulSetStrategyType. + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of pods that can be unavailable + during the update. Value can be an absolute number (ex: + 5) or a percentage of desired pods (ex: 10%). Absolute + number is calculated from percentage by rounding up. + This can not be 0. Defaults to 1. This field is alpha-level + and is only honored by servers that enable the MaxUnavailableStatefulSet + feature. The field applies to all pods in the range + 0 to Replicas-1. That means if there is any unavailable + pod in the range 0 to Replicas-1, it will be counted + towards MaxUnavailable.' + x-kubernetes-int-or-string: true + partition: + description: Partition indicates the ordinal at which + the StatefulSet should be partitioned for updates. During + a rolling update, all pods from ordinal Replicas-1 to + Partition are updated. All pods from ordinal Partition-1 + to 0 remain untouched. This is helpful in being able + to do a canary based deployment. The default value is + 0. + format: int32 + type: integer + type: object + type: + description: Type indicates the type of the StatefulSetUpdateStrategy. + Default is RollingUpdate. + type: string + type: object + required: + - image + type: object + livenessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + nodeSelector: + additionalProperties: + type: string + type: object + podSecurityContext: + description: PodSecurityContext holds pod-level security attributes + and common container settings. Some fields are also present in container.securityContext. Field + values of container.securityContext take precedence over field values + of PodSecurityContext. + properties: + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field cannot + be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers in this + pod. Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID, + the fsGroup (if specified), and group memberships defined in + the container image for the uid of the container process. If + unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image for + the uid of the container process are still effective, even if + they are not included in this list. Note that this field cannot + be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options within a container's SecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + priorityClassName: + type: string + readinessProbe: + default: + failureThreshold: 3 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + description: Probe is a interface for ReadinessProbe and LivenessProbe + properties: + failureThreshold: + default: 3 + format: int32 + minimum: 1 + type: integer + initialDelaySeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + periodSeconds: + default: 10 + format: int32 + minimum: 1 + type: integer + successThreshold: + default: 1 + format: int32 + minimum: 1 + type: integer + timeoutSeconds: + default: 1 + format: int32 + minimum: 1 + type: integer + type: object + redisConfig: + description: RedisConfig defines the external configuration of Redis + properties: + additionalRedisConfig: + type: string + type: object + redisExporter: + description: RedisExporter interface will have the information for + redis exporter related stuff + properties: + enabled: + type: boolean + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. If + a variable cannot be resolved, the reference in the input + string will be unchanged. Double $$ are reduced to a single + $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless + of whether the variable exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. Requests cannot exceed + Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + type: object + securityContext: + description: SecurityContext holds security configuration that will + be applied to a container. Some fields are present in both SecurityContext + and PodSecurityContext. When both are set, the values in SecurityContext + take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a process + can gain more privileges than its parent process. This bool + directly controls if the no_new_privs flag will be set on the + container process. AllowPrivilegeEscalation is true always when + the container is: 1) run as Privileged 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. Note that this field cannot be set when spec.os.name + is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in privileged + containers are essentially equivalent to root on the host. Defaults + to false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use for + the containers. The default is DefaultProcMount which uses the + container runtime defaults for readonly paths and masked paths. + This requires the ProcMountType feature flag to be enabled. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when spec.os.name + is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container process. + Uses runtime default if unset. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail to start + the container if it does. If unset or false, no such validation + will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies to + the container. + type: string + role: + description: Role is a SELinux role label that applies to + the container. + type: string + type: + description: Type is a SELinux type label that applies to + the container. + type: string + user: + description: User is a SELinux user label that applies to + the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. If + seccomp options are provided at both the pod & container level, + the container options override the pod options. Note that this + field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must be + preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT be + set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a profile + defined in a file on the node should be used. RuntimeDefault + - the container runtime default profile should be used. + Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will + be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named by + the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the GMSA + credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's containers + must have the same effective HostProcess value (it is not + allowed to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in PodSecurityContext. + If set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: string + type: object + type: object + serviceAccountName: + type: string + sidecars: + items: + description: Sidecar for each Redis pods + properties: + command: + items: + type: string + type: array + env: + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be + a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in + the container and any service environment variables. + If a variable cannot be resolved, the reference in the + input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) + syntax: i.e. "$$(VAR_NAME)" will produce the string + literal "$(VAR_NAME)". Escaped references will never + be expanded, regardless of whether the variable exists + or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, `metadata.labels['''']`, + `metadata.annotations['''']`, spec.nodeName, + spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other + way around. When not set, MountPropagationNone is used. + This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + name: + type: string + ports: + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: Number of port to expose on the pod's IP + address. This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: Number of port to expose on the host. If + specified, this must be a valid port number, 0 < x < + 65536. If HostNetwork is specified, this must match + ContainerPort. Most containers do not need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a pod + must have a unique name. Name for the port that can + be referred to by services. + type: string + protocol: + default: TCP + description: Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - image + - name + type: object + type: array + storage: + description: Storage is the inteface to add pvc and pv support in + redis + properties: + volumeClaimTemplate: + description: PersistentVolumeClaim is a user's request for and + claim to a persistent volume + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + type: object + spec: + description: 'spec defines the desired characteristics of + a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + status: + description: 'status represents the current information/status + of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + accessModes: + description: 'accessModes contains the actual access modes + the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + allocatedResourceStatuses: + additionalProperties: + description: When a controller receives persistentvolume + claim update with ClaimResourceStatus for a resource + that it does not recognizes, then it should ignore + that update and let other controllers handle it. + type: string + description: "allocatedResourceStatuses stores status + of resource being resized for the given PVC. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n ClaimResourceStatus can be + in any of following states: \t- ControllerResizeInProgress: + \t\tState set when resize controller starts resizing + the volume in control-plane. \t- ControllerResizeFailed: + \t\tState set when resize has failed in resize controller + with a terminal error. \t- NodeResizePending: \t\tState + set when resize controller has finished resizing the + volume but further resizing of \t\tvolume is needed + on the node. \t- NodeResizeInProgress: \t\tState set + when kubelet starts resizing the volume. \t- NodeResizeFailed: + \t\tState set when resizing has failed in kubelet with + a terminal error. Transient errors don't set \t\tNodeResizeFailed. + For example: if expanding a PVC for more capacity - + this field can be one of the following states: \t- pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"ControllerResizeFailed\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizePending\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeInProgress\" - pvc.status.allocatedResourceStatus['storage'] + = \"NodeResizeFailed\" When this field is not set, it + means that no resize operation is in progress for the + given PVC. \n A controller that receives PVC update + with previously unknown resourceName or ClaimResourceStatus + should ignore the update for the purpose it was designed. + For example - a controller that only is responsible + for resizing capacity of the volume, should ignore PVC + updates that change other valid resources associated + with PVC. \n This is an alpha field and requires enabling + RecoverVolumeExpansionFailure feature." + type: object + x-kubernetes-map-type: granular + allocatedResources: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: "allocatedResources tracks the resources + allocated to a PVC including its capacity. Key names + follow standard Kubernetes label syntax. Valid values + are either: \t* Un-prefixed keys: \t\t- storage - the + capacity of the volume. \t* Custom resources must use + implementation-defined prefixed names such as \"example.com/my-custom-resource\" + Apart from above values - keys that are unprefixed or + have kubernetes.io prefix are considered reserved and + hence may not be used. \n Capacity reported here may + be larger than the actual capacity when a volume expansion + operation is requested. For storage quota, the larger + value from allocatedResources and PVC.spec.resources + is used. If allocatedResources is not set, PVC.spec.resources + alone is used for quota calculation. If a volume expansion + capacity request is lowered, allocatedResources is only + lowered if there are no expansion operations in progress + and if the actual volume capacity is equal or lower + than the requested capacity. \n A controller that receives + PVC update with previously unknown resourceName should + ignore the update for the purpose it was designed. For + example - a controller that only is responsible for + resizing capacity of the volume, should ignore PVC updates + that change other valid resources associated with PVC. + \n This is an alpha field and requires enabling RecoverVolumeExpansionFailure + feature." + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: capacity represents the actual resources + of the underlying volume. + type: object + conditions: + description: conditions is the current Condition of persistent + volume claim. If underlying persistent volume is being + resized then the Condition will be set to 'ResizeStarted'. + items: + description: PersistentVolumeClaimCondition contains + details about state of pvc + properties: + lastProbeTime: + description: lastProbeTime is the time we probed + the condition. + format: date-time + type: string + lastTransitionTime: + description: lastTransitionTime is the time the + condition transitioned from one status to another. + format: date-time + type: string + message: + description: message is the human-readable message + indicating details about last transition. + type: string + reason: + description: reason is a unique, this should be + a short, machine understandable string that gives + the reason for condition's last transition. If + it reports "ResizeStarted" that means the underlying + persistent volume is being resized. + type: string + status: + type: string + type: + description: PersistentVolumeClaimConditionType + is a valid value of PersistentVolumeClaimCondition.Type + type: string + required: + - status + - type + type: object + type: array + phase: + description: phase represents the current phase of PersistentVolumeClaim. + type: string + type: object + type: object + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's + root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves + similarly to SubPath but environment variable references + $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). SubPathExpr and SubPath + are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS + Disk resource that is attached to a kubelet''s host + machine and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the + readOnly setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More + info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk + mount on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk + in the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in + the blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure + managed data disk (only in managed availability + set). defaults to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the + host that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is + a collection of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default + is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile + is the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is + reference to the authentication secret for User, + default is empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados + user name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Examples: "ext4", "xfs", "ntfs". + Implicitly inferred to be "ext4" if unspecified. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a + secret object containing parameters used to connect + to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver + that handles this volume. Consult with your admin + for the correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference + to the secret object containing sensitive information + to pass to the CSI driver to complete the CSI + NodePublishVolume and NodeUnpublishVolume calls. + This field is optional, and may be empty if no + secret is required. If the secret object contains + more than one secret, all secret references are + passed. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. + Consult your driver's documentation for supported + values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about + the pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default + is "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The + size limit is also applicable for memory medium. + The maximum usage on memory medium EmptyDir would + be the minimum value between the SizeLimit specified + here and the sum of memory limits of all containers + in a pod. The default is nil which means that + the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is + handled by a cluster storage driver. The volume's + lifecycle is tied to the pod that defines it - it + will be created before the pod starts, and deleted + when the pod is removed. \n Use this if: a) the volume + is only needed while the pod runs, b) features of + normal volumes like restoring from snapshot or capacity + \ tracking are needed, c) the storage driver is + specified through a storage class, and d) the storage + driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between + this volume type and PersistentVolumeClaim). \n + Use PersistentVolumeClaim or one of the vendor-specific + APIs for volumes that persist for longer than the + lifecycle of an individual pod. \n Use CSI for light-weight + local ephemeral volumes if the CSI driver is meant + to be used that way - see the documentation of the + driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes + at the same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone + PVC to provision the volume. The pod in which + this EphemeralVolumeSource is embedded will be + the owner of the PVC, i.e. the PVC will be deleted + together with the pod. The name of the PVC will + be `-` where `` + is the name from the `PodSpec.Volumes` array entry. + Pod validation will reject the pod if the concatenated + name is not valid for a PVC (for example, too + long). \n An existing PVC with that name that + is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by + mistake. Starting the pod is then blocked until + the unrelated PVC is removed. If such a pre-created + PVC is meant to be used by the pod, the PVC has + to updated with an owner reference to the pod + once the pod exists. Normally this should not + be necessary, but it may be useful when manually + reconstructing a broken cluster. \n This field + is read-only and no changes will be made by Kubernetes + to the PVC after it has been created. \n Required, + must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be + rejected during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into + the PVC that gets created from this template. + The same fields as in a PersistentVolumeClaim + are also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used + to specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, + it will create a new volume based on the + contents of the specified data source. + When the AnyVolumeDataSource feature gate + is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource + when dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the + object from which to populate the volume + with data, if a non-empty volume is desired. + This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, + volume binding will only succeed if the + type of the specified object matches some + installed volume populator or dynamic + provisioner. This field will replace the + functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the + same value automatically if one of them + is empty and the other is non-empty. When + namespace is specified in dataSourceRef, + dataSource isn''t set to the same value + and must be empty. There are three important + differences between dataSource and dataSourceRef: + * While dataSource only allows two specific + types of objects, dataSourceRef allows + any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed + values (dropping them), dataSourceRef preserves + all values, and generates an error if + a disallowed value is specified. * While + dataSource only allows local objects, + dataSourceRef allows objects in any + namespaces. (Beta) Using this field requires + the AnyVolumeDataSource feature gate to + be enabled. (Alpha) Using the namespace + field of dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for + the resource being referenced. If + APIGroup is not specified, the specified + Kind must be in the core API group. + For any other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note + that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent + namespace to allow that namespace's + owner to accept the reference. See + the ReferenceGrant documentation for + details. (Alpha) This field requires + the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to + specify resource requirements that are + lower than previous value but must still + be higher than capacity recorded in the + status field of the claim. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names + of resources, defined in spec.resourceClaims, + that are used by this container. \n + This is an alpha field and requires + enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. + It can only be set for containers." + items: + description: ResourceClaim references + one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the + name of one entry in pod.spec.resourceClaims + of the Pod where this field + is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + Requests cannot exceed Limits. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name + of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type + of volume is required by the claim. Value + of Filesystem is implied when not included + in claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource + that is attached to a kubelet's host machine and then + exposed to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. TODO: how + do we prevent errors in the filesystem from compromising + the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target + worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide + identifiers (wwids) Either wwids or combination + of targetWWNs and lun must be set, but not both + simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume + resource that is provisioned/attached using an exec + based plugin. + properties: + driver: + description: driver is the name of the driver to + use for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". The + default filesystem depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to + false (read/write). ReadOnly here will force the + ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is + reference to the secret object containing sensitive + information to pass to the plugin scripts. This + may be empty if no secret object is specified. + If the secret object contains more than one secret, + all secrets are passed to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset + stored as metadata -> name on the dataset for + Flocker should be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. + Examples: "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + partition: + description: 'partition is the partition in the + volume that you want to mount. If omitted, the + default is to mount by volume name. Examples: + For volume /dev/sda1, you specify the partition + as "1". Similarly, the volume partition for /dev/sda + is "0" (or you can leave the property empty). + More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at + a particular revision. DEPRECATED: GitRepo is deprecated. + To provision a container with a git repo, mount an + EmptyDir into an InitContainer that clones the repo + using git, then mount the EmptyDir into the Pod''s + container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is + supplied, the volume directory will be the git + repository. Otherwise, if specified, the volume + will contain the git repository in the subdirectory + with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the + specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. + More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. + Defaults to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file + or directory on the host machine that is directly + exposed to the container. This is generally used for + system agents or other privileged things that are + allowed to see the host machine. Most containers will + NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use + host directory mounts and who can/can not mount host + directories as read/write.' + properties: + path: + description: 'path of the directory on the host. + If the path is a symlink, it will follow the link + to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults + to "" More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource + that is attached to a kubelet''s host machine and + then exposed to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name + that uses an iSCSI transport. Defaults to 'default' + (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal + List. The portal is either an IP or ip_addr:port + if the port is other than default (typically TCP + ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. + The Portal is either an IP or ip_addr:port if + the port is other than default (typically TCP + ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL + and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host + that shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address + of the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same + namespace. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon + Controller persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type + to mount Must be a filesystem type supported by + the host operating system. Ex. "ext4", "xfs". + Implicitly inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources + secrets, configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used + to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Directories within the path + are not affected by this setting. This might be + in conflict with other options that affect the + file mode, like fsGroup, and the result can be + other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected + along with other supported volume types + properties: + configMap: + description: configMap information about the + configMap data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced ConfigMap will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether + the ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about + the downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects + a field of the pod: only annotations, + labels, name and namespace are + supported.' + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits + used to set permissions on this + file, must be an octal value between + 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts + both octal and decimal values, + JSON requires decimal values for + mode bits. If not specified, the + volume defaultMode will be used. + This might be in conflict with + other options that affect the + file mode, like fsGroup, and the + result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file + to be created. Must not be absolute + or contain the ''..'' path. Must + be utf-8 encoded. The first item + of the relative path must not + start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource + of the container: only resources + limits and requests (limits.cpu, + limits.memory, requests.cpu and + requests.memory) are currently + supported.' + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the + secret data to project + properties: + items: + description: items if unspecified, each + key-value pair in the Data field of + the referenced Secret will be projected + into the volume as a file whose name + is the key and content is the value. + If specified, the listed keys will be + projected into the specified paths, + and unlisted keys will not be present. + If a key is specified which is not present + in the Secret, the volume setup will + error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a + path within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: + mode bits used to set permissions + on this file. Must be an octal + value between 0000 and 0777 or + a decimal value between 0 and + 511. YAML accepts both octal and + decimal values, JSON requires + decimal values for mode bits. + If not specified, the volume defaultMode + will be used. This might be in + conflict with other options that + affect the file mode, like fsGroup, + and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative + path of the file to map the key + to. May not be an absolute path. + May not contain the path element + '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More + info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended + audience of the token. A recipient of + a token must identify itself with an + identifier specified in the audience + of the token, and otherwise should reject + the token. The audience defaults to + the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the + requested duration of validity of the + service account token. As the token + approaches expiration, the kubelet volume + plugin will proactively rotate the service + account token. The kubelet will start + trying to rotate the token if the token + is older than 80 percent of its time + to live or if the token is older than + 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative + to the mount point of the file to project + the token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the + host that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default + is no group + type: string + readOnly: + description: readOnly here will force the Quobyte + volume to be mounted with read-only permissions. + Defaults to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string + as host:port pair (multiple entries are separated + with commas) which acts as the central registry + for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned + Quobyte volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults + to serivceaccount user + type: string + volume: + description: volume is a string that references + an already created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the + volume that you want to mount. Tip: Ensure that + the filesystem type is supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: + https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem + from compromising the machine' + type: string + image: + description: 'image is the rados image name. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for + RBDUser. Default is /etc/ceph/keyring. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default + is rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default + is admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent + volume attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Default + is "xfs". + type: string + gateway: + description: gateway is the host address of the + ScaleIO API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the + ScaleIO Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret + for ScaleIO user and other sensitive information. + If this is not provided, Login operation will + fail. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL + communication with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage + Pool associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume + already created in the ScaleIO system that is + associated with this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should + populate this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits + used to set permissions on created files by default. + Must be an octal value between 0000 and 0777 or + a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal + values for mode bits. Defaults to 0644. Directories + within the path are not affected by this setting. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits + used to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. YAML + accepts both octal and decimal values, JSON + requires decimal values for mode bits. If + not specified, the volume defaultMode will + be used. This might be in conflict with + other options that affect the file mode, + like fsGroup, and the result can be other + mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path of + the file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the string + '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the + Secret or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret + in the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting + in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use + for obtaining the StorageOS API credentials. If + not specified, default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name + of the StorageOS volume. Volume names are only + unique within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope + of the volume within StorageOS. If no namespace + is specified then the Pod's namespace will be + used. This allows the Kubernetes name scoping + to be mirrored within StorageOS for tighter integration. + Set VolumeName to any name to override the default + behaviour. Set to "default" if you are not using + namespaces within StorageOS. Namespaces that do + not pre-exist within StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. + Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy + Based Management (SPBM) profile ID associated + with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + required: + - kubernetesConfig + type: object + status: + description: RedisStatus defines the observed state of Redis + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1beta1","v1beta2"] + clientConfig: + service: + namespace: redis-operator + name: webhook-service + path: /convert +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/redis-operator/readme.md b/charts/redis-operator/readme.md new file mode 100644 index 000000000..af4be36d2 --- /dev/null +++ b/charts/redis-operator/readme.md @@ -0,0 +1,112 @@ +# Redis Operator Helm Chart + +## Introduction + +This Helm chart deploys the redis-operator into your Kubernetes cluster. The operator facilitates the deployment, scaling, and management of Redis clusters and other Redis resources provided by the OpsTree Solutions team. + +## Pre-requisites + +- Helm v3+ +- Kubernetes v1.16+ +- If you intend to use the cert-manager, ensure that the cert-manager CRDs are installed before deploying the redis-operator. + +## Installation Steps + +### 1. Add Helm Repository + +```bash +helm repo add ot-helm https://ot-container-kit.github.io/helm-charts +``` + +### 2. Install Cert-Manager CRDs (if using cert-manager) + +If you plan to use cert-manager with the redis-operator, you need to install the cert-manager CRDs before deploying the operator. + +```bash +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.4/cert-manager.crds.yaml +``` + +### 3. Install Redis Operator + +Replace `` and `` with your specific values. + +```bash +helm install ot-helm/redis-operator --version=0.15.5 --appVersion=0.15.1 --set certificate.secretName= --set certmanager.enabled=true --set redisOperator.webhook=true --namespace --create-namespace +``` + +> Note: If `certificate.secretName` is not provided, the operator will generate a self-signed certificate and use it for webhook server. +--- +> Note : If you want to disable the webhook you have to pass the `--set webhook=false` and `--set certmanager.enabled=false` while installing the redis-operator. + +### 4. Patch the CA Bundle (if using cert-manager) + +Cert-manager injects the CA bundle into the webhook configuration. + +```bash +kubectl patch crd redis.redis.redis.opstreelabs.in -p '{"metadata":{"annotations":{"cert-manager.io/inject-ca-from":"/"}}}' + +kubectl patch crd redisclusters.redis.redis.opstreelabs.in -p '{"metadata":{"annotations":{"cert-manager.io/inject-ca-from":"/"}}}' + +kubectl patch crd redisreplications.redis.redis.opstreelabs.in -p '{"metadata":{"annotations":{"cert-manager.io/inject-ca-from":"/"}}}' + +kubectl patch crd redissentinels.redis.redis.opstreelabs.in -p '{"metadata":{"annotations":{"cert-manager.io/inject-ca-from":"/"}}}' +``` + +> Note: Replace `` and `` with your specific values i.e. release name and certificate name. + +#### You can verify the patch by running the following commands + +```bash +kubectl get crd redis.redis.redis.opstreelabs.in -o=jsonpath='{.metadata.annotations}' +kubectl get crd redisclusters.redis.redis.opstreelabs.in -o=jsonpath='{.metadata.annotations}' +kubectl get crd redisreplications.redis.redis.opstreelabs.in -o=jsonpath='{.metadata.annotations}' +kubectl get crd redissentinels.redis.redis.opstreelabs.in -o=jsonpath='{.metadata.annotations}' +``` + +### How to generate private key( Optional ) + +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt +kubectl create secret tls --key tls.key --cert tls.crt -n +``` + +> Note: This secret will be used for webhook server certificate so generate it before installing the redis-operator. + +## Default Values + +| Parameter | Description | Default | +|-------------------------------------|------------------------------------|--------------------------------------------------------------| +| `redisOperator.name` | Operator name | `redis-operator` | +| `redisOperator.imageName` | Image repository | `quay.io/opstree/redis-operator` | +| `redisOperator.imageTag` | Image tag | `{{appVersion}}` | +| `redisOperator.imagePullPolicy` | Image pull policy | `Always` | +| `redisOperator.podAnnotations` | Additional pod annotations | `{}` | +| `redisOperator.podLabels` | Additional Pod labels | `{}` | +| `redisOperator.extraArgs` | Additional arguments for the operator | `{}` | +| `redisOperator.watch_namespace` | Namespace for the operator to watch | `""` | +| `redisOperator.env` | Environment variables for the operator | `{}` | +| `redisOperator.webhook` | Enable webhook | `false` | +| `resources.limits.cpu` | CPU limit | `500m` | +| `resources.limits.memory` | Memory limit | `500Mi` | +| `resources.requests.cpu` | CPU request | `500m` | +| `resources.requests.memory` | Memory request | `500Mi` | +| `replicas` | Number of replicas | `1` | +| `serviceAccountName` | Service account name | `redis-operator` | +| `certificate.name` | Certificate name | `serving-cert` | +| `certificate.secretName` | Certificate secret name | `webhook-server-cert` | +| `issuer.type` | Issuer type | `selfSigned` | +| `issuer.name` | Issuer name | `redis-operator-issuer` | +| `issuer.email` | Issuer email | `shubham.gupta@opstree.com` | +| `issuer.server` | Issuer server URL | `https://acme-v02.api.letsencrypt.org/directory` | +| `issuer.privateKeySecretName` | Private key secret name | `letsencrypt-prod` | +| `certManager.enabled` | Enable cert-manager | `false` | + +## Scheduling Parameters + +| Parameter | Description | Default | +|-------------------------|--------------------------------------------|----------| +| `priorityClassName` | Priority class name for the pods | `""` | +| `nodeSelector` | Labels for pod assignment | `{}` | +| `tolerateAllTaints` | Whether to tolerate all node taints | `false` | +| `tolerations` | Taints to tolerate | `[]` | +| `affinity` | Affinity rules for pod assignment | `{}` | diff --git a/charts/redis-operator/templates/_helpers.tpl b/charts/redis-operator/templates/_helpers.tpl new file mode 100644 index 000000000..5a70733b0 --- /dev/null +++ b/charts/redis-operator/templates/_helpers.tpl @@ -0,0 +1,34 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Define issuer spec based on the type */}} +{{- define "redis-operator.issuerSpec" -}} +{{- if eq .Values.issuer.type "acme" }} +acme: + email: {{ .Values.issuer.email }} + server: {{ .Values.issuer.server }} + privateKeySecretRef: + name: {{ .Values.issuer.privateKeySecretName }} + solvers: + - http01: + ingress: + class: {{ .Values.issuer.solver.ingressClass }} +{{- else }} +selfSigned: {} +{{- end }} +{{- end -}} + +{{/* Common labels */}} +{{- define "redisOperator.labels" -}} +app.kubernetes.io/name: {{ .Values.redisOperator.name }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +app.kubernetes.io/component: operator +app.kubernetes.io/part-of: {{ .Release.Name }} +{{- end }} + +{{/* Selector labels */}} +{{- define "redisOperator.selectorLabels" -}} +name: {{ .Values.redisOperator.name }} +{{- end }} \ No newline at end of file diff --git a/charts/redis-operator/templates/cert-manager.yaml b/charts/redis-operator/templates/cert-manager.yaml new file mode 100644 index 000000000..fa09325fe --- /dev/null +++ b/charts/redis-operator/templates/cert-manager.yaml @@ -0,0 +1,43 @@ +{{ if .Values.certmanager.enabled }} + +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ .Values.issuer.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ .Values.redisOperator.name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: issuer + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + {{- include "redis-operator.issuerSpec" . | nindent 2 }} + +--- + +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ .Values.certificate.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ .Values.redisOperator.name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: certificate + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + dnsNames: + - {{ .Values.service.name }}.{{ .Values.service.namespace }}.svc + - {{ .Values.service.name }}.{{ .Values.service.namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: {{ .Values.issuer.name }} + secretName: {{ .Values.certificate.secretName }} + +{{ end }} \ No newline at end of file diff --git a/charts/redis-operator/templates/operator-deployment.yaml b/charts/redis-operator/templates/operator-deployment.yaml new file mode 100644 index 000000000..b1a5d8bea --- /dev/null +++ b/charts/redis-operator/templates/operator-deployment.yaml @@ -0,0 +1,76 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Values.redisOperator.name }} + namespace: {{ .Release.Namespace }} + labels: {{- include "redisOperator.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: {{- include "redisOperator.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} + {{- with .Values.redisOperator.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: {{- include "redisOperator.selectorLabels" . | nindent 8 }} + {{- with .Values.redisOperator.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + containers: + - name: "{{ .Values.redisOperator.name }}" + image: "{{ .Values.redisOperator.imageName }}:{{ .Values.redisOperator.imageTag | default (printf "v%s" .Chart.AppVersion) }}" + imagePullPolicy: {{ .Values.redisOperator.imagePullPolicy }} + command: + - /manager + args: + - --leader-elect + {{- range $arg := .Values.redisOperator.extraArgs }} + - {{ $arg }} + {{- end }} + {{- if .Values.redisOperator.webhook }} + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + {{- end }} + env: + - name: ENABLE_WEBHOOKS + value: "{{ .Values.redisOperator.webhook | toString }}" + {{- if .WATCH_NAMESPACE }} + - name: WATCH_NAMESPACE + value: {{ .WATCH_NAMESPACE }} + {{- end }} + {{- range $env := .Values.redisOperator.env }} + - name: {{ $env.name }} + value: {{ $env.value | quote }} + {{- end }} + {{- if .Values.resources }} + resources: {{ toYaml .Values.resources | nindent 10 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: {{ toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName}} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- with .Values.affinity }} + affinity: {{ toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: "{{ .Values.serviceAccountName }}" + serviceAccount: "{{ .Values.serviceAccountName }}" + {{- if .Values.redisOperator.webhook }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: {{ .Values.certificate.secretName }} + {{- end }} \ No newline at end of file diff --git a/charts/redis-operator/templates/role-binding.yaml b/charts/redis-operator/templates/role-binding.yaml new file mode 100644 index 000000000..a1aaa585d --- /dev/null +++ b/charts/redis-operator/templates/role-binding.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ .Values.redisOperator.name }} + labels: + app.kubernetes.io/name : {{ .Values.redisOperator.name }} + helm.sh/chart : {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by : {{ .Release.Service }} + app.kubernetes.io/instance : {{ .Release.Name }} + app.kubernetes.io/version : {{ .Chart.AppVersion }} + app.kubernetes.io/component: role-binding + app.kubernetes.io/part-of : {{ .Release.Name }} +subjects: +- kind: ServiceAccount + name: {{ .Values.serviceAccountName }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ .Values.redisOperator.name }} + apiGroup: rbac.authorization.k8s.io diff --git a/charts/redis-operator/templates/role.yaml b/charts/redis-operator/templates/role.yaml new file mode 100644 index 000000000..600e1be8b --- /dev/null +++ b/charts/redis-operator/templates/role.yaml @@ -0,0 +1,126 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ .Values.redisOperator.name }} + labels: + app.kubernetes.io/name : {{ .Values.redisOperator.name }} + helm.sh/chart : {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by : {{ .Release.Service }} + app.kubernetes.io/instance : {{ .Release.Name }} + app.kubernetes.io/version : {{ .Chart.AppVersion }} + app.kubernetes.io/component: role + app.kubernetes.io/part-of : {{ .Release.Name }} +rules: +- apiGroups: + - redis.redis.opstreelabs.in + resources: + - rediss + - redisclusters + - redisreplications + - redis + - rediscluster + - redissentinel + - redissentinels + - redisreplication + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- nonResourceURLs: + - '*' + verbs: + - get +- apiGroups: + - "apiextensions.k8s.io" + resources: + - "customresourcedefinitions" + verbs: + - "get" + - "list" + - "watch" +- apiGroups: + - redis.redis.opstreelabs.in + resources: + - redis/finalizers + - rediscluster/finalizers + - redisclusters/finalizers + - redissentinel/finalizers + - redissentinels/finalizers + - redisreplication/finalizers + - redisreplications/finalizers + verbs: + - update +- apiGroups: + - redis.redis.opstreelabs.in + resources: + - redis/status + - rediscluster/status + - redisclusters/status + - redissentinel/status + - redissentinels/status + - redisreplication/status + - redisreplications/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - secrets + - pods/exec + - pods + - services + - configmaps + - events + - persistentvolumeclaims + - namespace + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "coordination.k8s.io" + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "policy" + resources: + - poddisruptionbudgets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch diff --git a/charts/redis-operator/templates/service-account.yaml b/charts/redis-operator/templates/service-account.yaml new file mode 100644 index 000000000..f1cbdcca7 --- /dev/null +++ b/charts/redis-operator/templates/service-account.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.redisOperator.name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name : {{ .Values.redisOperator.name }} + helm.sh/chart : {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by : {{ .Release.Service }} + app.kubernetes.io/instance : {{ .Release.Name }} + app.kubernetes.io/version : {{ .Chart.AppVersion }} + app.kubernetes.io/component: service-account + app.kubernetes.io/part-of : {{ .Release.Name }} diff --git a/charts/redis-operator/templates/service.yaml b/charts/redis-operator/templates/service.yaml new file mode 100644 index 000000000..9a6bcbf68 --- /dev/null +++ b/charts/redis-operator/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name : {{ .Values.redisOperator.name }} + helm.sh/chart : {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by : {{ .Release.Service }} + app.kubernetes.io/instance : {{ .Release.Name }} + app.kubernetes.io/version : {{ .Chart.AppVersion }} + app.kubernetes.io/component: webhook + app.kubernetes.io/part-of : {{ .Release.Name }} + name: {{ .Values.service.name }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + name: {{ .Values.redisOperator.name }} diff --git a/charts/redis-operator/values.yaml b/charts/redis-operator/values.yaml new file mode 100644 index 000000000..5367b8f02 --- /dev/null +++ b/charts/redis-operator/values.yaml @@ -0,0 +1,60 @@ +--- +redisOperator: + name: redis-operator + imageName: ghcr.io/ot-container-kit/redis-operator + # Overrides the image tag whose default is the chart appVersion. + imageTag: "" + imagePullPolicy: Always + + # Additional pod annotations + podAnnotations: {} + # Additional Pod labels (e.g. for filtering Pod by custom labels) + podLabels: {} + + # Additional arguments for redis-operator container + extraArgs: [] + + # - -zap-log-level=error + watch_namespace: "" + env: [] + webhook: false + + +resources: + limits: + cpu: 500m + memory: 500Mi + requests: + cpu: 500m + memory: 500Mi + +replicas: 1 + +serviceAccountName: redis-operator + +service: + name: webhook-service + namespace: redis-operator + +certificate: + name: serving-cert + secretName: webhook-server-cert + +issuer: + type: selfSigned + name: redis-operator-issuer + email: shubham.gupta@opstree.com + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretName: letsencrypt-prod + solver: + enabled: true + ingressClass: nginx + +certmanager: + enabled: false + +priorityClassName: "" +nodeSelector: {} +tolerateAllTaints: false +tolerations: [] +affinity: {} From bd6ddac64fb0c0cbfa761329fa0481c6b70f355e Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 30 May 2024 11:30:02 +0800 Subject: [PATCH 174/203] build: separate chart and image release process (#956) build: separate chart / image release process Signed-off-by: drivebyer --- .github/workflows/publish-charts.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-charts.yaml b/.github/workflows/publish-charts.yaml index 9a77c29f8..e86e50d43 100644 --- a/.github/workflows/publish-charts.yaml +++ b/.github/workflows/publish-charts.yaml @@ -1,9 +1,15 @@ name: Release Charts +#on: +# push: +# tags: +# - "v*.*.*" on: push: - tags: - - "v*.*.*" + paths: + - 'charts/**' + branches: + - master jobs: release-charts: @@ -36,8 +42,8 @@ jobs: shell: bash working-directory: redis-operator run: | - VERSION=$(echo ${{ env.chart_version }} | cut -c 2-) - sed -i "s/appVersion:.*/appVersion: \"$VERSION\"/g" charts/redis-operator/Chart.yaml +# VERSION=$(echo ${{ env.chart_version }} | cut -c 2-) +# sed -i "s/appVersion:.*/appVersion: \"$VERSION\"/g" charts/redis-operator/Chart.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm dependency update charts/redis-operator From 5ec6ef3248fa8501691fb60777ea36219f3bc1d7 Mon Sep 17 00:00:00 2001 From: Jordan Rodgers Date: Thu, 30 May 2024 02:29:54 -0700 Subject: [PATCH 175/203] feat: add support for configurable probe handlers (#934) add support for configurable probe handlers Signed-off-by: Jordan Rodgers --- api/common_types.go | 40 +- api/v1beta1/common_types.go | 5 - api/v1beta1/redis_conversion.go | 17 +- api/v1beta1/redis_types.go | 30 +- api/v1beta1/rediscluster_types.go | 6 +- api/v1beta1/redisreplication_conversion.go | 17 +- api/v1beta1/redisreplication_types.go | 32 +- api/v1beta1/redissentinel_conversion.go | 17 +- api/v1beta1/redissentinel_types.go | 10 +- api/v1beta1/zz_generated.deepcopy.go | 40 +- api/v1beta2/common_types.go | 5 - api/v1beta2/redis_types.go | 40 +- api/v1beta2/rediscluster_types.go | 6 +- api/v1beta2/redisreplication_types.go | 42 +- api/v1beta2/redissentinel_types.go | 40 +- api/v1beta2/zz_generated.deepcopy.go | 40 +- api/zz_generated.deepcopy.go | 31 +- .../redis.redis.opstreelabs.in_redis.yaml | 572 +++++++- ...is.redis.opstreelabs.in_redisclusters.yaml | 1244 ++++++++++++++--- ...edis.opstreelabs.in_redisreplications.yaml | 572 +++++++- ...s.redis.opstreelabs.in_redissentinels.yaml | 572 +++++++- .../en/docs/CRD Reference/Redis API/_index.md | 100 +- k8sutils/redis-cluster.go | 7 +- k8sutils/redis-replication.go | 4 +- k8sutils/redis-sentinel.go | 11 +- k8sutils/redis-standalone.go | 4 +- k8sutils/statefulset.go | 54 +- 27 files changed, 2808 insertions(+), 750 deletions(-) diff --git a/api/common_types.go b/api/common_types.go index ae4f5aa6a..22030149d 100644 --- a/api/common_types.go +++ b/api/common_types.go @@ -76,26 +76,6 @@ type TLSConfig struct { Secret corev1.SecretVolumeSource `json:"secret"` } -// Probe is a interface for ReadinessProbe and LivenessProbe -// +k8s:deepcopy-gen=true -type Probe struct { - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:default=1 - InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty" protobuf:"varint,2,opt,name=initialDelaySeconds"` - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:default=1 - TimeoutSeconds int32 `json:"timeoutSeconds,omitempty" protobuf:"varint,3,opt,name=timeoutSeconds"` - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:default=10 - PeriodSeconds int32 `json:"periodSeconds,omitempty" protobuf:"varint,4,opt,name=periodSeconds"` - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:default=1 - SuccessThreshold int32 `json:"successThreshold,omitempty" protobuf:"varint,5,opt,name=successThreshold"` - // +kubebuilder:validation:Minimum=1 - // +kubebuilder:default=3 - FailureThreshold int32 `json:"failureThreshold,omitempty" protobuf:"varint,6,opt,name=failureThreshold"` -} - // Sidecar for each Redis pods // +k8s:deepcopy-gen=true type Sidecar struct { @@ -113,12 +93,10 @@ type RedisLeader struct { RedisConfig *RedisConfig `json:"redisConfig,omitempty"` Affinity *corev1.Affinity `json:"affinity,omitempty"` PodDisruptionBudget *RedisPodDisruptionBudget `json:"pdb,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` } // RedisFollower interface will have the redis follower configuration @@ -128,12 +106,10 @@ type RedisFollower struct { RedisConfig *RedisConfig `json:"redisConfig,omitempty"` Affinity *corev1.Affinity `json:"affinity,omitempty"` PodDisruptionBudget *RedisPodDisruptionBudget `json:"pdb,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` } // RedisPodDisruptionBudget configure a PodDisruptionBudget on the resource (leader/follower) diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index bb15d4bb7..5165359be 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -58,11 +58,6 @@ type TLSConfig struct { common.TLSConfig `json:",inline"` } -// Probe is a interface for ReadinessProbe and LivenessProbe -type Probe struct { - common.Probe `json:",inline"` -} - // Sidecar for each Redis pods type Sidecar struct { common.Sidecar `json:",inline"` diff --git a/api/v1beta1/redis_conversion.go b/api/v1beta1/redis_conversion.go index 297eb7e3f..3dd0a28b6 100644 --- a/api/v1beta1/redis_conversion.go +++ b/api/v1beta1/redis_conversion.go @@ -2,6 +2,7 @@ package v1beta1 import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -60,13 +61,13 @@ func (src *Redis) ConvertTo(dstRaw conversion.Hub) error { } // ReadinessProbe if src.Spec.ReadinessProbe != nil { - dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} - dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.ReadinessProbe = src.Spec.ReadinessProbe } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.LivenessProbe = &redisv1beta2.Probe{} - dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe + dst.Spec.LivenessProbe = &corev1.Probe{} + dst.Spec.LivenessProbe = src.Spec.LivenessProbe } // Sidecars if src.Spec.Sidecars != nil { @@ -141,13 +142,13 @@ func (dst *Redis) ConvertFrom(srcRaw conversion.Hub) error { } // ReadinessProbe if src.Spec.ReadinessProbe != nil { - dst.Spec.ReadinessProbe = &Probe{} - dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.ReadinessProbe = src.Spec.ReadinessProbe } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.LivenessProbe = &Probe{} - dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe + dst.Spec.LivenessProbe = &corev1.Probe{} + dst.Spec.LivenessProbe = src.Spec.LivenessProbe } // Sidecars if src.Spec.Sidecars != nil { diff --git a/api/v1beta1/redis_types.go b/api/v1beta1/redis_types.go index 8f30e2d10..b5e4c61e5 100644 --- a/api/v1beta1/redis_types.go +++ b/api/v1beta1/redis_types.go @@ -26,22 +26,20 @@ import ( // RedisSpec defines the desired state of Redis type RedisSpec struct { - KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` - RedisExporter *RedisExporter `json:"redisExporter,omitempty"` - RedisConfig *RedisConfig `json:"redisConfig,omitempty"` - Storage *Storage `json:"storage,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` - PriorityClassName string `json:"priorityClassName,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - TLS *TLSConfig `json:"TLS,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` + KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` + RedisExporter *RedisExporter `json:"redisExporter,omitempty"` + RedisConfig *RedisConfig `json:"redisConfig,omitempty"` + Storage *Storage `json:"storage,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` + PriorityClassName string `json:"priorityClassName,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + TLS *TLSConfig `json:"TLS,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` } // RedisStatus defines the observed state of Redis diff --git a/api/v1beta1/rediscluster_types.go b/api/v1beta1/rediscluster_types.go index 21df7fde0..4e5900878 100644 --- a/api/v1beta1/rediscluster_types.go +++ b/api/v1beta1/rediscluster_types.go @@ -27,10 +27,8 @@ type RedisClusterSpec struct { Size *int32 `json:"clusterSize"` KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` // +kubebuilder:default:=v7 - ClusterVersion *string `json:"clusterVersion,omitempty"` - // +kubebuilder:default:={livenessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}, readinessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}} - RedisLeader RedisLeader `json:"redisLeader,omitempty"` - // +kubebuilder:default:={livenessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}, readinessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}} + ClusterVersion *string `json:"clusterVersion,omitempty"` + RedisLeader RedisLeader `json:"redisLeader,omitempty"` RedisFollower RedisFollower `json:"redisFollower,omitempty"` RedisExporter *RedisExporter `json:"redisExporter,omitempty"` Storage *Storage `json:"storage,omitempty"` diff --git a/api/v1beta1/redisreplication_conversion.go b/api/v1beta1/redisreplication_conversion.go index 5555dfc5a..121f4ff02 100644 --- a/api/v1beta1/redisreplication_conversion.go +++ b/api/v1beta1/redisreplication_conversion.go @@ -2,6 +2,7 @@ package v1beta1 import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -59,13 +60,13 @@ func (src *RedisReplication) ConvertTo(dstRaw conversion.Hub) error { } // ReadinessProbe if src.Spec.ReadinessProbe != nil { - dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} - dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.ReadinessProbe = src.Spec.ReadinessProbe } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.LivenessProbe = &redisv1beta2.Probe{} - dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe + dst.Spec.LivenessProbe = &corev1.Probe{} + dst.Spec.LivenessProbe = src.Spec.LivenessProbe } // Sidecars if src.Spec.Sidecars != nil { @@ -138,13 +139,13 @@ func (dst *RedisReplication) ConvertFrom(srcRaw conversion.Hub) error { } // ReadinessProbe if src.Spec.ReadinessProbe != nil { - dst.Spec.ReadinessProbe = &Probe{} - dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.ReadinessProbe = src.Spec.ReadinessProbe } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.ReadinessProbe = &Probe{} - dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.LivenessProbe = src.Spec.LivenessProbe } // Sidecars if src.Spec.Sidecars != nil { diff --git a/api/v1beta1/redisreplication_types.go b/api/v1beta1/redisreplication_types.go index d4be20456..0503ebd53 100644 --- a/api/v1beta1/redisreplication_types.go +++ b/api/v1beta1/redisreplication_types.go @@ -6,23 +6,21 @@ import ( ) type RedisReplicationSpec struct { - Size *int32 `json:"clusterSize"` - KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` - RedisExporter *RedisExporter `json:"redisExporter,omitempty"` - RedisConfig *RedisConfig `json:"redisConfig,omitempty"` - Storage *Storage `json:"storage,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` - PriorityClassName string `json:"priorityClassName,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - TLS *TLSConfig `json:"TLS,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` + Size *int32 `json:"clusterSize"` + KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` + RedisExporter *RedisExporter `json:"redisExporter,omitempty"` + RedisConfig *RedisConfig `json:"redisConfig,omitempty"` + Storage *Storage `json:"storage,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` + PriorityClassName string `json:"priorityClassName,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + TLS *TLSConfig `json:"TLS,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` } func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { diff --git a/api/v1beta1/redissentinel_conversion.go b/api/v1beta1/redissentinel_conversion.go index 63a460b1c..9a8b69cd6 100644 --- a/api/v1beta1/redissentinel_conversion.go +++ b/api/v1beta1/redissentinel_conversion.go @@ -2,6 +2,7 @@ package v1beta1 import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/conversion" ) @@ -48,13 +49,13 @@ func (src *RedisSentinel) ConvertTo(dstRaw conversion.Hub) error { } // ReadinessProbe if src.Spec.ReadinessProbe != nil { - dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} - dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.ReadinessProbe = src.Spec.ReadinessProbe } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.ReadinessProbe = &redisv1beta2.Probe{} - dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe + dst.Spec.LivenessProbe = &corev1.Probe{} + dst.Spec.LivenessProbe = src.Spec.LivenessProbe } // Sidecars if src.Spec.Sidecars != nil { @@ -116,13 +117,13 @@ func (dst *RedisSentinel) ConvertFrom(srcRaw conversion.Hub) error { } // ReadinessProbe if src.Spec.ReadinessProbe != nil { - dst.Spec.ReadinessProbe = &Probe{} - dst.Spec.ReadinessProbe.Probe = src.Spec.ReadinessProbe.Probe + dst.Spec.ReadinessProbe = &corev1.Probe{} + dst.Spec.ReadinessProbe = src.Spec.ReadinessProbe } // LivenessProbe if src.Spec.LivenessProbe != nil { - dst.Spec.LivenessProbe = &Probe{} - dst.Spec.LivenessProbe.Probe = src.Spec.LivenessProbe.Probe + dst.Spec.LivenessProbe = &corev1.Probe{} + dst.Spec.LivenessProbe = src.Spec.LivenessProbe } // Sidecars if src.Spec.Sidecars != nil { diff --git a/api/v1beta1/redissentinel_types.go b/api/v1beta1/redissentinel_types.go index 54536b231..999dbf364 100644 --- a/api/v1beta1/redissentinel_types.go +++ b/api/v1beta1/redissentinel_types.go @@ -20,12 +20,10 @@ type RedisSentinelSpec struct { Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` TLS *TLSConfig `json:"TLS,omitempty"` PodDisruptionBudget *common.RedisPodDisruptionBudget `json:"pdb,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` } func (cr *RedisSentinelSpec) GetSentinelCounts(t string) int32 { diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index ff2aa9844..c1b1a0474 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -68,22 +68,6 @@ func (in *KubernetesConfig) DeepCopy() *KubernetesConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Probe) DeepCopyInto(out *Probe) { - *out = *in - out.Probe = in.Probe -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Probe. -func (in *Probe) DeepCopy() *Probe { - if in == nil { - return nil - } - out := new(Probe) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Redis) DeepCopyInto(out *Redis) { *out = *in @@ -473,13 +457,13 @@ func (in *RedisReplicationSpec) DeepCopyInto(out *RedisReplicationSpec) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.Sidecars != nil { in, out := &in.Sidecars, &out.Sidecars @@ -653,13 +637,13 @@ func (in *RedisSentinelSpec) DeepCopyInto(out *RedisSentinelSpec) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.Sidecars != nil { in, out := &in.Sidecars, &out.Sidecars @@ -758,13 +742,13 @@ func (in *RedisSpec) DeepCopyInto(out *RedisSpec) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.Sidecars != nil { in, out := &in.Sidecars, &out.Sidecars diff --git a/api/v1beta2/common_types.go b/api/v1beta2/common_types.go index 76a3adcd0..8de37a3ad 100644 --- a/api/v1beta2/common_types.go +++ b/api/v1beta2/common_types.go @@ -71,11 +71,6 @@ type ACLConfig struct { Secret *corev1.SecretVolumeSource `json:"secret,omitempty"` } -// Probe is a interface for ReadinessProbe and LivenessProbe -type Probe struct { - common.Probe `json:",inline"` -} - // Sidecar for each Redis pods type Sidecar struct { common.Sidecar `json:",inline"` diff --git a/api/v1beta2/redis_types.go b/api/v1beta2/redis_types.go index d6e56c775..fe33f5809 100644 --- a/api/v1beta2/redis_types.go +++ b/api/v1beta2/redis_types.go @@ -26,27 +26,25 @@ import ( // RedisSpec defines the desired state of Redis type RedisSpec struct { - KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` - RedisExporter *RedisExporter `json:"redisExporter,omitempty"` - RedisConfig *RedisConfig `json:"redisConfig,omitempty"` - Storage *Storage `json:"storage,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` - SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` - PriorityClassName string `json:"priorityClassName,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - TLS *TLSConfig `json:"TLS,omitempty"` - ACL *ACLConfig `json:"acl,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - InitContainer *InitContainer `json:"initContainer,omitempty"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` - EnvVars *[]corev1.EnvVar `json:"env,omitempty"` + KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` + RedisExporter *RedisExporter `json:"redisExporter,omitempty"` + RedisConfig *RedisConfig `json:"redisConfig,omitempty"` + Storage *Storage `json:"storage,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` + PriorityClassName string `json:"priorityClassName,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + TLS *TLSConfig `json:"TLS,omitempty"` + ACL *ACLConfig `json:"acl,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + InitContainer *InitContainer `json:"initContainer,omitempty"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } // RedisStatus defines the observed state of Redis diff --git a/api/v1beta2/rediscluster_types.go b/api/v1beta2/rediscluster_types.go index 31c188494..e49141d15 100644 --- a/api/v1beta2/rediscluster_types.go +++ b/api/v1beta2/rediscluster_types.go @@ -31,10 +31,8 @@ type RedisClusterSpec struct { // +kubebuilder:default:=6379 Port *int `json:"port,omitempty"` // +kubebuilder:default:=v7 - ClusterVersion *string `json:"clusterVersion,omitempty"` - // +kubebuilder:default:={livenessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}, readinessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}} - RedisLeader RedisLeader `json:"redisLeader,omitempty"` - // +kubebuilder:default:={livenessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}, readinessProbe:{initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3}} + ClusterVersion *string `json:"clusterVersion,omitempty"` + RedisLeader RedisLeader `json:"redisLeader,omitempty"` RedisFollower RedisFollower `json:"redisFollower,omitempty"` RedisExporter *RedisExporter `json:"redisExporter,omitempty"` Storage *ClusterStorage `json:"storage,omitempty"` diff --git a/api/v1beta2/redisreplication_types.go b/api/v1beta2/redisreplication_types.go index 90bf70796..92915e76c 100644 --- a/api/v1beta2/redisreplication_types.go +++ b/api/v1beta2/redisreplication_types.go @@ -6,28 +6,26 @@ import ( ) type RedisReplicationSpec struct { - Size *int32 `json:"clusterSize"` - KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` - RedisExporter *RedisExporter `json:"redisExporter,omitempty"` - RedisConfig *RedisConfig `json:"redisConfig,omitempty"` - Storage *Storage `json:"storage,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` - SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` - PriorityClassName string `json:"priorityClassName,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - TLS *TLSConfig `json:"TLS,omitempty"` - ACL *ACLConfig `json:"acl,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - InitContainer *InitContainer `json:"initContainer,omitempty"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` - EnvVars *[]corev1.EnvVar `json:"env,omitempty"` + Size *int32 `json:"clusterSize"` + KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` + RedisExporter *RedisExporter `json:"redisExporter,omitempty"` + RedisConfig *RedisConfig `json:"redisConfig,omitempty"` + Storage *Storage `json:"storage,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` + PriorityClassName string `json:"priorityClassName,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + TLS *TLSConfig `json:"TLS,omitempty"` + ACL *ACLConfig `json:"acl,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + InitContainer *InitContainer `json:"initContainer,omitempty"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } func (cr *RedisReplicationSpec) GetReplicationCounts(t string) int32 { diff --git a/api/v1beta2/redissentinel_types.go b/api/v1beta2/redissentinel_types.go index 8787ee96c..53837c04b 100644 --- a/api/v1beta2/redissentinel_types.go +++ b/api/v1beta2/redissentinel_types.go @@ -9,27 +9,25 @@ import ( type RedisSentinelSpec struct { // +kubebuilder:validation:Minimum=1 // +kubebuilder:default=3 - Size *int32 `json:"clusterSize"` - KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` - RedisExporter *RedisExporter `json:"redisExporter,omitempty"` - RedisSentinelConfig *RedisSentinelConfig `json:"redisSentinelConfig,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` - SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` - PriorityClassName string `json:"priorityClassName,omitempty"` - Affinity *corev1.Affinity `json:"affinity,omitempty"` - Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` - TLS *TLSConfig `json:"TLS,omitempty"` - PodDisruptionBudget *common.RedisPodDisruptionBudget `json:"pdb,omitempty"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - ReadinessProbe *Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` - // +kubebuilder:default:={initialDelaySeconds: 1, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold:3} - LivenessProbe *Probe `json:"livenessProbe,omitempty" protobuf:"bytes,11,opt,name=livenessProbe"` - InitContainer *InitContainer `json:"initContainer,omitempty"` - Sidecars *[]Sidecar `json:"sidecars,omitempty"` - ServiceAccountName *string `json:"serviceAccountName,omitempty"` - TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` - EnvVars *[]corev1.EnvVar `json:"env,omitempty"` + Size *int32 `json:"clusterSize"` + KubernetesConfig KubernetesConfig `json:"kubernetesConfig"` + RedisExporter *RedisExporter `json:"redisExporter,omitempty"` + RedisSentinelConfig *RedisSentinelConfig `json:"redisSentinelConfig,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` + PriorityClassName string `json:"priorityClassName,omitempty"` + Affinity *corev1.Affinity `json:"affinity,omitempty"` + Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"` + TLS *TLSConfig `json:"TLS,omitempty"` + PodDisruptionBudget *common.RedisPodDisruptionBudget `json:"pdb,omitempty"` + ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"` + LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,12,opt,name=livenessProbe"` + InitContainer *InitContainer `json:"initContainer,omitempty"` + Sidecars *[]Sidecar `json:"sidecars,omitempty"` + ServiceAccountName *string `json:"serviceAccountName,omitempty"` + TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` + EnvVars *[]corev1.EnvVar `json:"env,omitempty"` } func (cr *RedisSentinelSpec) GetSentinelCounts(t string) int32 { diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 6fc14b16b..2da35d19a 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -151,22 +151,6 @@ func (in *KubernetesConfig) DeepCopy() *KubernetesConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Probe) DeepCopyInto(out *Probe) { - *out = *in - out.Probe = in.Probe -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Probe. -func (in *Probe) DeepCopy() *Probe { - if in == nil { - return nil - } - out := new(Probe) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Redis) DeepCopyInto(out *Redis) { *out = *in @@ -612,13 +596,13 @@ func (in *RedisReplicationSpec) DeepCopyInto(out *RedisReplicationSpec) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.InitContainer != nil { in, out := &in.InitContainer, &out.InitContainer @@ -823,13 +807,13 @@ func (in *RedisSentinelSpec) DeepCopyInto(out *RedisSentinelSpec) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.InitContainer != nil { in, out := &in.InitContainer, &out.InitContainer @@ -959,13 +943,13 @@ func (in *RedisSpec) DeepCopyInto(out *RedisSpec) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.InitContainer != nil { in, out := &in.InitContainer, &out.InitContainer diff --git a/api/zz_generated.deepcopy.go b/api/zz_generated.deepcopy.go index 975b24a1b..2e3b3ae55 100644 --- a/api/zz_generated.deepcopy.go +++ b/api/zz_generated.deepcopy.go @@ -124,21 +124,6 @@ func (in *KubernetesConfig) DeepCopy() *KubernetesConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Probe) DeepCopyInto(out *Probe) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Probe. -func (in *Probe) DeepCopy() *Probe { - if in == nil { - return nil - } - out := new(Probe) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RedisConfig) DeepCopyInto(out *RedisConfig) { *out = *in @@ -220,13 +205,13 @@ func (in *RedisFollower) DeepCopyInto(out *RedisFollower) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.Tolerations != nil { in, out := &in.Tolerations, &out.Tolerations @@ -283,13 +268,13 @@ func (in *RedisLeader) DeepCopyInto(out *RedisLeader) { } if in.ReadinessProbe != nil { in, out := &in.ReadinessProbe, &out.ReadinessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.LivenessProbe != nil { in, out := &in.LivenessProbe, &out.LivenessProbe - *out = new(Probe) - **out = **in + *out = new(v1.Probe) + (*in).DeepCopyInto(*out) } if in.Tolerations != nil { in, out := &in.Tolerations, &out.Tolerations diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index f4c87f468..906382035 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -1226,38 +1226,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1267,38 +1376,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -5696,38 +5914,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -5906,38 +6233,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 025c80d57..8cd05c666 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -459,19 +459,6 @@ spec: - image type: object redisFollower: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisFollower interface will have the redis follower configuration properties: @@ -1497,38 +1484,153 @@ spec: type: object type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1549,38 +1651,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -1635,19 +1852,6 @@ spec: type: array type: object redisLeader: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisLeader interface will have the redis leader configuration properties: affinity: @@ -2672,38 +2876,153 @@ spec: type: object type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -2724,38 +3043,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -6449,19 +6883,6 @@ spec: - image type: object redisFollower: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisFollower interface will have the redis follower configuration properties: @@ -7487,38 +7908,153 @@ spec: type: object type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -7539,38 +8075,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -7797,19 +8448,6 @@ spec: type: array type: object redisLeader: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisLeader interface will have the redis leader configuration properties: affinity: @@ -8834,38 +9472,153 @@ spec: type: object type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -8886,38 +9639,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index eb09d428f..0c3f696b1 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -1228,38 +1228,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1269,38 +1378,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -5704,38 +5922,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -5914,38 +6241,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 6be2efd14..00eb3b94e 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -1229,38 +1229,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1283,38 +1392,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisSentinelConfig: @@ -3327,38 +3545,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -3550,38 +3877,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisExporter: diff --git a/docs/content/en/docs/CRD Reference/Redis API/_index.md b/docs/content/en/docs/CRD Reference/Redis API/_index.md index 31edce5d6..b639bb502 100644 --- a/docs/content/en/docs/CRD Reference/Redis API/_index.md +++ b/docs/content/en/docs/CRD Reference/Redis API/_index.md @@ -51,31 +51,11 @@ _Appears in:_ | Field | Description | | --- | --- | | `image` _string_ | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#pullpolicy-v1-core)_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#resourcerequirements-v1-core)_ | | +| `imagePullPolicy` _[ImagePullPolicy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy)_ | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | | `redisSecret` _[ExistingPasswordSecret](#existingpasswordsecret)_ | | -| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#localobjectreference-v1-core)_ | | -| `updateStrategy` _[StatefulSetUpdateStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#statefulsetupdatestrategy-v1-apps)_ | | - -#### Probe - -Probe is a interface for ReadinessProbe and LivenessProbe - -_Appears in:_ - -- [RedisFollower](#redisfollower) -- [RedisLeader](#redisleader) -- [RedisSpec](#redisspec) -- [RedisReplicationSpec](#redisreplicationspec) -- [RedisSentinel](#redissentinelspec) - -| Field | Description | -| --- | --- | -| `initialDelaySeconds` _integer_ | | -| `timeoutSeconds` _integer_ | | -| `periodSeconds` _integer_ | | -| `successThreshold` _integer_ | | -| `failureThreshold` _integer_ | | +| `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | +| `updateStrategy` _[StatefulSetUpdateStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#statefulsetupdatestrategy-v1-apps)_ | | #### Redis @@ -85,7 +65,7 @@ Redis is the Schema for the redis API | --- | --- | | `apiVersion` _string_ | `redis.redis.opstreelabs.in/v1beta1` | `kind` _string_ | `Redis` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | `spec` _[RedisSpec](#redisspec)_ | | #### RedisCluster @@ -96,7 +76,7 @@ RedisCluster is the Schema for the redisclusters API | --- | --- | | `apiVersion` _string_ | `redis.redis.opstreelabs.in/v1beta1` | `kind` _string_ | `RedisCluster` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | `spec` _[RedisClusterSpec](#redisclusterspec)_ | | #### RedisReplication @@ -107,7 +87,7 @@ RedisReplication is the Schema for the redisreplication API | --- | --- | | `apiVersion` _string_ | `redis.redis.opstreelabs.in/v1beta1` | `kind` _string_ | `RedisReplication` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | `spec` _[RedisReplicationSpec](#redisreplicationspec)_ | | #### RedisSentinel @@ -118,7 +98,7 @@ RedisSentinel is the Schema for the redissentinel API | --- | --- | | `apiVersion` _string_ | `redis.redis.opstreelabs.in/v1beta1` | `kind` _string_ | `RedisSentinel` -| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | `spec` _[RedisSentinelSpec](#redissentinelspec)_ | | #### RedisClusterSpec @@ -139,10 +119,10 @@ _Appears in:_ | `redisExporter` _[RedisExporter](#redisexporter)_ | | | `storage` _[Storage](#storage)_ | | | `nodeSelector` _object (keys:string, values:string)_ | | -| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core)_ | | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | | `priorityClassName` _string_ | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core)_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#resourcerequirements-v1-core)_ | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#toleration-v1-core)_ | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | | `TLS` _[TLSConfig](#tlsconfig)_ | | | `sidecars` _[Sidecar](#sidecar)_ | | | `serviceAccountName` _string_ | | @@ -163,13 +143,13 @@ _Appears in:_ | `redisConfig` _[RedisConfig](#redisconfig)_ | | | `storage` _[Storage](#storage)_ | | | `nodeSelector` _object (keys:string, values:string)_ | | -| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core)_ | | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | | `priorityClassName` _string_ | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core)_ | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core)_ | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#affinity-v1-core)_ | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#toleration-v1-core)_ | | | `TLS` _[TLSConfig](#tlsconfig)_ | | -| `readinessProbe` _[Probe](#probe)_ | | -| `livenessProbe` _[Probe](#probe)_ | | +| `readinessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | +| `livenessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | | `sidecars` _[Sidecar](#sidecar)_ | | | `serviceAccountName` _string_ | | @@ -189,13 +169,13 @@ _Appears in:_ | `redisConfig` _[RedisConfig](#redisconfig)_ | | | `storage` _[Storage](#storage)_ | | | `nodeSelector` _object (keys:string, values:string)_ | | -| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core)_ | | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | | `priorityClassName` _string_ | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core)_ | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core)_ | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#affinity-v1-core)_ | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#toleration-v1-core)_ | | | `TLS` _[TLSConfig](#tlsconfig)_ | | -| `readinessProbe` _[Probe](#probe)_ | | -| `livenessProbe` _[Probe](#probe)_ | | +| `readinessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | +| `livenessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | | `sidecars` _[Sidecar](#sidecar)_ | | | `serviceAccountName` _string_ | | @@ -213,13 +193,13 @@ _Appears in:_ | `kubernetesConfig` _[KubernetesConfig](#kubernetesconfig)_ | | | `redisSentinelConfig` _[RedisSentinelConfig](#redissentinelconfig)_ | | | `nodeSelector` _object (keys:string, values:string)_ | | -| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core)_ | | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | | `priorityClassName` _string_ | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core)_ | | -| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#toleration-v1-core)_ | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#affinity-v1-core)_ | | +| `tolerations` _[Toleration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#toleration-v1-core)_ | | | `TLS` _[TLSConfig](#tlsconfig)_ | | -| `readinessProbe` _[Probe](#probe)_ | | -| `livenessProbe` _[Probe](#probe)_ | | +| `readinessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | +| `livenessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | | `sidecars` _[Sidecar](#sidecar)_ | | | `serviceAccountName` _string_ | | @@ -270,9 +250,9 @@ _Appears in:_ | --- | --- | | `enabled` _boolean_ | | | `image` _string_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#resourcerequirements-v1-core)_ | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#pullpolicy-v1-core)_ | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#envvar-v1-core)_ | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | +| `imagePullPolicy` _[ImagePullPolicy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy)_ | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | #### RedisFollower @@ -286,10 +266,10 @@ _Appears in:_ | --- | --- | | `replicas` _integer_ | | | `redisConfig` _[RedisConfig](#redisconfig)_ | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core)_ | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#affinity-v1-core)_ | | | `pdb` _[RedisPodDisruptionBudget](#redispoddisruptionbudget)_ | | -| `readinessProbe` _[Probe](#probe)_ | | -| `livenessProbe` _[Probe](#probe)_ | | +| `readinessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | +| `livenessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | #### RedisLeader @@ -303,10 +283,10 @@ _Appears in:_ | --- | --- | | `replicas` _integer_ | | | `redisConfig` _[RedisConfig](#redisconfig)_ | | -| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#affinity-v1-core)_ | | +| `affinity` _[Affinity](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#affinity-v1-core)_ | | | `pdb` _[RedisPodDisruptionBudget](#redispoddisruptionbudget)_ | | -| `readinessProbe` _[Probe](#probe)_ | | -| `livenessProbe` _[Probe](#probe)_ | | +| `readinessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | +| `livenessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | #### RedisPodDisruptionBudget @@ -340,9 +320,9 @@ _Appears in:_ | --- | --- | | `name` _string_ | | | `image` _string_ | | -| `imagePullPolicy` _[PullPolicy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#pullpolicy-v1-core)_ | | -| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#resourcerequirements-v1-core)_ | | -| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#envvar-v1-core)_ | | +| `imagePullPolicy` _[ImagePullPolicy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy)_ | | +| `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | +| `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | #### Storage @@ -356,7 +336,7 @@ _Appears in:_ | Field | Description | | --- | --- | -| `volumeClaimTemplate` _[PersistentVolumeClaim](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#persistentvolumeclaim-v1-core)_ | | +| `volumeClaimTemplate` _[PersistentVolumeClaim](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#persistentvolumeclaim-v1-core)_ | | #### TLSConfig @@ -374,4 +354,4 @@ _Appears in:_ | `ca` _string_ | | | `cert` _string_ | | | `key` _string_ | | -| `secret` _[SecretVolumeSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#secretvolumesource-v1-core)_ | Reference to secret which contains the certificates | +| `secret` _[SecretVolumeSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#secretvolumesource-v1-core)_ | Reference to secret which contains the certificates | diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index d16b9308c..1934fa291 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -4,7 +4,6 @@ import ( "strconv" "strings" - commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "github.com/go-logr/logr" @@ -21,8 +20,8 @@ type RedisClusterSTS struct { SecurityContext *corev1.SecurityContext Affinity *corev1.Affinity `json:"affinity,omitempty"` TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` - ReadinessProbe *commonapi.Probe - LivenessProbe *commonapi.Probe + ReadinessProbe *corev1.Probe + LivenessProbe *corev1.Probe NodeSelector map[string]string Tolerations *[]corev1.Toleration } @@ -100,7 +99,7 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init } // generateRedisClusterContainerParams generates Redis container information -func generateRedisClusterContainerParams(cl kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, role string) containerParameters { +func generateRedisClusterContainerParams(cl kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, securityContext *corev1.SecurityContext, readinessProbeDef *corev1.Probe, livenessProbeDef *corev1.Probe, role string) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 9bef5a9eb..5bbfad818 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -154,10 +154,10 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) } } if cr.Spec.ReadinessProbe != nil { - containerProp.ReadinessProbe = &cr.Spec.ReadinessProbe.Probe + containerProp.ReadinessProbe = cr.Spec.ReadinessProbe } if cr.Spec.LivenessProbe != nil { - containerProp.LivenessProbe = &cr.Spec.LivenessProbe.Probe + containerProp.LivenessProbe = cr.Spec.LivenessProbe } if cr.Spec.Storage != nil { containerProp.PersistenceEnabled = &trueProperty diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 7b9eaeaa4..b905f495a 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" - commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "github.com/go-logr/logr" @@ -23,8 +22,8 @@ type RedisSentinelSTS struct { ExternalConfig *string Affinity *corev1.Affinity `json:"affinity,omitempty"` TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` - ReadinessProbe *commonapi.Probe - LivenessProbe *commonapi.Probe + ReadinessProbe *corev1.Probe + LivenessProbe *corev1.Probe } // RedisSentinelService is a interface to call Redis Service function @@ -41,8 +40,8 @@ func CreateRedisSentinel(ctx context.Context, client kubernetes.Interface, logge prop := RedisSentinelSTS{ RedisStateFulType: "sentinel", Affinity: cr.Spec.Affinity, - ReadinessProbe: &cr.Spec.ReadinessProbe.Probe, - LivenessProbe: &cr.Spec.LivenessProbe.Probe, + ReadinessProbe: cr.Spec.ReadinessProbe, + LivenessProbe: cr.Spec.LivenessProbe, TerminationGracePeriodSeconds: cr.Spec.TerminationGracePeriodSeconds, } @@ -139,7 +138,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in } // Create Redis Sentinel Statefulset Container Params -func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, readinessProbeDef *commonapi.Probe, livenessProbeDef *commonapi.Probe, dcl dynamic.Interface) containerParameters { +func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisSentinel, readinessProbeDef *corev1.Probe, livenessProbeDef *corev1.Probe, dcl dynamic.Interface) containerParameters { trueProperty := true falseProperty := false containerProp := containerParameters{ diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 7f76d191a..7a481ae95 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -152,10 +152,10 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar } } if cr.Spec.ReadinessProbe != nil { - containerProp.ReadinessProbe = &cr.Spec.ReadinessProbe.Probe + containerProp.ReadinessProbe = cr.Spec.ReadinessProbe } if cr.Spec.LivenessProbe != nil { - containerProp.LivenessProbe = &cr.Spec.LivenessProbe.Probe + containerProp.LivenessProbe = cr.Spec.LivenessProbe } if cr.Spec.Storage != nil { containerProp.PersistenceEnabled = &trueProperty diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 918b4d044..c654b8d52 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -8,7 +8,6 @@ import ( "strconv" "strings" - commonapi "github.com/OT-CONTAINER-KIT/redis-operator/api" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/pkg/util" "github.com/banzaicloud/k8s-objectmatcher/patch" @@ -71,8 +70,8 @@ type containerParameters struct { PersistenceEnabled *bool TLSConfig *redisv1beta2.TLSConfig ACLConfig *redisv1beta2.ACLConfig - ReadinessProbe *commonapi.Probe - LivenessProbe *commonapi.Probe + ReadinessProbe *corev1.Probe + LivenessProbe *corev1.Probe AdditionalEnvVariable *[]corev1.EnvVar AdditionalVolume []corev1.Volume AdditionalMountPath []corev1.VolumeMount @@ -596,35 +595,34 @@ func getVolumeMount(name string, persistenceEnabled *bool, clusterMode bool, nod } // getProbeInfo generate probe for Redis StatefulSet -func getProbeInfo(probe *commonapi.Probe, sentinel, enableTLS, enableAuth bool) *corev1.Probe { - healthChecker := []string{ - "redis-cli", - "-h", "$(hostname)", - } - if sentinel { - healthChecker = append(healthChecker, "-p", "${SENTINEL_PORT}") - } else { - healthChecker = append(healthChecker, "-p", "${REDIS_PORT}") - } - if enableAuth { - healthChecker = append(healthChecker, "-a", "${REDIS_PASSWORD}") - } - if enableTLS { - healthChecker = append(healthChecker, "--tls", "--cert", "${REDIS_TLS_CERT}", "--key", "${REDIS_TLS_CERT_KEY}", "--cacert", "${REDIS_TLS_CA_KEY}") - } - healthChecker = append(healthChecker, "ping") - return &corev1.Probe{ - InitialDelaySeconds: probe.InitialDelaySeconds, - PeriodSeconds: probe.PeriodSeconds, - FailureThreshold: probe.FailureThreshold, - TimeoutSeconds: probe.TimeoutSeconds, - SuccessThreshold: probe.SuccessThreshold, - ProbeHandler: corev1.ProbeHandler{ +func getProbeInfo(probe *corev1.Probe, sentinel, enableTLS, enableAuth bool) *corev1.Probe { + if probe == nil { + probe = &corev1.Probe{} + } + if probe.ProbeHandler.Exec == nil && probe.ProbeHandler.HTTPGet == nil && probe.ProbeHandler.TCPSocket == nil && probe.ProbeHandler.GRPC == nil { + healthChecker := []string{ + "redis-cli", + "-h", "$(hostname)", + } + if sentinel { + healthChecker = append(healthChecker, "-p", "${SENTINEL_PORT}") + } else { + healthChecker = append(healthChecker, "-p", "${REDIS_PORT}") + } + if enableAuth { + healthChecker = append(healthChecker, "-a", "${REDIS_PASSWORD}") + } + if enableTLS { + healthChecker = append(healthChecker, "--tls", "--cert", "${REDIS_TLS_CERT}", "--key", "${REDIS_TLS_CERT_KEY}", "--cacert", "${REDIS_TLS_CA_KEY}") + } + healthChecker = append(healthChecker, "ping") + probe.ProbeHandler = corev1.ProbeHandler{ Exec: &corev1.ExecAction{ Command: []string{"sh", "-c", strings.Join(healthChecker, " ")}, }, - }, + } } + return probe } // getEnvironmentVariables returns all the required Environment Variables From 52ed749d8bf83a3c279da450ce03268c0af5041c Mon Sep 17 00:00:00 2001 From: drivebyer Date: Thu, 30 May 2024 21:54:00 +0800 Subject: [PATCH 176/203] Release operator chart 0.15.11 --- charts/redis-operator/Chart.yaml | 4 ++-- charts/redis-operator/values.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/redis-operator/Chart.yaml b/charts/redis-operator/Chart.yaml index 0dda19878..bc60c3f2b 100644 --- a/charts/redis-operator/Chart.yaml +++ b/charts/redis-operator/Chart.yaml @@ -1,7 +1,7 @@ --- apiVersion: v2 -version: 0.15.9 -appVersion: "0.15.1" +version: 0.15.11 +appVersion: "0.17.0" description: Provides easy redis setup definitions for Kubernetes services, and deployment. engine: gotpl maintainers: diff --git a/charts/redis-operator/values.yaml b/charts/redis-operator/values.yaml index 5367b8f02..ba4da7f82 100644 --- a/charts/redis-operator/values.yaml +++ b/charts/redis-operator/values.yaml @@ -1,7 +1,7 @@ --- redisOperator: name: redis-operator - imageName: ghcr.io/ot-container-kit/redis-operator + imageName: ghcr.io/ot-container-kit/redis-operator/redis-operator # Overrides the image tag whose default is the chart appVersion. imageTag: "" imagePullPolicy: Always From df24341c84475d244f03ed7d5dea52a7d9c611ad Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 30 May 2024 22:12:52 +0800 Subject: [PATCH 177/203] ci: fix chart release yaml syntax (#957) * ci: fix chart release yaml syntax Signed-off-by: drivebyer * add path Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/publish-charts.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-charts.yaml b/.github/workflows/publish-charts.yaml index e86e50d43..267616d87 100644 --- a/.github/workflows/publish-charts.yaml +++ b/.github/workflows/publish-charts.yaml @@ -1,13 +1,10 @@ name: Release Charts -#on: -# push: -# tags: -# - "v*.*.*" on: push: paths: - 'charts/**' + - '.github/workflows/publish-charts.yaml' branches: - master @@ -42,8 +39,6 @@ jobs: shell: bash working-directory: redis-operator run: | -# VERSION=$(echo ${{ env.chart_version }} | cut -c 2-) -# sed -i "s/appVersion:.*/appVersion: \"$VERSION\"/g" charts/redis-operator/Chart.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm dependency update charts/redis-operator @@ -100,4 +95,4 @@ jobs: # owner CR_OWNER: "${{ github.repository_owner }}" # index path - CR_INDEX_PATH: "index.yaml" \ No newline at end of file + CR_INDEX_PATH: "index.yaml" From 64d376eba303e5489be82ae8f4c536fe39ad767e Mon Sep 17 00:00:00 2001 From: drivebyer Date: Thu, 30 May 2024 22:22:24 +0800 Subject: [PATCH 178/203] Release operator chart 0.16.1 --- charts/redis-operator/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/redis-operator/Chart.yaml b/charts/redis-operator/Chart.yaml index bc60c3f2b..2d3266f2f 100644 --- a/charts/redis-operator/Chart.yaml +++ b/charts/redis-operator/Chart.yaml @@ -1,6 +1,6 @@ --- apiVersion: v2 -version: 0.15.11 +version: 0.16.1 appVersion: "0.17.0" description: Provides easy redis setup definitions for Kubernetes services, and deployment. engine: gotpl From 55540256605c1d2f0a37e90dd282fc6f8ba15e6d Mon Sep 17 00:00:00 2001 From: yangw Date: Fri, 31 May 2024 10:05:19 +0800 Subject: [PATCH 179/203] ci: remove unuse kuttl test workflow (#958) Signed-off-by: drivebyer --- .github/workflows/e2e.yaml | 57 ------------------- tests/{readme.md => README.md} | 2 + tests/_config/kuttl-test.yaml | 14 ----- tests/e2e/v1beta1/setup/00-install.yaml | 5 -- tests/e2e/v1beta1/setup/cluster.yaml | 41 ------------- .../e2e/v1beta1/setup/ready-cluster-sts.yaml | 16 ------ tests/e2e/v1beta1/setup/ready-cluster.yaml | 8 --- 7 files changed, 2 insertions(+), 141 deletions(-) delete mode 100644 .github/workflows/e2e.yaml rename tests/{readme.md => README.md} (92%) delete mode 100644 tests/_config/kuttl-test.yaml delete mode 100644 tests/e2e/v1beta1/setup/00-install.yaml delete mode 100644 tests/e2e/v1beta1/setup/cluster.yaml delete mode 100644 tests/e2e/v1beta1/setup/ready-cluster-sts.yaml delete mode 100644 tests/e2e/v1beta1/setup/ready-cluster.yaml diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml deleted file mode 100644 index c5bfa34de..000000000 --- a/.github/workflows/e2e.yaml +++ /dev/null @@ -1,57 +0,0 @@ -name: E2E Kuttl tests - -on: - pull_request: - branches: - - master - push: - branches: - - master - -jobs: - test: - name: ${{ matrix.testpath }} - runs-on: ubuntu-latest - strategy: - matrix: - testpath: [] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Build Dockerfile - run: docker build . --file Dockerfile --tag redis-operator:e2e - - - name: Install kuttl - run: | - curl -L https://github.com/kudobuilder/kuttl/releases/download/v0.15.0/kubectl-kuttl_0.15.0_linux_x86_64 -o /usr/local/bin/kuttl - chmod +x /usr/local/bin/kuttl - - - name: Install kubectl - run: | - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x kubectl - sudo mv kubectl /usr/local/bin/ - - - name: Create k8s Kind Cluster - uses: helm/kind-action@v1.10.0 - with: - config: tests/_config/kind-config.yaml - cluster_name: kind - - - name: Load Docker image into Kind - run: | - kubectl cluster-info --context kind-kind - kind load docker-image redis-operator:e2e --name kind - - - name: Install Redis Operator - run: | - make deploy IMG=redis-operator:e2e - - - name: Wait for Redis Operator to be ready - run: | - kubectl wait --for=condition=available --timeout=300s deployment/redis-operator-redis-operator -n redis-operator-system - - - name: Run kuttl test - run: kuttl test ${{ matrix.testpath }} --config tests/_config/kuttl-test.yaml diff --git a/tests/readme.md b/tests/README.md similarity index 92% rename from tests/readme.md rename to tests/README.md index c4c91cd86..b17a0ce84 100644 --- a/tests/readme.md +++ b/tests/README.md @@ -1,5 +1,7 @@ # E2E Testing of the Redis Cluster with Kuttl +> ***Kuttl is depracated!*** now we use chainsaw to run e2e tests. Please refer to the [chainsaw](https://github.com/kyverno/chainsaw). + This guide will walk you through the process of end-to-end (E2E) testing a Redis cluster using the `kuttl` utility. ## **Prerequisites** diff --git a/tests/_config/kuttl-test.yaml b/tests/_config/kuttl-test.yaml deleted file mode 100644 index e64c01a54..000000000 --- a/tests/_config/kuttl-test.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestSuite -startKIND: false -kindConfig: ./kind-config.yaml -parallel: 1 -timeout: 1200 -testDirs: - - tests/e2e/v1beta2/setup - - tests/e2e/v1beta2/teardown - - tests/e2e/v1beta2/ignore-annots - - tests/e2e/v1beta2/scaling - - tests/e2e/v1beta2/hostnetwork -suppress: [events] diff --git a/tests/e2e/v1beta1/setup/00-install.yaml b/tests/e2e/v1beta1/setup/00-install.yaml deleted file mode 100644 index 05090155c..000000000 --- a/tests/e2e/v1beta1/setup/00-install.yaml +++ /dev/null @@ -1,5 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -apply: [cluster.yaml] -assert: [ready-cluster.yaml, ready-cluster-sts.yaml] diff --git a/tests/e2e/v1beta1/setup/cluster.yaml b/tests/e2e/v1beta1/setup/cluster.yaml deleted file mode 100644 index fe7a6119f..000000000 --- a/tests/e2e/v1beta1/setup/cluster.yaml +++ /dev/null @@ -1,41 +0,0 @@ ---- -apiVersion: redis.redis.opstreelabs.in/v1beta1 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta1 -spec: - clusterSize: 3 - clusterVersion: v7 - persistenceEnabled: true - securityContext: - runAsUser: 1000 - fsGroup: 1000 - kubernetesConfig: - image: quay.io/opstree/redis:v7.0.12 - imagePullPolicy: IfNotPresent - resources: - requests: - cpu: 101m - memory: 128Mi - limits: - cpu: 101m - memory: 128Mi - redisExporter: - enabled: true - image: quay.io/opstree/redis-exporter:v1.44.0 - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 128Mi - limits: - cpu: 100m - memory: 128Mi - storage: - volumeClaimTemplate: - spec: - # storageClassName: standard - accessModes: [ReadWriteOnce] - resources: - requests: - storage: 1Gi diff --git a/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml b/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml deleted file mode 100644 index 909597dc1..000000000 --- a/tests/e2e/v1beta1/setup/ready-cluster-sts.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta1-leader -status: - replicas: 3 - readyReplicas: 3 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis-cluster-v1beta1-follower -status: - replicas: 3 - readyReplicas: 3 diff --git a/tests/e2e/v1beta1/setup/ready-cluster.yaml b/tests/e2e/v1beta1/setup/ready-cluster.yaml deleted file mode 100644 index 88a19d87e..000000000 --- a/tests/e2e/v1beta1/setup/ready-cluster.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: redis.redis.opstreelabs.in/v1beta1 -kind: RedisCluster -metadata: - name: redis-cluster-v1beta1 -status: - readyFollowerReplicas: 3 - readyLeaderReplicas: 3 From 0fd0e42dd827663b0ed92f103508ac236c6bb96c Mon Sep 17 00:00:00 2001 From: yangw Date: Sun, 2 Jun 2024 23:24:42 +0800 Subject: [PATCH 180/203] refactor: remove duplicated tls code (#961) * remove dup log Signed-off-by: drivebyer * remove dup tsl replication code Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/redis.go | 62 ++++++++--------- k8sutils/secrets.go | 109 ++++++++---------------------- k8sutils/secrets_test.go | 140 +-------------------------------------- 3 files changed, 56 insertions(+), 255 deletions(-) diff --git a/k8sutils/redis.go b/k8sutils/redis.go index 1c9002dfc..368991483 100644 --- a/k8sutils/redis.go +++ b/k8sutils/redis.go @@ -371,28 +371,23 @@ func configureRedisClient(client kubernetes.Interface, logger logr.Logger, cr *r PodName: podName, Namespace: cr.Namespace, } - var redisClient *redis.Client - + var err error + var pass string if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err = getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } - redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerAddress(client, logger, redisInfo, *cr.Spec.Port), - Password: pass, - DB: 0, - TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), - }) - } else { - redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerAddress(client, logger, redisInfo, *cr.Spec.Port), - Password: "", - DB: 0, - TLSConfig: getRedisTLSConfig(client, logger, cr, redisInfo), - }) - } - return redisClient + } + opts := &redis.Options{ + Addr: getRedisServerAddress(client, logger, redisInfo, *cr.Spec.Port), + Password: pass, + DB: 0, + } + if cr.Spec.TLS != nil { + opts.TLSConfig = getRedisTLSConfig(client, logger, cr.Namespace, cr.Spec.TLS.Secret.SecretName, redisInfo.PodName) + } + return redis.NewClient(opts) } // executeCommand will execute the commands in pod @@ -498,28 +493,23 @@ func configureRedisReplicationClient(client kubernetes.Interface, logger logr.Lo PodName: podName, Namespace: cr.Namespace, } - var redisClient *redis.Client - + var err error + var pass string if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { - pass, err := getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) + pass, err = getRedisPassword(client, logger, cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key) if err != nil { logger.Error(err, "Error in getting redis password") } - redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerAddress(client, logger, redisInfo, 6379), - Password: pass, - DB: 0, - TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), - }) - } else { - redisClient = redis.NewClient(&redis.Options{ - Addr: getRedisServerAddress(client, logger, redisInfo, 6379), - Password: "", - DB: 0, - TLSConfig: getRedisReplicationTLSConfig(client, logger, cr, redisInfo), - }) - } - return redisClient + } + opts := &redis.Options{ + Addr: getRedisServerAddress(client, logger, redisInfo, 6379), + Password: pass, + DB: 0, + } + if cr.Spec.TLS != nil { + opts.TLSConfig = getRedisTLSConfig(client, logger, cr.Namespace, cr.Spec.TLS.Secret.SecretName, podName) + } + return redis.NewClient(opts) } // Get Redis nodes by it's role i.e. master, slave and sentinel diff --git a/k8sutils/secrets.go b/k8sutils/secrets.go index ab86a5960..91cc852c2 100644 --- a/k8sutils/secrets.go +++ b/k8sutils/secrets.go @@ -7,7 +7,6 @@ import ( "errors" "strings" - redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/go-logr/logr" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -33,90 +32,40 @@ func getRedisPassword(client kubernetes.Interface, logger logr.Logger, namespace return "", nil } -func getRedisTLSConfig(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisCluster, redisInfo RedisDetails) *tls.Config { - if cr.Spec.TLS != nil { - secret, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) - if err != nil { - logger.Error(err, "Failed in getting TLS secret for redis cluster") - logger.V(1).Error(err, "Failed in getting TLS secret for redis cluster", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisClusterName", cr.Name) - return nil - } - - tlsClientCert, certExists := secret.Data["tls.crt"] - tlsClientKey, keyExists := secret.Data["tls.key"] - tlsCaCertificate, caExists := secret.Data["ca.crt"] - - if !certExists || !keyExists || !caExists { - logger.Error(errors.New("required TLS keys are missing in the secret"), "Missing TLS keys in the secret") - return nil - } - - cert, err := tls.X509KeyPair(tlsClientCert, tlsClientKey) - if err != nil { - logger.Error(err, "Couldn't load TLS client key pair") - logger.V(1).Error(err, "Couldn't load TLS client key pair", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisClusterName", cr.Name) - return nil - } - - tlsCaCertificates := x509.NewCertPool() - ok := tlsCaCertificates.AppendCertsFromPEM(tlsCaCertificate) - if !ok { - logger.Error(errors.New("failed to load CA Certificates from secret"), "Invalid CA Certificates") - logger.V(1).Error(err, "Invalid CA Certificates", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisClusterName", cr.Name) - return nil - } - - return &tls.Config{ - Certificates: []tls.Certificate{cert}, - ServerName: redisInfo.PodName, - RootCAs: tlsCaCertificates, - MinVersion: tls.VersionTLS12, - ClientAuth: tls.NoClientCert, - } +func getRedisTLSConfig(client kubernetes.Interface, logger logr.Logger, namespace, tlsSecretName, podName string) *tls.Config { + secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), tlsSecretName, metav1.GetOptions{}) + if err != nil { + logger.V(1).Error(err, "Failed in getting TLS secret", "secretName", tlsSecretName, "namespace", namespace) + return nil } - return nil -} - -func getRedisReplicationTLSConfig(client kubernetes.Interface, logger logr.Logger, cr *redisv1beta2.RedisReplication, redisInfo RedisDetails) *tls.Config { - if cr.Spec.TLS != nil { - secret, err := client.CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.Spec.TLS.Secret.SecretName, metav1.GetOptions{}) - if err != nil { - logger.Error(err, "Failed in getting TLS secret for redis replication") - logger.V(1).Error(err, "Failed in getting TLS secret for redis replication", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisReplicationName", cr.Name) - return nil - } - tlsClientCert, certExists := secret.Data["tls.crt"] - tlsClientKey, keyExists := secret.Data["tls.key"] - tlsCaCertificate, caExists := secret.Data["ca.crt"] + tlsClientCert, certExists := secret.Data["tls.crt"] + tlsClientKey, keyExists := secret.Data["tls.key"] + tlsCaCertificate, caExists := secret.Data["ca.crt"] - if !certExists || !keyExists || !caExists { - logger.Error(errors.New("required TLS keys are missing in the secret"), "Missing TLS keys in the secret") - return nil - } + if !certExists || !keyExists || !caExists { + logger.Error(errors.New("required TLS keys are missing in the secret"), "Missing TLS keys in the secret") + return nil + } - cert, err := tls.X509KeyPair(tlsClientCert, tlsClientKey) - if err != nil { - logger.Error(err, "Couldn't load TLS client key pair") - logger.V(1).Error(err, "Couldn't load TLS client key pair", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisReplicationName", cr.Name) - return nil - } + cert, err := tls.X509KeyPair(tlsClientCert, tlsClientKey) + if err != nil { + logger.V(1).Error(err, "Couldn't load TLS client key pair", "secretName", tlsSecretName, "namespace", namespace) + return nil + } - tlsCaCertificates := x509.NewCertPool() - ok := tlsCaCertificates.AppendCertsFromPEM(tlsCaCertificate) - if !ok { - logger.Error(errors.New("failed to load CA Certificates from secret"), "Invalid CA Certificates") - logger.V(1).Error(err, "Invalid CA Certificates", "secretName", cr.Spec.TLS.Secret.SecretName, "namespace", cr.Namespace, "redisReplicationName", cr.Name) - return nil - } + tlsCaCertificates := x509.NewCertPool() + ok := tlsCaCertificates.AppendCertsFromPEM(tlsCaCertificate) + if !ok { + logger.V(1).Error(err, "Invalid CA Certificates", "secretName", tlsSecretName, "namespace", namespace) + return nil + } - return &tls.Config{ - Certificates: []tls.Certificate{cert}, - ServerName: redisInfo.PodName, - RootCAs: tlsCaCertificates, - MinVersion: tls.VersionTLS12, - ClientAuth: tls.NoClientCert, - } + return &tls.Config{ + Certificates: []tls.Certificate{cert}, + ServerName: podName, + RootCAs: tlsCaCertificates, + MinVersion: tls.VersionTLS12, + ClientAuth: tls.NoClientCert, } - return nil } diff --git a/k8sutils/secrets_test.go b/k8sutils/secrets_test.go index e8ae83fe3..754bcb036 100644 --- a/k8sutils/secrets_test.go +++ b/k8sutils/secrets_test.go @@ -222,145 +222,7 @@ func Test_getRedisTLSConfig(t *testing.T) { t.Run(tt.name, func(t *testing.T) { client := tt.setup() logger := testr.New(t) - tlsConfig := getRedisTLSConfig(client, logger, tt.redisCluster, tt.redisInfo) - - if tt.expectTLS { - require.NotNil(t, tlsConfig, "Expected TLS configuration but got nil") - require.NotEmpty(t, tlsConfig.Certificates, "TLS Certificates should not be empty") - require.NotNil(t, tlsConfig.RootCAs, "Root CAs should not be nil") - } else { - assert.Nil(t, tlsConfig, "Expected no TLS configuration but got one") - } - }) - } -} - -func Test_getRedisReplicationTLSConfig(t *testing.T) { - tests := []struct { - name string - setup func() *k8sClientFake.Clientset - redisReplication *redisv1beta2.RedisReplication - redisInfo RedisDetails - expectTLS bool - }{ - { - name: "TLS enabled and successful configuration", - setup: func() *k8sClientFake.Clientset { - tlsSecret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-tls-secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "ca.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "ca.crt")), - "tls.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "tls.crt")), - "tls.key": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "tls.key")), - }, - } - client := k8sClientFake.NewSimpleClientset(tlsSecret) - return client - }, - redisReplication: &redisv1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - }, - Spec: redisv1beta2.RedisReplicationSpec{ - TLS: &redisv1beta2.TLSConfig{ - TLSConfig: common.TLSConfig{ - CaKeyFile: "ca.crt", - CertKeyFile: "tls.crt", - KeyFile: "tls.key", - Secret: corev1.SecretVolumeSource{ - SecretName: "redis-tls-secret", - }, - }, - }, - }, - }, - redisInfo: RedisDetails{ - PodName: "redis-pod", - Namespace: "default", - }, - expectTLS: true, - }, - { - name: "TLS enabled but secret not found", - setup: func() *k8sClientFake.Clientset { - client := k8sClientFake.NewSimpleClientset() - return client - }, - redisReplication: &redisv1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - }, - Spec: redisv1beta2.RedisReplicationSpec{ - TLS: &redisv1beta2.TLSConfig{ - TLSConfig: common.TLSConfig{ - CaKeyFile: "ca.crt", - CertKeyFile: "tls.crt", - KeyFile: "tls.key", - Secret: corev1.SecretVolumeSource{ - SecretName: "redis-tls-secret", - }, - }, - }, - }, - }, - redisInfo: RedisDetails{ - PodName: "redis-pod", - Namespace: "default", - }, - expectTLS: false, - }, - { - name: "TLS enabled but incomplete secret", - setup: func() *k8sClientFake.Clientset { - tlsSecret := &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-tls-secret", - Namespace: "default", - }, - Data: map[string][]byte{ - "ca.crt": helperReadFile(filepath.Join("..", "tests", "testdata", "secrets", "ca.crt")), - // Missing tls.crt and tls.key - }, - } - client := k8sClientFake.NewSimpleClientset(tlsSecret) - return client - }, - redisReplication: &redisv1beta2.RedisReplication{ - ObjectMeta: metav1.ObjectMeta{ - Name: "redis-cluster", - Namespace: "default", - }, - Spec: redisv1beta2.RedisReplicationSpec{ - TLS: &redisv1beta2.TLSConfig{ - TLSConfig: common.TLSConfig{ - CaKeyFile: "ca.crt", - CertKeyFile: "tls.crt", - KeyFile: "tls.key", - Secret: corev1.SecretVolumeSource{ - SecretName: "redis-tls-secret", - }, - }, - }, - }, - }, - redisInfo: RedisDetails{ - PodName: "redis-pod", - Namespace: "default", - }, - expectTLS: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - client := tt.setup() - logger := testr.New(t) - tlsConfig := getRedisReplicationTLSConfig(client, logger, tt.redisReplication, tt.redisInfo) + tlsConfig := getRedisTLSConfig(client, logger, tt.redisCluster.Namespace, tt.redisCluster.Spec.TLS.Secret.SecretName, tt.redisInfo.PodName) if tt.expectTLS { require.NotNil(t, tlsConfig, "Expected TLS configuration but got nil") From a207422faccca8773b705e7e69b3db545e457bfe Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Mon, 3 Jun 2024 17:19:19 +0530 Subject: [PATCH 181/203] test: cover generateContainerDef (#962) Signed-off-by: Mahesh Kumar --- k8sutils/statefulset_test.go | 233 +++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 7b0e57d97..d70df53ca 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -12,6 +12,7 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" k8sClientFake "k8s.io/client-go/kubernetes/fake" @@ -452,6 +453,238 @@ func TestEnableRedisMonitoring(t *testing.T) { } } +func TestGenerateContainerDef(t *testing.T) { + tests := []struct { + name string + containerName string + containerDef containerParameters + expectedContainerDef []corev1.Container + redisClusterMode bool + containerNodeConfVolume bool + containerEnableMetrics bool + containerExternalConfig *string + redisClusterVersion *string + containerMountPaths []corev1.VolumeMount + sideCareContainer []redisv1beta2.Sidecar + }{ + { + name: "redis-1", + containerName: "redis", + containerDef: containerParameters{ + Image: "redis:latest", + ImagePullPolicy: corev1.PullAlways, + EnabledPassword: ptr.To(false), + PersistenceEnabled: ptr.To(false), + AdditionalEnvVariable: &[]corev1.EnvVar{ + { + Name: "Add_ENV", + Value: "Add_Value", + }, + }, + }, + expectedContainerDef: []corev1.Container{ + { + Name: "redis", + Image: "redis:latest", + ImagePullPolicy: corev1.PullAlways, + VolumeMounts: getVolumeMount("redisVolume", ptr.To(false), false, false, nil, []corev1.VolumeMount{}, nil, nil), + // Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Env: []corev1.EnvVar{ + { + Name: "REDIS_ADDR", + Value: "redis://localhost:6379", + }, + { + Name: "REDIS_MAJOR_VERSION", + Value: "1.0", + }, + { + Name: "SERVER_MODE", + Value: "", + }, + { + Name: "SETUP_MODE", + Value: "", + }, + { + Name: "Add_ENV", + Value: "Add_Value", + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + }, + }, + redisClusterMode: false, + containerNodeConfVolume: false, + containerEnableMetrics: false, + containerExternalConfig: nil, + redisClusterVersion: ptr.To("1.0"), + containerMountPaths: []corev1.VolumeMount{}, + sideCareContainer: []redisv1beta2.Sidecar{}, + }, + { + name: "redis-2", + containerName: "redis", + containerDef: containerParameters{ + Image: "redis:latest", + ImagePullPolicy: corev1.PullAlways, + EnabledPassword: ptr.To(false), + PersistenceEnabled: ptr.To(false), + Resources: &corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + }, + expectedContainerDef: []corev1.Container{ + { + Name: "redis", + Image: "redis:latest", + ImagePullPolicy: corev1.PullAlways, + VolumeMounts: getVolumeMount("redisVolume", ptr.To(false), false, false, nil, []corev1.VolumeMount{ + { + Name: "external-config", + ReadOnly: false, + MountPath: "/etc/redis/external.conf.d", + }, + }, nil, nil), + // Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Env: []corev1.EnvVar{ + { + Name: "REDIS_ADDR", + Value: "redis://localhost:6379", + }, + { + Name: "REDIS_MAJOR_VERSION", + Value: "1.0", + }, + { + Name: "SERVER_MODE", + Value: "", + }, + { + Name: "SETUP_MODE", + Value: "", + }, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + }, + { + Name: "redis-exporter", + Ports: []corev1.ContainerPort{ + { + Name: "redis-exporter", + ContainerPort: 9121, + Protocol: corev1.ProtocolTCP, + }, + }, + }, + { + Name: "redis-sidecare", + Image: "redis-sidecar:latest", + ImagePullPolicy: corev1.PullAlways, + Env: []corev1.EnvVar{ + { + Name: "REDISEXPORTER", + Value: "ENVVALUE", + }, + }, + Resources: corev1.ResourceRequirements{}, + VolumeMounts: []corev1.VolumeMount{}, + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Ports: []corev1.ContainerPort{ + { + Name: "redis-sidecare", + ContainerPort: 7000, + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + redisClusterMode: false, + containerNodeConfVolume: false, + containerEnableMetrics: true, + containerExternalConfig: ptr.To("some-config"), + redisClusterVersion: ptr.To("1.0"), + containerMountPaths: []corev1.VolumeMount{}, + sideCareContainer: []redisv1beta2.Sidecar{ + { + Sidecar: common.Sidecar{ + Name: "redis-sidecare", + Image: "redis-sidecar:latest", + ImagePullPolicy: corev1.PullAlways, + EnvVars: &[]corev1.EnvVar{ + { + Name: "REDISEXPORTER", + Value: "ENVVALUE", + }, + }, + Resources: &corev1.ResourceRequirements{}, + }, + Volumes: &[]corev1.VolumeMount{}, + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + Ports: &[]corev1.ContainerPort{ + { + Name: "redis-sidecare", + ContainerPort: 7000, + Protocol: corev1.ProtocolTCP, + }, + }, + }, + }, + }, + } + + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + containerDef := generateContainerDef(test.containerName, test.containerDef, test.redisClusterMode, test.containerNodeConfVolume, test.containerEnableMetrics, test.containerExternalConfig, test.redisClusterVersion, test.containerMountPaths, test.sideCareContainer) + assert.Equal(t, containerDef, test.expectedContainerDef, "Container Configration") + }) + } +} + func TestGenerateInitContainerDef(t *testing.T) { tests := []struct { name string From ba8dfa43491532d0eed0f6458ed9901bf86c6340 Mon Sep 17 00:00:00 2001 From: yangw Date: Tue, 4 Jun 2024 22:51:16 +0800 Subject: [PATCH 182/203] fix: sentinel should not reconcile until replication cluster ready (#964) * fix: sentinel should not reconcile until replication cluster ready Signed-off-by: drivebyer * check master attached slave Signed-off-by: drivebyer * increase waiting Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- controllers/redissentinel_controller.go | 16 ++------- k8sutils/redis-replication.go | 6 ++++ k8sutils/redis-sentinel.go | 33 +++++++++---------- .../v1beta2/ha-failover/chainsaw-test.yaml | 11 ++----- 4 files changed, 25 insertions(+), 41 deletions(-) diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index d660e1c12..8d3f50c28 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -11,11 +11,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/util/workqueue" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/handler" ) // RedisSentinelReconciler reconciles a RedisSentinel object @@ -80,22 +77,13 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } - reqLogger.Info("Will reconcile after 600 seconds") - return ctrl.Result{RequeueAfter: time.Second * 600}, nil + reqLogger.Info("Will reconcile after 10 seconds") + return ctrl.Result{RequeueAfter: time.Second * 10}, nil } // SetupWithManager sets up the controller with the Manager. func (r *RedisSentinelReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&redisv1beta2.RedisSentinel{}). - Watches(&redisv1beta2.RedisReplication{}, &handler.Funcs{ - CreateFunc: nil, - UpdateFunc: func(ctx context.Context, event event.UpdateEvent, limitingInterface workqueue.RateLimitingInterface) { - _ = event.ObjectNew.GetName() - _ = event.ObjectNew.GetNamespace() - }, - DeleteFunc: nil, - GenericFunc: nil, - }). Complete(r) } diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 5bbfad818..1d1c1d14c 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -210,6 +210,12 @@ func IsRedisReplicationReady(ctx context.Context, logger logr.Logger, client kub if sts.Status.ReadyReplicas != *sts.Spec.Replicas { return false } + if sts.Status.ObservedGeneration != sts.Generation { + return false + } + if sts.Status.UpdateRevision != sts.Status.CurrentRevision { + return false + } // Enhanced check: When the pod is ready, it may not have been // created as part of a replication cluster, so we should verify // whether there is an actual master node. diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index b905f495a..e76a7837f 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -316,30 +316,27 @@ func getRedisReplicationMasterIP(ctx context.Context, client kubernetes.Interfac } masterPods := GetRedisNodesByRole(ctx, client, logger, &replicationInstance, "master") - if len(masterPods) == 0 { - realMasterPod = "" - err := errors.New("no master pods found") - logger.Error(err, "") - } else if len(masterPods) == 1 { - realMasterPod = masterPods[0] - } else { - for _, podName := range masterPods { - redisClient := configureRedisReplicationClient(client, logger, &replicationInstance, podName) - defer redisClient.Close() - - if checkAttachedSlave(ctx, redisClient, logger, podName) > 0 { - realMasterPod = podName - break - } + logger.Error(errors.New("no master pods found"), "") + return "" + } + for _, podName := range masterPods { + redisClient := configureRedisReplicationClient(client, logger, &replicationInstance, podName) + defer redisClient.Close() + + if checkAttachedSlave(ctx, redisClient, logger, podName) > 0 { + realMasterPod = podName + break } } + if realMasterPod == "" { + logger.Error(errors.New("no real master pod found"), "") + return "" + } realMasterInfo := RedisDetails{ PodName: realMasterPod, Namespace: replicationNamespace, } - - realMasterPodIP := getRedisServerIP(client, logger, realMasterInfo) - return realMasterPodIP + return getRedisServerIP(client, logger, realMasterInfo) } diff --git a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml index 43b3f04ee..7f36a7e1c 100644 --- a/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml +++ b/tests/e2e-chainsaw/v1beta2/ha-failover/chainsaw-test.yaml @@ -50,18 +50,11 @@ spec: timeout: 10s content: | kubectl --namespace ${NAMESPACE} delete pod redis-replication-0 - catch: - - description: Redis Operator Logs - podLogs: - namespace: redis-operator-system - selector: control-plane=redis-operator - container: manager - tail: -1 # tail all logs - - name: Sleep for 3 minutes + - name: Sleep for 5 minutes try: - sleep: - duration: 3m + duration: 5m - name: Test sentinel monitoring try: From 96a5ccf86c105fb65ce2fd3a1db1d971cf3fe3b7 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Wed, 5 Jun 2024 07:32:28 +0530 Subject: [PATCH 183/203] test: generateInitContainerDef added additional env and resources (#963) * test: cover generateInitContainerDef Signed-off-by: Mahesh Kumar * test: generateInitContainerDef added additional env and resources Signed-off-by: Mahesh Kumar --------- Signed-off-by: Mahesh Kumar --- k8sutils/statefulset_test.go | 48 +++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index d70df53ca..3ea826556 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -688,31 +689,66 @@ func TestGenerateContainerDef(t *testing.T) { func TestGenerateInitContainerDef(t *testing.T) { tests := []struct { name string + initContainerName string initContainerDef initContainerParameters expectedInitContainerDef []corev1.Container mountPaths []corev1.VolumeMount }{ { - name: "Redis", + name: "Test1_With_Resources_AdditionalENV", + initContainerName: "redis", initContainerDef: initContainerParameters{ Image: "redis-init-container:latest", ImagePullPolicy: corev1.PullAlways, Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, PersistenceEnabled: ptr.To(false), + Resources: &corev1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("220m"), + v1.ResourceMemory: resource.MustParse("500Mi"), + }, + Limits: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("250m"), + v1.ResourceMemory: resource.MustParse("500Mi"), + }, + }, + AdditionalEnvVariable: &[]v1.EnvVar{ + { + Name: "TLS_MODE", + Value: "true", + }, + }, }, expectedInitContainerDef: []corev1.Container{ { - Name: "initRedis", + Name: "initredis", Image: "redis-init-container:latest", Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, ImagePullPolicy: corev1.PullAlways, VolumeMounts: getVolumeMount("redisVolume", ptr.To(false), false, false, nil, []corev1.VolumeMount{}, nil, nil), + Resources: corev1.ResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("220m"), + v1.ResourceMemory: resource.MustParse("500Mi"), + }, + Limits: v1.ResourceList{ + v1.ResourceCPU: resource.MustParse("250m"), + v1.ResourceMemory: resource.MustParse("500Mi"), + }, + }, + Env: []v1.EnvVar{ + { + Name: "TLS_MODE", + Value: "true", + }, + }, }, }, mountPaths: []corev1.VolumeMount{}, }, { - name: "Redis-1", + name: "Test2_With_Volume", + initContainerName: "redis", initContainerDef: initContainerParameters{ Image: "redis-init-container:latest", ImagePullPolicy: corev1.PullAlways, @@ -721,11 +757,11 @@ func TestGenerateInitContainerDef(t *testing.T) { }, expectedInitContainerDef: []corev1.Container{ { - Name: "initRedis-1", + Name: "initredis", Image: "redis-init-container:latest", Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, ImagePullPolicy: corev1.PullAlways, - VolumeMounts: getVolumeMount("Redis-1", ptr.To(true), false, false, nil, []corev1.VolumeMount{ + VolumeMounts: getVolumeMount("redis", ptr.To(true), false, false, nil, []corev1.VolumeMount{ { Name: "Redis-1", MountPath: "/data", @@ -745,7 +781,7 @@ func TestGenerateInitContainerDef(t *testing.T) { for i := range tests { test := tests[i] t.Run(test.name, func(t *testing.T) { - initContainer := generateInitContainerDef(test.name, test.initContainerDef, test.mountPaths) + initContainer := generateInitContainerDef(test.initContainerName, test.initContainerDef, test.mountPaths) assert.Equal(t, initContainer, test.expectedInitContainerDef, "Init Container Configuration") }) } From 92ac24faffcd1f083dc2e2c1339469a7ab766ee8 Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 5 Jun 2024 14:24:15 +0800 Subject: [PATCH 184/203] feat: rolling update sequence from leader to follower (#966) * feat: rolling update sequence from leader to follower Signed-off-by: drivebyer * fix Signed-off-by: drivebyer * add suffix Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer * fix lint Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .github/workflows/publish-image.yaml | 4 +- controllers/rediscluster_controller.go | 11 ++- controllers/suite_test.go | 12 ++- k8sutils/statefulset.go | 54 ++++++++++ main.go | 12 ++- .../redis-cluster/chainsaw-test.yaml | 98 +++++++++++++++++++ .../redis-cluster/cluster-hscale.yaml | 36 +++++++ .../redis-cluster/cluster.yaml | 36 +++++++ .../redis-cluster/ready-cluster.yaml | 10 ++ 9 files changed, 257 insertions(+), 16 deletions(-) create mode 100644 tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/chainsaw-test.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster-hscale.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster.yaml create mode 100644 tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/ready-cluster.yaml diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml index 03f269996..f4b1c37fc 100644 --- a/.github/workflows/publish-image.yaml +++ b/.github/workflows/publish-image.yaml @@ -40,6 +40,6 @@ jobs: file: Dockerfile push: true tags: | - ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:${{ env.TAG }} - ${{ env.REGISTRY }}/${{ env.REPOSITORY }}:latest + ${{ env.REGISTRY }}/${{ env.REPOSITORY }}/redis-operator:${{ env.TAG }} + ${{ env.REGISTRY }}/${{ env.REPOSITORY }}/redis-operator:latest platforms: linux/amd64,linux/arm64 \ No newline at end of file diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index fc280c916..f385b978a 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -36,6 +36,7 @@ import ( // RedisClusterReconciler reconciles a RedisCluster object type RedisClusterReconciler struct { client.Client + k8sutils.StatefulSet K8sClient kubernetes.Interface Dk8sClient dynamic.Interface Log logr.Logger @@ -125,6 +126,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } + // todo: remove me after watch statefulset in controller redisLeaderInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-leader") if err != nil { if errors.IsNotFound(err) { @@ -133,7 +135,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } - if redisLeaderInfo.Status.ReadyReplicas == leaderReplicas { + if r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") { // Mark the cluster status as initializing if there are no follower nodes if (instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0) || instance.Status.ReadyFollowerReplicas != followerReplicas { @@ -158,6 +160,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{}, err } } + // todo: remove me after watch statefulset in controller redisFollowerInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-follower") if err != nil { if errors.IsNotFound(err) { @@ -171,9 +174,9 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return ctrl.Result{RequeueAfter: time.Second * 60}, nil } - if !(redisLeaderInfo.Status.ReadyReplicas == leaderReplicas && redisFollowerInfo.Status.ReadyReplicas == followerReplicas) { - reqLogger.Info("Redis leader and follower nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + if !(r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") && r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-follower")) { + reqLogger.Info("Redis leader and follower nodes are not ready yet") + return ctrl.Result{RequeueAfter: time.Second * 30}, nil } // Mark the cluster status as bootstrapping if all the leader and follower nodes are ready diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 970eaf24d..e6039fde5 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -21,8 +21,8 @@ import ( "testing" "time" - // redisv1beta1 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta1" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" + "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" @@ -101,11 +101,13 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + rrLog := ctrl.Log.WithName("controllers").WithName("RedisReplication") err = (&RedisClusterReconciler{ - Client: k8sManager.GetClient(), - K8sClient: k8sClient, - Dk8sClient: dk8sClient, - Scheme: k8sManager.GetScheme(), + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Dk8sClient: dk8sClient, + Scheme: k8sManager.GetScheme(), + StatefulSet: k8sutils.NewStatefulSetService(k8sClient, rrLog), }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index c654b8d52..2a0a5c675 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -24,6 +24,60 @@ import ( "k8s.io/utils/ptr" ) +type StatefulSet interface { + IsStatefulSetReady(ctx context.Context, namespace, name string) bool +} + +type StatefulSetService struct { + kubeClient kubernetes.Interface + log logr.Logger +} + +func NewStatefulSetService(kubeClient kubernetes.Interface, log logr.Logger) *StatefulSetService { + log = log.WithValues("service", "k8s.statefulset") + return &StatefulSetService{ + kubeClient: kubeClient, + log: log, + } +} + +func (s *StatefulSetService) IsStatefulSetReady(ctx context.Context, namespace, name string) bool { + var ( + partition = 0 + replicas = 1 + + logger = s.log.WithValues("namespace", namespace, "name", name) + ) + + sts, err := s.kubeClient.AppsV1().StatefulSets(namespace).Get(ctx, name, metav1.GetOptions{}) + if err != nil { + logger.Error(err, "failed to get statefulset") + return false + } + + if sts.Spec.UpdateStrategy.RollingUpdate != nil && sts.Spec.UpdateStrategy.RollingUpdate.Partition != nil { + partition = int(*sts.Spec.UpdateStrategy.RollingUpdate.Partition) + } + if sts.Spec.Replicas != nil { + replicas = int(*sts.Spec.Replicas) + } + + if expectedUpdateReplicas := replicas - partition; sts.Status.UpdatedReplicas < int32(expectedUpdateReplicas) { + logger.V(1).Info("StatefulSet is not ready", "Status.UpdatedReplicas", sts.Status.UpdatedReplicas, "ExpectedUpdateReplicas", expectedUpdateReplicas) + return false + } + if partition == 0 && sts.Status.CurrentRevision != sts.Status.UpdateRevision { + logger.V(1).Info("StatefulSet is not ready", "Status.CurrentRevision", sts.Status.CurrentRevision, "Status.UpdateRevision", sts.Status.UpdateRevision) + return false + } + if sts.Status.ObservedGeneration != sts.ObjectMeta.Generation { + logger.V(1).Info("StatefulSet is not ready", "Status.ObservedGeneration", sts.Status.ObservedGeneration, "ObjectMeta.Generation", sts.ObjectMeta.Generation) + return false + } + + return true +} + const ( redisExporterContainer = "redis-exporter" ) diff --git a/main.go b/main.go index a45dfd53a..556b169ad 100644 --- a/main.go +++ b/main.go @@ -124,12 +124,14 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "Redis") os.Exit(1) } + rcLog := ctrl.Log.WithName("controllers").WithName("RedisCluster") if err = (&controllers.RedisClusterReconciler{ - Client: mgr.GetClient(), - K8sClient: k8sclient, - Dk8sClient: dk8sClient, - Log: ctrl.Log.WithName("controllers").WithName("RedisCluster"), - Scheme: mgr.GetScheme(), + Client: mgr.GetClient(), + K8sClient: k8sclient, + Dk8sClient: dk8sClient, + Log: rcLog, + Scheme: mgr.GetScheme(), + StatefulSet: k8sutils.NewStatefulSetService(k8sclient, rcLog), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "RedisCluster") os.Exit(1) diff --git a/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/chainsaw-test.yaml b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/chainsaw-test.yaml new file mode 100644 index 000000000..902751e45 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/chainsaw-test.yaml @@ -0,0 +1,98 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: redis-cluster +spec: + steps: + - try: + - apply: + file: cluster.yaml + - assert: + file: ready-cluster.yaml + + - name: Try saving a key + try: + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 set foo-0 bar-0 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 set foo-1 bar-1 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 set foo-2 bar-2 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 set foo-3 bar-3 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 set foo-4 bar-4 + check: + ($stdout=='OK'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 set foo-5 bar-5 + check: + ($stdout=='OK'): true + + - name: Rolling update the cluster + try: + - apply: + file: cluster-hscale.yaml + - assert: + file: ready-cluster.yaml + + - name: Check if all keys exist + try: + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-0 -- redis-cli -c -p 6379 get foo-0 + check: + ($stdout=='bar-0'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-1 -- redis-cli -c -p 6379 get foo-1 + check: + ($stdout=='bar-1'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-leader redis-cluster-v1beta2-leader-2 -- redis-cli -c -p 6379 get foo-2 + check: + ($stdout=='bar-2'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-0 -- redis-cli -c -p 6379 get foo-3 + check: + ($stdout=='bar-3'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-1 -- redis-cli -c -p 6379 get foo-4 + check: + ($stdout=='bar-4'): true + - script: + timeout: 30s + content: > + kubectl exec --namespace ${NAMESPACE} --container redis-cluster-v1beta2-follower redis-cluster-v1beta2-follower-2 -- redis-cli -c -p 6379 get foo-5 + check: + ($stdout=='bar-5'): true diff --git a/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster-hscale.yaml b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster-hscale.yaml new file mode 100644 index 000000000..014675747 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster-hscale.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: false + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 256Mi # Increased memory limit + storage: + volumeClaimTemplate: + spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster.yaml b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster.yaml new file mode 100644 index 000000000..5bf34bb88 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/cluster.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +spec: + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: false + podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + kubernetesConfig: + image: quay.io/opstree/redis:v7.0.12 + imagePullPolicy: Always + resources: + requests: + cpu: 101m + memory: 128Mi + limits: + cpu: 101m + memory: 128Mi + storage: + volumeClaimTemplate: + spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 1Gi diff --git a/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/ready-cluster.yaml new file mode 100644 index 000000000..a0708b5a5 --- /dev/null +++ b/tests/e2e-chainsaw/v1beta2/disable-persistence/redis-cluster/ready-cluster.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: redis-cluster-v1beta2 +status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready From ae814ecc05231944178597cd07365e8ea858ffea Mon Sep 17 00:00:00 2001 From: yangw Date: Thu, 6 Jun 2024 22:38:13 +0800 Subject: [PATCH 185/203] feat: add security context values in operator chart (#973) Signed-off-by: drivebyer --- .github/workflows/publish-charts.yaml | 63 +++++++++++++++++++ charts/redis-operator/Chart.yaml | 4 +- .../templates/operator-deployment.yaml | 4 ++ charts/redis-operator/values.yaml | 11 ++++ ct.yaml | 7 +++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 ct.yaml diff --git a/.github/workflows/publish-charts.yaml b/.github/workflows/publish-charts.yaml index 267616d87..a72b453e8 100644 --- a/.github/workflows/publish-charts.yaml +++ b/.github/workflows/publish-charts.yaml @@ -9,8 +9,71 @@ on: - master jobs: + lint-charts: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Helm + uses: azure/setup-helm@v3 + with: + version: v3.5.4 + + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + check-latest: true + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.6.0 + + - name: Run chart-testing (lint) + run: | + ct lint --config ct.yaml + + test-charts: + needs: + - lint-charts + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Create k8s Kind Cluster + uses: helm/kind-action@v1.5.0 + with: + cluster_name: kind + + - name: Install Helm + uses: azure/setup-helm@v3 + with: + version: v3.5.4 + + - name: Install yq + run: | + sudo snap install yq + + - name: Install and test Redis Related Helm charts + run: | + kubectl cluster-info --context kind-kind + chart_dirs=("redis-operator") + for dir in "${chart_dirs[@]}" + do + if [[ -f ./charts/$dir/Chart.yaml ]]; then + helm dependency update ./charts/$dir/ + fi + helm install $dir ./charts/$dir/ + helm test $dir + done + echo "Listing installed Helm charts..." + release-charts: runs-on: ubuntu-latest + needs: + - test-charts steps: - name: Checkout uses: actions/checkout@v3 diff --git a/charts/redis-operator/Chart.yaml b/charts/redis-operator/Chart.yaml index 2d3266f2f..4d7a00851 100644 --- a/charts/redis-operator/Chart.yaml +++ b/charts/redis-operator/Chart.yaml @@ -1,6 +1,6 @@ --- apiVersion: v2 -version: 0.16.1 +version: 0.16.2 appVersion: "0.17.0" description: Provides easy redis setup definitions for Kubernetes services, and deployment. engine: gotpl @@ -25,4 +25,4 @@ dependencies: version: v1.12.4 repository: https://charts.jetstack.io alias: certmanager - condition: certmanager.enabled \ No newline at end of file + condition: certmanager.enabled diff --git a/charts/redis-operator/templates/operator-deployment.yaml b/charts/redis-operator/templates/operator-deployment.yaml index b1a5d8bea..1dea377a0 100644 --- a/charts/redis-operator/templates/operator-deployment.yaml +++ b/charts/redis-operator/templates/operator-deployment.yaml @@ -21,8 +21,12 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} spec: + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: "{{ .Values.redisOperator.name }}" + securityContext: + {{- toYaml .Values.securityContext | nindent 10 }} image: "{{ .Values.redisOperator.imageName }}:{{ .Values.redisOperator.imageTag | default (printf "v%s" .Chart.AppVersion) }}" imagePullPolicy: {{ .Values.redisOperator.imagePullPolicy }} command: diff --git a/charts/redis-operator/values.yaml b/charts/redis-operator/values.yaml index ba4da7f82..ce7f7490e 100644 --- a/charts/redis-operator/values.yaml +++ b/charts/redis-operator/values.yaml @@ -58,3 +58,14 @@ nodeSelector: {} tolerateAllTaints: false tolerations: [] affinity: {} + +podSecurityContext: {} +# fsGroup: 2000 + +securityContext: {} +# capabilities: +# drop: +# - ALL +# readOnlyRootFilesystem: true +# runAsNonRoot: true +# runAsUser: 1000 diff --git a/ct.yaml b/ct.yaml new file mode 100644 index 000000000..4b2ac5725 --- /dev/null +++ b/ct.yaml @@ -0,0 +1,7 @@ +--- +remote: origin +target-branch: master +chart-dirs: + - charts +chart-repos: + - ot-helm=https://ot-container-kit.github.io/helm-charts \ No newline at end of file From b44f30367cc5fe833a7ac258a10abb10993a6038 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 8 Jun 2024 11:52:04 +0800 Subject: [PATCH 186/203] refactor: add common controller util (#977) * refactor: add common controller util Signed-off-by: drivebyer * fix lint Signed-off-by: drivebyer --------- Signed-off-by: drivebyer Signed-off-by: drivebyer --- controllers/redis_controller.go | 25 ++++----- controllers/rediscluster_controller.go | 61 ++++++++++------------ controllers/redisreplication_controller.go | 34 +++++------- controllers/redissentinel_controller.go | 29 ++++------ pkg/controllerutil/controller_common.go | 40 ++++++++++++++ 5 files changed, 101 insertions(+), 88 deletions(-) create mode 100644 pkg/controllerutil/controller_common.go diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go index 2ac11f27e..dbd0488ba 100644 --- a/controllers/redis_controller.go +++ b/controllers/redis_controller.go @@ -22,8 +22,8 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" + intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil" "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -47,36 +47,29 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl err := r.Client.Get(context.TODO(), req.NamespacedName, instance) if err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err + return intctrlutil.RequeueWithErrorChecking(err, reqLogger, "failed to get redis instance") } if instance.ObjectMeta.GetDeletionTimestamp() != nil { if err = k8sutils.HandleRedisFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "failed to handle redis finalizer") } - return ctrl.Result{}, nil + return intctrlutil.Reconciled() } if _, found := instance.ObjectMeta.GetAnnotations()["redis.opstreelabs.in/skip-reconcile"]; found { - reqLogger.Info("Found annotations redis.opstreelabs.in/skip-reconcile, so skipping reconcile") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "found skip reconcile annotation") } if err = k8sutils.AddFinalizer(instance, k8sutils.RedisFinalizer, r.Client); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "failed to add finalizer") } - err = k8sutils.CreateStandaloneRedis(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "failed to create redis") } err = k8sutils.CreateStandaloneService(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "failed to create service") } - - reqLogger.Info("Will reconcile redis operator in again 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "requeue after 10 seconds") } // SetupWithManager sets up the controller with the Manager. diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index f385b978a..ae7d8af9c 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -24,6 +24,7 @@ import ( "github.com/OT-CONTAINER-KIT/redis-operator/api/status" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" + intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil" "github.com/go-logr/logr" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" @@ -50,20 +51,16 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request err := r.Client.Get(context.TODO(), req.NamespacedName, instance) if err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err + return intctrlutil.RequeueWithErrorChecking(err, reqLogger, "failed to get redis cluster instance") } if instance.ObjectMeta.GetDeletionTimestamp() != nil { if err = k8sutils.HandleRedisClusterFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "failed to handle redis cluster finalizer") } - return ctrl.Result{}, nil + return intctrlutil.Reconciled() } if _, found := instance.ObjectMeta.GetAnnotations()["rediscluster.opstreelabs.in/skip-reconcile"]; found { - reqLogger.Info("Found annotations rediscluster.opstreelabs.in/skip-reconcile, so skipping reconcile") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "found skip reconcile annotation") } instance.SetDefault() @@ -72,7 +69,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request totalReplicas := leaderReplicas + followerReplicas if err = k8sutils.AddFinalizer(instance, k8sutils.RedisClusterFinalizer, r.Client); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "failed to add finalizer") } // Check if the cluster is downscaled @@ -98,7 +95,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // Step 3 Rebalance the cluster k8sutils.RebalanceRedisCluster(r.K8sClient, r.Log, instance) reqLogger.Info("Redis cluster is downscaled... Rebalancing the cluster is done") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "") } // Mark the cluster status as initializing if there are no leader or follower nodes @@ -106,33 +103,33 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request instance.Status.ReadyLeaderReplicas != leaderReplicas { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterLeaderReason, instance.Status.ReadyLeaderReplicas, instance.Status.ReadyFollowerReplicas, r.Dk8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } if leaderReplicas != 0 { err = k8sutils.CreateRedisLeaderService(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } err = k8sutils.CreateRedisLeader(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } // todo: remove me after watch statefulset in controller redisLeaderInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-leader") if err != nil { if errors.IsNotFound(err) { - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") } - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } if r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") { @@ -141,54 +138,52 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request instance.Status.ReadyFollowerReplicas != followerReplicas { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterInitializing, status.InitializingClusterFollowerReason, leaderReplicas, instance.Status.ReadyFollowerReplicas, r.Dk8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } // if we have followers create their service. if followerReplicas != 0 { err = k8sutils.CreateRedisFollowerService(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } err = k8sutils.CreateRedisFollower(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "follower", instance.Spec.RedisFollower.PodDisruptionBudget, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } // todo: remove me after watch statefulset in controller redisFollowerInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-follower") if err != nil { if errors.IsNotFound(err) { - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") } - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } if leaderReplicas == 0 { - reqLogger.Info("Redis leaders Cannot be 0", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis leaders Cannot be 0", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) } if !(r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") && r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-follower")) { - reqLogger.Info("Redis leader and follower nodes are not ready yet") - return ctrl.Result{RequeueAfter: time.Second * 30}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis leader and follower nodes are not ready yet") } // Mark the cluster status as bootstrapping if all the leader and follower nodes are ready if !(instance.Status.ReadyLeaderReplicas == leaderReplicas && instance.Status.ReadyFollowerReplicas == followerReplicas) { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterBootstrap, status.BootstrapClusterReason, leaderReplicas, followerReplicas, r.Dk8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } if nc := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, ""); nc != totalReplicas { - reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Followers.Ready", strconv.Itoa(int(redisFollowerInfo.Status.ReadyReplicas))) + reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", redisLeaderInfo.Status.ReadyReplicas, "Followers.Ready", redisFollowerInfo.Status.ReadyReplicas) leaderCount := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) @@ -211,8 +206,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request reqLogger.Info("no follower/replicas configured, skipping replication configuration", "Leaders.Count", leaderCount, "Leader.Size", leaderReplicas, "Follower.Replicas", followerReplicas) } } - reqLogger.Info("Redis cluster count is not desired", "Current.Count", nc, "Desired.Count", totalReplicas) - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis cluster count is not desired", "Current.Count", nc, "Desired.Count", totalReplicas) } reqLogger.Info("Redis cluster count is desired") @@ -220,7 +214,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request reqLogger.Info("Redis leader is not desired, executing failover operation") err = k8sutils.ExecuteFailoverOperation(ctx, r.K8sClient, r.Log, instance) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } @@ -234,12 +228,11 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if k8sutils.RedisClusterStatusHealth(ctx, r.K8sClient, r.Log, instance) { err = k8sutils.UpdateRedisClusterStatus(instance, status.RedisClusterReady, status.ReadyClusterReason, leaderReplicas, followerReplicas, r.Dk8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } } } - reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "") } // SetupWithManager sets up the controller with the Manager. diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 0473d412a..0446b4dc3 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -7,9 +7,9 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" + intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -34,20 +34,16 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req err := r.Client.Get(context.TODO(), req.NamespacedName, instance) if err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err + return intctrlutil.RequeueWithErrorChecking(err, reqLogger, "") } if instance.ObjectMeta.GetDeletionTimestamp() != nil { if err = k8sutils.HandleRedisReplicationFinalizer(r.Client, r.K8sClient, r.Log, instance); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } - return ctrl.Result{}, nil + return intctrlutil.Reconciled() } if _, found := instance.ObjectMeta.GetAnnotations()["redisreplication.opstreelabs.in/skip-reconcile"]; found { - reqLogger.Info("Found annotations redisreplication.opstreelabs.in/skip-reconcile, so skipping reconcile") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "found skip reconcile annotation") } leaderReplicas := int32(1) @@ -55,29 +51,28 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req totalReplicas := leaderReplicas + followerReplicas if err = k8sutils.AddFinalizer(instance, k8sutils.RedisReplicationFinalizer, r.Client); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } err = k8sutils.CreateReplicationRedis(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } err = k8sutils.CreateReplicationService(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } // Set Pod distruptiuon Budget Later redisReplicationInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()) if err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") } // Check that the Leader and Follower are ready in redis replication if redisReplicationInfo.Status.ReadyReplicas != totalReplicas { - reqLogger.Info("Redis replication nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas)), "Expected.Replicas", totalReplicas) - return ctrl.Result{RequeueAfter: time.Second * 60}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis replication nodes are not ready yet", "Ready.Replicas", redisReplicationInfo.Status.ReadyReplicas, "Expected.Replicas", totalReplicas) } var realMaster string @@ -90,18 +85,17 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req realMaster = masterNodes[0] } if err = k8sutils.CreateMasterSlaveReplication(ctx, r.K8sClient, r.Log, instance, masterNodes, realMaster); err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") } } realMaster = k8sutils.GetRedisReplicationRealMaster(ctx, r.K8sClient, r.Log, instance, masterNodes) if err = r.UpdateRedisReplicationMaster(ctx, instance, realMaster); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } if err = r.UpdateRedisPodRoleLabel(ctx, instance, realMaster); err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } - reqLogger.Info("Will reconcile redis operator in again 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "") } func (r *RedisReplicationReconciler) UpdateRedisReplicationMaster(ctx context.Context, instance *redisv1beta2.RedisReplication, masterNode string) error { diff --git a/controllers/redissentinel_controller.go b/controllers/redissentinel_controller.go index 8d3f50c28..2130c3907 100644 --- a/controllers/redissentinel_controller.go +++ b/controllers/redissentinel_controller.go @@ -6,8 +6,8 @@ import ( redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" + intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil" "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -31,54 +31,47 @@ func (r *RedisSentinelReconciler) Reconcile(ctx context.Context, req ctrl.Reques err := r.Client.Get(context.TODO(), req.NamespacedName, instance) if err != nil { - if errors.IsNotFound(err) { - return ctrl.Result{}, nil - } - return ctrl.Result{}, err + return intctrlutil.RequeueWithErrorChecking(err, reqLogger, "") } if instance.ObjectMeta.GetDeletionTimestamp() != nil { if err = k8sutils.HandleRedisSentinelFinalizer(r.Client, r.Log, instance); err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } - return ctrl.Result{}, nil + return intctrlutil.Reconciled() } if _, found := instance.ObjectMeta.GetAnnotations()["redissentinel.opstreelabs.in/skip-reconcile"]; found { - reqLogger.Info("Found annotations redissentinel.opstreelabs.in/skip-reconcile, so skipping reconcile") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "found skip reconcile annotation") } // Get total Sentinel Replicas // sentinelReplicas := instance.Spec.GetSentinelCounts("sentinel") if err = k8sutils.AddFinalizer(instance, k8sutils.RedisSentinelFinalizer, r.Client); err != nil { - return ctrl.Result{RequeueAfter: time.Second * 60}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } if instance.Spec.RedisSentinelConfig != nil && !k8sutils.IsRedisReplicationReady(ctx, reqLogger, r.K8sClient, r.Dk8sClient, instance) { - reqLogger.Info("Redis Replication is specified but not ready, so will reconcile again in 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "Redis Replication is specified but not ready") } // Create Redis Sentinel err = k8sutils.CreateRedisSentinel(ctx, r.K8sClient, r.Log, instance, r.K8sClient, r.Dk8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } err = k8sutils.ReconcileSentinelPodDisruptionBudget(instance, instance.Spec.PodDisruptionBudget, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } // Create the Service for Redis Sentinel err = k8sutils.CreateRedisSentinelService(instance, r.K8sClient) if err != nil { - return ctrl.Result{}, err + return intctrlutil.RequeueWithError(err, reqLogger, "") } - - reqLogger.Info("Will reconcile after 10 seconds") - return ctrl.Result{RequeueAfter: time.Second * 10}, nil + return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "") } // SetupWithManager sets up the controller with the Manager. diff --git a/pkg/controllerutil/controller_common.go b/pkg/controllerutil/controller_common.go new file mode 100644 index 000000000..ba063060b --- /dev/null +++ b/pkg/controllerutil/controller_common.go @@ -0,0 +1,40 @@ +package controllerutil + +import ( + "time" + + "github.com/go-logr/logr" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +func Reconciled() (reconcile.Result, error) { + return reconcile.Result{}, nil +} + +func RequeueAfter(logger logr.Logger, duration time.Duration, msg string, keysAndValues ...interface{}) (reconcile.Result, error) { + keysAndValues = append(keysAndValues, "duration", duration.String()) + if msg == "" { + msg = "requeue-after" + } + logger.V(1).Info(msg, keysAndValues...) + return reconcile.Result{ + Requeue: true, + RequeueAfter: duration, + }, nil +} + +func RequeueWithError(err error, logger logr.Logger, msg string, keysAndValues ...interface{}) (reconcile.Result, error) { + if msg == "" { + msg = "requeue with error" + } + logger.Error(err, msg, keysAndValues...) + return reconcile.Result{}, err +} + +func RequeueWithErrorChecking(err error, logger logr.Logger, msg string, keysAndValues ...interface{}) (reconcile.Result, error) { + if apierrors.IsNotFound(err) { + return Reconciled() + } + return RequeueWithError(err, logger, msg, keysAndValues...) +} From 46ded9feb80c43f21783be69b5b7318f8dc6eaeb Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Wed, 12 Jun 2024 07:37:05 +0530 Subject: [PATCH 187/203] test: generateStatefulSetsDef cover (#980) Signed-off-by: Mahesh Kumar --- k8sutils/statefulset_test.go | 415 +++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 3ea826556..b0c0fc505 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -1017,3 +1017,418 @@ func Test_getExporterEnvironmentVariables(t *testing.T) { }) } } + +func TestGenerateStatefulSetsDef(t *testing.T) { + tests := []struct { + name string + statefulSetMeta metav1.ObjectMeta + stsParams statefulSetParameters + expectedStsDef *appsv1.StatefulSet + stsOwnerDef metav1.OwnerReference + initContainerParams initContainerParameters + containerParams containerParameters + sideCareContainer []redisv1beta2.Sidecar + }{ + { + name: "Test1_With_cluster_mode_ExternalConfig_tls", + statefulSetMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-sts", + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + stsOwnerDef: metav1.OwnerReference{ + Kind: "StatefulSet", + APIVersion: "apps/v1", + Name: "test-sts", + }, + stsParams: statefulSetParameters{ + Replicas: ptr.To(int32(3)), + ClusterMode: true, + NodeConfVolume: true, + ExternalConfig: ptr.To(""), + Tolerations: &[]v1.Toleration{ + { + Key: "node.kubernetes.io/unreachable", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + ServiceAccountName: ptr.To("redis"), + }, + expectedStsDef: &appsv1.StatefulSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "StatefulSet", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-sts", + OwnerReferences: []metav1.OwnerReference{ + { + Kind: "StatefulSet", + APIVersion: "apps/v1", + Name: "test-sts", + }, + }, + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + Spec: appsv1.StatefulSetSpec{ + ServiceName: "test-sts-headless", + Selector: &metav1.LabelSelector{}, + Replicas: ptr.To(int32(3)), + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + Spec: v1.PodSpec{ + Tolerations: []v1.Toleration{ + { + Key: "node.kubernetes.io/unreachable", + Operator: corev1.TolerationOpExists, + Effect: corev1.TaintEffectNoExecute, + }, + }, + ServiceAccountName: "redis", + Containers: []corev1.Container{ + { + Name: "test-sts", + Image: "redis:latest", + Env: []corev1.EnvVar{ + { + Name: "ACL_MODE", + Value: "true", + }, + { + Name: "REDIS_ADDR", + Value: "redis://localhost:6379", + }, + { + Name: "REDIS_MAJOR_VERSION", + Value: "1.0", + }, + { + Name: "REDIS_TLS_CA_KEY", + Value: path.Join("/tls/", "ca.crt"), + }, + { + Name: "REDIS_TLS_CERT", + Value: path.Join("/tls/", "tls.crt"), + }, + { + Name: "REDIS_TLS_CERT_KEY", + Value: path.Join("/tls/", "tls.key"), + }, + { + Name: "SERVER_MODE", + Value: "", + }, + { + Name: "SETUP_MODE", + Value: "", + }, + { + Name: "TLS_MODE", + Value: "true", + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} --tls --cert ${REDIS_TLS_CERT} --key ${REDIS_TLS_CERT_KEY} --cacert ${REDIS_TLS_CA_KEY} ping"}, + }, + }, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} --tls --cert ${REDIS_TLS_CERT} --key ${REDIS_TLS_CERT_KEY} --cacert ${REDIS_TLS_CA_KEY} ping"}, + }, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "tls-certs", + MountPath: "/tls", + ReadOnly: true, + }, + { + Name: "acl-secret", + MountPath: "/etc/redis/user.acl", + SubPath: "user.acl", + }, + { + Name: "external-config", + MountPath: "/etc/redis/external.conf.d", + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: "external-config", + VolumeSource: v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{}, + }, + }, + { + Name: "tls-certs", + VolumeSource: v1.VolumeSource{ + Secret: &v1.SecretVolumeSource{ + SecretName: "sts-secret", + }, + }, + }, + { + Name: "acl-secret", + VolumeSource: v1.VolumeSource{ + Secret: &v1.SecretVolumeSource{ + SecretName: "sts-acl", + }, + }, + }, + }, + }, + }, + }, + }, + initContainerParams: initContainerParameters{}, + containerParams: containerParameters{ + Image: "redis:latest", + EnvVars: &[]v1.EnvVar{ + { + Name: "REDIS_MAJOR_VERSION", + Value: "1.0", + }, + }, + TLSConfig: &redisv1beta2.TLSConfig{ + TLSConfig: common.TLSConfig{ + Secret: v1.SecretVolumeSource{ + SecretName: "sts-secret", + }, + }, + }, + ACLConfig: &redisv1beta2.ACLConfig{ + Secret: &v1.SecretVolumeSource{ + SecretName: "sts-acl", + }, + }, + }, + sideCareContainer: []redisv1beta2.Sidecar{}, + }, + { + name: "Test2_With_initcontainer_sidecare_enabledMetrics_enable_volume_clustermode", + statefulSetMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-sts", + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + stsOwnerDef: metav1.OwnerReference{ + Kind: "StatefulSet", + APIVersion: "apps/v1", + Name: "test-sts", + }, + stsParams: statefulSetParameters{ + Replicas: ptr.To(int32(3)), + EnableMetrics: true, + ClusterMode: true, + NodeConfVolume: true, + ImagePullSecrets: &[]v1.LocalObjectReference{ + { + Name: "redis-secret", + }, + }, + }, + expectedStsDef: &appsv1.StatefulSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "StatefulSet", + APIVersion: "apps/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-sts", + OwnerReferences: []metav1.OwnerReference{ + { + Kind: "StatefulSet", + APIVersion: "apps/v1", + Name: "test-sts", + }, + }, + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + Spec: appsv1.StatefulSetSpec{ + ServiceName: "test-sts-headless", + Selector: &metav1.LabelSelector{}, + Replicas: ptr.To(int32(3)), + Template: v1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + Spec: v1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "inittest-sts", + Image: "redis-init:latest", + }, + }, + Containers: []corev1.Container{ + { + Name: "test-sts", + Image: "redis:latest", + Env: []corev1.EnvVar{ + { + Name: "PERSISTENCE_ENABLED", + Value: "true", + }, + { + Name: "REDIS_ADDR", + Value: "redis://localhost:6379", + }, + { + Name: "SERVER_MODE", + Value: "", + }, + { + Name: "SETUP_MODE", + Value: "", + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "node-conf", + MountPath: "/node-conf", + ReadOnly: false, + }, + { + Name: "test-sts", + MountPath: "/data", + ReadOnly: false, + }, + }, + }, + { + Name: "redis-exporter", + Ports: []corev1.ContainerPort{ + { + Name: "redis-exporter", + ContainerPort: 9121, + Protocol: corev1.ProtocolTCP, + }, + }, + }, + { + Name: "redis-sidecare", + Image: "redis-sidecar:latest", + ImagePullPolicy: corev1.PullAlways, + }, + }, + Volumes: []v1.Volume{ + { + Name: "additional-vol", + }, + }, + ImagePullSecrets: []v1.LocalObjectReference{ + { + Name: "redis-secret", + }, + }, + }, + }, + VolumeClaimTemplates: []v1.PersistentVolumeClaim{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "node-conf", + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + Spec: v1.PersistentVolumeClaimSpec{ + AccessModes: []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + }, + VolumeMode: ptr.To(v1.PersistentVolumeFilesystem), + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Annotations: map[string]string{ + "redis.opstreelabs.in": "true", + "redis.opstreelabs.instance": "test-sts", + }, + }, + Spec: v1.PersistentVolumeClaimSpec{ + AccessModes: []v1.PersistentVolumeAccessMode{ + v1.ReadWriteOnce, + }, + VolumeMode: ptr.To(v1.PersistentVolumeFilesystem), + }, + }, + }, + }, + }, + initContainerParams: initContainerParameters{ + Enabled: ptr.To(true), + Image: "redis-init:latest", + }, + containerParams: containerParameters{ + Image: "redis:latest", + PersistenceEnabled: ptr.To(true), + AdditionalVolume: []v1.Volume{ + { + Name: "additional-vol", + }, + }, + }, + sideCareContainer: []redisv1beta2.Sidecar{ + { + Sidecar: common.Sidecar{ + Name: "redis-sidecare", + Image: "redis-sidecar:latest", + ImagePullPolicy: corev1.PullAlways, + }, + }, + }, + }, + } + + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + stsDef := generateStatefulSetsDef(test.statefulSetMeta, test.stsParams, test.stsOwnerDef, test.initContainerParams, test.containerParams, test.sideCareContainer) + assert.Equal(t, stsDef, test.expectedStsDef, "StatefulSet Configration") + }) + } +} From b22118c21e2fbdc70323ba1a565406dd605fa394 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 15 Jun 2024 17:02:07 +0800 Subject: [PATCH 188/203] refactor: reconcile on statefulset update (#988) Signed-off-by: drivebyer --- controllers/rediscluster_controller.go | 16 +++---------- controllers/redisreplication_controller.go | 27 ++++++---------------- controllers/suite_test.go | 15 +++++++----- main.go | 13 ++++++----- 4 files changed, 26 insertions(+), 45 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index ae7d8af9c..6e4b9fa99 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -18,7 +18,6 @@ package controllers import ( "context" - "strconv" "time" "github.com/OT-CONTAINER-KIT/redis-operator/api/status" @@ -26,7 +25,7 @@ import ( "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil" "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/api/errors" + appsv1 "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -126,9 +125,6 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // todo: remove me after watch statefulset in controller redisLeaderInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-leader") if err != nil { - if errors.IsNotFound(err) { - return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") - } return intctrlutil.RequeueWithError(err, reqLogger, "") } @@ -160,18 +156,11 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request // todo: remove me after watch statefulset in controller redisFollowerInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-follower") if err != nil { - if errors.IsNotFound(err) { - return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") - } return intctrlutil.RequeueWithError(err, reqLogger, "") } - if leaderReplicas == 0 { - return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis leaders Cannot be 0", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", leaderReplicas) - } - if !(r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") && r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-follower")) { - return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis leader and follower nodes are not ready yet") + return intctrlutil.Reconciled() } // Mark the cluster status as bootstrapping if all the leader and follower nodes are ready @@ -239,5 +228,6 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request func (r *RedisClusterReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&redisv1beta2.RedisCluster{}). + Owns(&appsv1.StatefulSet{}). Complete(r) } diff --git a/controllers/redisreplication_controller.go b/controllers/redisreplication_controller.go index 0446b4dc3..335d0606e 100644 --- a/controllers/redisreplication_controller.go +++ b/controllers/redisreplication_controller.go @@ -2,13 +2,13 @@ package controllers import ( "context" - "strconv" "time" redisv1beta2 "github.com/OT-CONTAINER-KIT/redis-operator/api/v1beta2" "github.com/OT-CONTAINER-KIT/redis-operator/k8sutils" intctrlutil "github.com/OT-CONTAINER-KIT/redis-operator/pkg/controllerutil" "github.com/go-logr/logr" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" @@ -21,6 +21,7 @@ import ( type RedisReplicationReconciler struct { client.Client k8sutils.Pod + k8sutils.StatefulSet K8sClient kubernetes.Interface Dk8sClient dynamic.Interface Log logr.Logger @@ -45,15 +46,9 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req if _, found := instance.ObjectMeta.GetAnnotations()["redisreplication.opstreelabs.in/skip-reconcile"]; found { return intctrlutil.RequeueAfter(reqLogger, time.Second*10, "found skip reconcile annotation") } - - leaderReplicas := int32(1) - followerReplicas := instance.Spec.GetReplicationCounts("replication") - leaderReplicas - totalReplicas := leaderReplicas + followerReplicas - if err = k8sutils.AddFinalizer(instance, k8sutils.RedisReplicationFinalizer, r.Client); err != nil { return intctrlutil.RequeueWithError(err, reqLogger, "") } - err = k8sutils.CreateReplicationRedis(instance, r.K8sClient) if err != nil { return intctrlutil.RequeueWithError(err, reqLogger, "") @@ -62,23 +57,14 @@ func (r *RedisReplicationReconciler) Reconcile(ctx context.Context, req ctrl.Req if err != nil { return intctrlutil.RequeueWithError(err, reqLogger, "") } - - // Set Pod distruptiuon Budget Later - - redisReplicationInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()) - if err != nil { - return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "") - } - - // Check that the Leader and Follower are ready in redis replication - if redisReplicationInfo.Status.ReadyReplicas != totalReplicas { - return intctrlutil.RequeueAfter(reqLogger, time.Second*60, "Redis replication nodes are not ready yet", "Ready.Replicas", redisReplicationInfo.Status.ReadyReplicas, "Expected.Replicas", totalReplicas) + if !r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name) { + return intctrlutil.Reconciled() } var realMaster string masterNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "master") - if len(masterNodes) > int(leaderReplicas) { - reqLogger.Info("Creating redis replication by executing replication creation commands", "Replication.Ready", strconv.Itoa(int(redisReplicationInfo.Status.ReadyReplicas))) + if len(masterNodes) > 1 { + reqLogger.Info("Creating redis replication by executing replication creation commands") slaveNodes := k8sutils.GetRedisNodesByRole(ctx, r.K8sClient, r.Log, instance, "slave") realMaster = k8sutils.GetRedisReplicationRealMaster(ctx, r.K8sClient, r.Log, instance, masterNodes) if len(slaveNodes) == 0 { @@ -138,5 +124,6 @@ func (r *RedisReplicationReconciler) UpdateRedisPodRoleLabel(ctx context.Context func (r *RedisReplicationReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&redisv1beta2.RedisReplication{}). + Owns(&appsv1.StatefulSet{}). Complete(r) } diff --git a/controllers/suite_test.go b/controllers/suite_test.go index e6039fde5..5ae61deae 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -101,21 +101,24 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) - rrLog := ctrl.Log.WithName("controllers").WithName("RedisReplication") + rcLog := ctrl.Log.WithName("controllers").WithName("RedisCluster") err = (&RedisClusterReconciler{ Client: k8sManager.GetClient(), K8sClient: k8sClient, Dk8sClient: dk8sClient, Scheme: k8sManager.GetScheme(), - StatefulSet: k8sutils.NewStatefulSetService(k8sClient, rrLog), + StatefulSet: k8sutils.NewStatefulSetService(k8sClient, rcLog), }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + rrLog := ctrl.Log.WithName("controllers").WithName("RedisReplication") err = (&RedisReplicationReconciler{ - Client: k8sManager.GetClient(), - K8sClient: k8sClient, - Dk8sClient: dk8sClient, - Scheme: k8sManager.GetScheme(), + Client: k8sManager.GetClient(), + K8sClient: k8sClient, + Dk8sClient: dk8sClient, + Scheme: k8sManager.GetScheme(), + Pod: k8sutils.NewPodService(k8sClient, rrLog), + StatefulSet: k8sutils.NewStatefulSetService(k8sClient, rrLog), }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/main.go b/main.go index 556b169ad..4da3274e6 100644 --- a/main.go +++ b/main.go @@ -138,12 +138,13 @@ func main() { } rrLog := ctrl.Log.WithName("controllers").WithName("RedisReplication") if err = (&controllers.RedisReplicationReconciler{ - Client: mgr.GetClient(), - K8sClient: k8sclient, - Dk8sClient: dk8sClient, - Log: rrLog, - Scheme: mgr.GetScheme(), - Pod: k8sutils.NewPodService(k8sclient, rrLog), + Client: mgr.GetClient(), + K8sClient: k8sclient, + Dk8sClient: dk8sClient, + Log: rrLog, + Scheme: mgr.GetScheme(), + Pod: k8sutils.NewPodService(k8sclient, rrLog), + StatefulSet: k8sutils.NewStatefulSetService(k8sclient, rrLog), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "RedisReplication") os.Exit(1) From a8386083695ecd36c4d28e4d6ef7148747250b6c Mon Sep 17 00:00:00 2001 From: Laurentiu Soica Date: Sat, 15 Jun 2024 12:04:50 +0300 Subject: [PATCH 189/203] feat: add securityContext for exporter, initcontainers and sidecars (#987) * feat: add securityContext for exporter, initcontainers and sidecars Signed-off-by: laurentiusoica * fix: add docs Signed-off-by: laurentiusoica * fix: RedisExporterSecurityContext instead of SecurityContext Signed-off-by: laurentiusoica * fix: code review Signed-off-by: laurentiusoica * fix: refresh crds Signed-off-by: laurentiusoica * fix: refresh crds Signed-off-by: laurentiusoica --------- Signed-off-by: laurentiusoica Co-authored-by: laurentiusoica --- api/common_types.go | 1 + api/v1beta2/common_types.go | 10 +- api/v1beta2/zz_generated.deepcopy.go | 10 + api/zz_generated.deepcopy.go | 5 + charts/redis-operator/crds/redis-cluster.yaml | 3222 +++++++++++++++-- .../crds/redis-replication.yaml | 2079 ++++++++++- .../redis-operator/crds/redis-sentinel.yaml | 1581 +++++++- charts/redis-operator/crds/redis.yaml | 2073 ++++++++++- .../redis.redis.opstreelabs.in_redis.yaml | 679 ++++ ...is.redis.opstreelabs.in_redisclusters.yaml | 803 +++- ...edis.opstreelabs.in_redisreplications.yaml | 679 ++++ ...s.redis.opstreelabs.in_redissentinels.yaml | 510 +++ .../en/docs/CRD Reference/Redis API/_index.md | 2 + k8sutils/redis-cluster.go | 2 + k8sutils/redis-replication.go | 2 + k8sutils/redis-sentinel.go | 2 + k8sutils/redis-standalone.go | 2 + k8sutils/statefulset.go | 5 + 18 files changed, 10791 insertions(+), 876 deletions(-) diff --git a/api/common_types.go b/api/common_types.go index 22030149d..42af4be25 100644 --- a/api/common_types.go +++ b/api/common_types.go @@ -43,6 +43,7 @@ type RedisExporter struct { Resources *corev1.ResourceRequirements `json:"resources,omitempty"` ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` EnvVars *[]corev1.EnvVar `json:"env,omitempty"` + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` } // RedisConfig defines the external configuration of Redis diff --git a/api/v1beta2/common_types.go b/api/v1beta2/common_types.go index 8de37a3ad..1fe7fda2a 100644 --- a/api/v1beta2/common_types.go +++ b/api/v1beta2/common_types.go @@ -73,10 +73,11 @@ type ACLConfig struct { // Sidecar for each Redis pods type Sidecar struct { - common.Sidecar `json:",inline"` - Volumes *[]corev1.VolumeMount `json:"mountPath,omitempty"` - Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"` - Ports *[]corev1.ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort" protobuf:"bytes,6,rep,name=ports"` + common.Sidecar `json:",inline"` + Volumes *[]corev1.VolumeMount `json:"mountPath,omitempty"` + Command []string `json:"command,omitempty" protobuf:"bytes,3,rep,name=command"` + Ports *[]corev1.ContainerPort `json:"ports,omitempty" patchStrategy:"merge" patchMergeKey:"containerPort" protobuf:"bytes,6,rep,name=ports"` + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` } // InitContainer for each Redis pods @@ -88,4 +89,5 @@ type InitContainer struct { EnvVars *[]corev1.EnvVar `json:"env,omitempty"` Command []string `json:"command,omitempty"` Args []string `json:"args,omitempty"` + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` } diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 2da35d19a..71323c66c 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -123,6 +123,11 @@ func (in *InitContainer) DeepCopyInto(out *InitContainer) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(v1.SecurityContext) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitContainer. @@ -1066,6 +1071,11 @@ func (in *Sidecar) DeepCopyInto(out *Sidecar) { copy(*out, *in) } } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(v1.SecurityContext) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Sidecar. diff --git a/api/zz_generated.deepcopy.go b/api/zz_generated.deepcopy.go index 2e3b3ae55..df94626ef 100644 --- a/api/zz_generated.deepcopy.go +++ b/api/zz_generated.deepcopy.go @@ -168,6 +168,11 @@ func (in *RedisExporter) DeepCopyInto(out *RedisExporter) { } } } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(v1.SecurityContext) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisExporter. diff --git a/charts/redis-operator/crds/redis-cluster.yaml b/charts/redis-operator/crds/redis-cluster.yaml index bc6203d92..d6b10f5c5 100644 --- a/charts/redis-operator/crds/redis-cluster.yaml +++ b/charts/redis-operator/crds/redis-cluster.yaml @@ -5,7 +5,6 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 - # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} creationTimestamp: null name: redisclusters.redis.redis.opstreelabs.in spec: @@ -403,6 +402,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -453,23 +455,179 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object redisFollower: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisFollower interface will have the redis follower configuration properties: @@ -718,7 +876,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -768,6 +927,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -880,7 +1081,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -929,6 +1131,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1038,7 +1278,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1088,6 +1329,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1200,7 +1483,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -1249,6 +1533,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1331,38 +1653,153 @@ spec: type: object type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1383,38 +1820,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -1469,19 +2021,6 @@ spec: type: array type: object redisLeader: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisLeader interface will have the redis leader configuration properties: affinity: @@ -1729,7 +2268,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -1779,6 +2319,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -1891,7 +2473,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -1940,6 +2523,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2049,7 +2670,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -2099,6 +2721,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2211,7 +2875,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2260,6 +2925,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2336,44 +3039,159 @@ spec: pods is running. Empty topologyKey is not allowed. type: string required: - - topologyKey + - topologyKey + type: object + type: array + type: object + type: object + livenessProbe: + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value type: object type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - type: object - livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe - properties: - failureThreshold: - default: 3 - format: int32 - minimum: 1 - type: integer initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -2394,38 +3212,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -2882,6 +3815,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -3004,30 +3939,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -3103,6 +4014,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -3251,6 +4182,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -3902,32 +4869,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -4016,6 +4957,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -4415,6 +5382,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -5298,6 +6372,8 @@ spec: - name type: object type: array + hostNetwork: + type: boolean initContainer: description: InitContainer for each Redis pods properties: @@ -5476,6 +6552,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -5793,6 +7038,9 @@ spec: type: string type: object type: object + port: + default: 6379 + type: integer priorityClassName: type: string redisExporter: @@ -5916,6 +7164,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -5966,23 +7217,179 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object redisFollower: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisFollower interface will have the redis follower configuration properties: @@ -6231,7 +7638,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -6281,6 +7689,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6393,7 +7843,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -6442,6 +7893,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6551,7 +8040,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -6601,6 +8091,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6713,7 +8245,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -6762,6 +8295,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -6838,44 +8409,159 @@ spec: pods is running. Empty topologyKey is not allowed. type: string required: - - topologyKey + - topologyKey + type: object + type: array + type: object + type: object + livenessProbe: + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. + properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value type: object type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port type: object - type: object - livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe - properties: - failureThreshold: - default: 3 - format: int32 - minimum: 1 - type: integer initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -6896,38 +8582,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -7154,19 +8955,6 @@ spec: type: array type: object redisLeader: - default: - livenessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 description: RedisLeader interface will have the redis leader configuration properties: affinity: @@ -7414,7 +9202,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7464,6 +9253,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7576,7 +9407,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -7625,6 +9457,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7734,7 +9604,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list @@ -7784,6 +9655,48 @@ spec: only "value". The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key in (value)` to select the group of + existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) + affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value + is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature + gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod + label keys to select which pods will be taken + into consideration. The keys are used to lookup + values from the incoming pod labels, those + key-value labels are merged with `LabelSelector` + as `key notin (value)` to select the group + of existing pods which pods will be taken + into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist + in the incoming pod labels will be ignored. + The default value is empty. The same key is + forbidden to exist in both MismatchLabelKeys + and LabelSelector. Also, MismatchLabelKeys + cannot be set when LabelSelector isn't set. + This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -7896,7 +9809,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -7945,6 +9859,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -8027,38 +9979,153 @@ spec: type: object type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -8079,38 +10146,153 @@ spec: type: integer type: object readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command + is simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit + status of 0 is treated as live/healthy and non-zero + is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to + be considered failed after having succeeded. Defaults to + 3. Minimum value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is + defined by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the + pod IP. You probably want to set "Host" in httpHeaders + instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: The header field name. This will be + canonicalized upon output, so case-variant names + will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to + be considered successful after having failed. Defaults to + 1. Must be 1 for liveness and startup. Minimum value is + 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP + port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the + container. Number must be in the range 1 to 65535. Name + must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to + terminate gracefully upon probe failure. The grace period + is the duration in seconds after the processes running in + the pod are sent a termination signal and the time when + the processes are forcibly halted with a kill signal. Set + this value longer than the expected cleanup time for your + process. If this value is nil, the pod's terminationGracePeriodSeconds + will be used. Otherwise, this value overrides the value + provided by the pod spec. Value must be non-negative integer. + The value zero indicates stop immediately via the kill signal + (no opportunity to shut down). This is a beta field and + requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is + used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times + out. Defaults to 1 second. Minimum value is 1. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -8639,6 +10821,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name @@ -8647,6 +11001,8 @@ spec: storage: description: Node-conf needs to be added only in redis cluster properties: + keepAfterDelete: + type: boolean nodeConfVolume: default: false type: boolean @@ -8772,30 +11128,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -8871,6 +11203,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -9019,6 +11371,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -9146,30 +11534,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -9245,6 +11609,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -9393,6 +11777,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -10044,32 +12464,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -10158,6 +12552,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -10557,6 +12977,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -11151,15 +13678,6 @@ spec: storage: true subresources: status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: ["v1beta1","v1beta2"] - clientConfig: - service: - namespace: redis-operator - name: webhook-service - path: /convert status: acceptedNames: kind: "" diff --git a/charts/redis-operator/crds/redis-replication.yaml b/charts/redis-operator/crds/redis-replication.yaml index 1e9fdbf8d..e14a87912 100644 --- a/charts/redis-operator/crds/redis-replication.yaml +++ b/charts/redis-operator/crds/redis-replication.yaml @@ -5,7 +5,6 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 - # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} creationTimestamp: null name: redisreplications.redis.redis.opstreelabs.in spec: @@ -344,7 +343,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -393,6 +393,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -502,7 +540,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -547,6 +586,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -649,7 +725,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -698,6 +775,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -807,7 +922,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -852,6 +968,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -1075,38 +1228,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1116,38 +1378,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -1277,6 +1648,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -1327,6 +1701,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -1685,6 +2228,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -1807,30 +2352,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1906,6 +2427,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -2054,6 +2595,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -2705,32 +3282,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2819,6 +3370,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -3218,6 +3795,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -3830,6 +4514,9 @@ spec: type: object status: description: RedisStatus defines the observed state of Redis + properties: + masterNode: + type: string type: object required: - spec @@ -4234,7 +4921,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4283,6 +4971,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4392,7 +5118,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4437,6 +5164,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -4539,7 +5303,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4588,6 +5353,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4697,7 +5500,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4742,6 +5546,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -5103,6 +5944,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -5250,38 +6260,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -5460,38 +6579,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -5621,6 +6849,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -5671,6 +6902,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6089,6 +7489,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name @@ -6098,6 +7670,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -6220,30 +7794,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6319,6 +7869,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -6467,6 +8037,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -7118,32 +8724,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7232,6 +8812,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -7631,6 +9237,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -8246,6 +9959,9 @@ spec: type: object status: description: RedisStatus defines the observed state of Redis + properties: + masterNode: + type: string type: object required: - spec @@ -8254,15 +9970,6 @@ spec: storage: true subresources: status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: ["v1beta1","v1beta2"] - clientConfig: - service: - namespace: redis-operator - name: webhook-service - path: /convert status: acceptedNames: kind: "" diff --git a/charts/redis-operator/crds/redis-sentinel.yaml b/charts/redis-operator/crds/redis-sentinel.yaml index 3fea9d33b..3915039ce 100644 --- a/charts/redis-operator/crds/redis-sentinel.yaml +++ b/charts/redis-operator/crds/redis-sentinel.yaml @@ -5,7 +5,6 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 - # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} creationTimestamp: null name: redissentinels.redis.redis.opstreelabs.in spec: @@ -344,7 +343,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -393,6 +393,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -502,7 +540,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -547,6 +586,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -649,7 +725,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -698,6 +775,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -807,7 +922,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -852,6 +968,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -1076,38 +1229,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1130,38 +1392,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisSentinelConfig: @@ -1188,6 +1559,87 @@ spec: type: string redisReplicationName: type: string + redisReplicationPassword: + description: EnvVarSource represents a source for the value of + an EnvVar. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only resources + limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, + requests.cpu, requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object required: - redisReplicationName type: object @@ -1921,7 +2373,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -1970,6 +2423,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2079,7 +2570,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2124,6 +2616,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -2226,7 +2755,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2275,6 +2805,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -2384,7 +2952,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -2429,6 +2998,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -2792,6 +3398,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -2939,38 +3714,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -3162,38 +4046,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisExporter: @@ -3317,6 +4310,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -3367,6 +4363,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -3394,6 +4559,87 @@ spec: type: string redisReplicationName: type: string + redisReplicationPassword: + description: EnvVarSource represents a source for the value of + an EnvVar. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, `metadata.labels['''']`, `metadata.annotations['''']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, + status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: only resources + limits and requests (limits.cpu, limits.memory, limits.ephemeral-storage, + requests.cpu, requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object required: - redisReplicationName type: object @@ -3812,6 +5058,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name @@ -3872,15 +5290,6 @@ spec: storage: true subresources: status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: ["v1beta1","v1beta2"] - clientConfig: - service: - namespace: redis-operator - name: webhook-service - path: /convert status: acceptedNames: kind: "" diff --git a/charts/redis-operator/crds/redis.yaml b/charts/redis-operator/crds/redis.yaml index cd7bac22d..3506cf20d 100644 --- a/charts/redis-operator/crds/redis.yaml +++ b/charts/redis-operator/crds/redis.yaml @@ -5,7 +5,6 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.4.1 - # cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.name }} creationTimestamp: null name: redis.redis.redis.opstreelabs.in spec: @@ -345,7 +344,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -394,6 +394,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -503,7 +541,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -548,6 +587,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -650,7 +726,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -699,6 +776,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -808,7 +923,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -853,6 +969,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -1073,38 +1226,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -1114,38 +1376,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -1275,6 +1646,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -1325,6 +1699,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -1683,6 +2226,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -1805,30 +2350,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1904,6 +2425,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -2052,6 +2593,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -2703,32 +3280,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2817,6 +3368,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -3216,6 +3793,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -4232,7 +4916,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4281,6 +4966,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4390,7 +5113,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4435,6 +5159,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -4537,7 +5298,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4586,6 +5348,44 @@ spec: The requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key in (value)` to select + the group of existing pods which pods will be + taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MatchLabelKeys and LabelSelector. Also, + MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged + with `LabelSelector` as `key notin (value)` to + select the group of existing pods which pods will + be taken into consideration for the incoming pod's + pod (anti) affinity. Keys that don't exist in + the incoming pod labels will be ignored. The default + value is empty. The same key is forbidden to exist + in both MismatchLabelKeys and LabelSelector. Also, + MismatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires + enabling MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied @@ -4695,7 +5495,8 @@ spec: properties: labelSelector: description: A label query over a set of resources, - in this case pods. + in this case pods. If it's null, this PodAffinityTerm + matches with no Pods. properties: matchExpressions: description: matchExpressions is a list of label @@ -4740,6 +5541,43 @@ spec: requirements are ANDed. type: object type: object + matchLabelKeys: + description: MatchLabelKeys is a set of pod label keys + to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key in (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MatchLabelKeys and LabelSelector. + Also, MatchLabelKeys cannot be set when LabelSelector + isn't set. This is an alpha field and requires enabling + MatchLabelKeysInPodAffinity feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: MismatchLabelKeys is a set of pod label + keys to select which pods will be taken into consideration. + The keys are used to lookup values from the incoming + pod labels, those key-value labels are merged with + `LabelSelector` as `key notin (value)` to select the + group of existing pods which pods will be taken into + consideration for the incoming pod's pod (anti) affinity. + Keys that don't exist in the incoming pod labels will + be ignored. The default value is empty. The same key + is forbidden to exist in both MismatchLabelKeys and + LabelSelector. Also, MismatchLabelKeys cannot be set + when LabelSelector isn't set. This is an alpha field + and requires enabling MatchLabelKeysInPodAffinity + feature gate. + items: + type: string + type: array + x-kubernetes-list-type: atomic namespaceSelector: description: A label query over the set of namespaces that the term applies to. The term is applied to the @@ -5098,6 +5936,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -5245,38 +6252,147 @@ spec: - image type: object livenessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object nodeSelector: @@ -5455,38 +6571,147 @@ spec: priorityClassName: type: string readinessProbe: - default: - failureThreshold: 3 - initialDelaySeconds: 1 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - description: Probe is a interface for ReadinessProbe and LivenessProbe + description: Probe describes a health check to be performed against + a container to determine whether it is alive or ready to receive + traffic. properties: + exec: + description: Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute inside + the container, the working directory for the command is + root ('/') in the container's filesystem. The command is + simply exec'd, it is not run inside a shell, so traditional + shell instructions ('|', etc) won't work. To use a shell, + you need to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object failureThreshold: - default: 3 + description: Minimum consecutive failures for the probe to be + considered failed after having succeeded. Defaults to 3. Minimum + value is 1. format: int32 - minimum: 1 type: integer + grpc: + description: GRPC specifies an action involving a GRPC port. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + description: "Service is the name of the service to place + in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + \n If this is not specified, the default behavior is defined + by gRPC." + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to the pod + IP. You probably want to set "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP allows + repeated headers. + items: + description: HTTPHeader describes a custom header to be + used in HTTP probes + properties: + name: + description: The header field name. This will be canonicalized + upon output, so case-variant names will be understood + as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the host. Defaults + to HTTP. + type: string + required: + - port + type: object initialDelaySeconds: - default: 1 + description: 'Number of seconds after the container has started + before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer periodSeconds: - default: 10 + description: How often (in seconds) to perform the probe. Default + to 10 seconds. Minimum value is 1. format: int32 - minimum: 1 type: integer successThreshold: - default: 1 + description: Minimum consecutive successes for the probe to be + considered successful after having failed. Defaults to 1. Must + be 1 for liveness and startup. Minimum value is 1. format: int32 - minimum: 1 + type: integer + tcpSocket: + description: TCPSocket specifies an action involving a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access on the container. + Number must be in the range 1 to 65535. Name must be an + IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: Optional duration in seconds the pod needs to terminate + gracefully upon probe failure. The grace period is the duration + in seconds after the processes running in the pod are sent a + termination signal and the time when the processes are forcibly + halted with a kill signal. Set this value longer than the expected + cleanup time for your process. If this value is nil, the pod's + terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. Value must + be non-negative integer. The value zero indicates stop immediately + via the kill signal (no opportunity to shut down). This is a + beta field and requires enabling ProbeTerminationGracePeriod + feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds + is used if unset. + format: int64 type: integer timeoutSeconds: - default: 1 + description: 'Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' format: int32 - minimum: 1 type: integer type: object redisConfig: @@ -5616,6 +6841,9 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string + port: + default: 9121 + type: integer resources: description: ResourceRequirements describes the compute resource requirements. @@ -5666,6 +6894,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6084,6 +7481,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name @@ -6093,6 +7662,8 @@ spec: description: Storage is the inteface to add pvc and pv support in redis properties: + keepAfterDelete: + type: boolean volumeClaimTemplate: description: PersistentVolumeClaim is a user's request for and claim to a persistent volume @@ -6215,30 +7786,6 @@ spec: must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names of resources, - defined in spec.resourceClaims, that are used by - this container. \n This is an alpha field and requires - enabling the DynamicResourceAllocation feature gate. - \n This field is immutable. It can only be set for - containers." - items: - description: ResourceClaim references one entry - in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one - entry in pod.spec.resourceClaims of the Pod - where this field is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -6314,6 +7861,26 @@ spec: description: 'storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may be used to + set the VolumeAttributesClass used by this claim. If + specified, the CSI driver will create or update the + volume with the attributes defined in the corresponding + VolumeAttributesClass. This has a different purpose + than storageClassName, it can be changed after the claim + is created. An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not allowed to + reset this field to empty string once it is set. If + unspecified and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will be set by the + persistentvolume controller if it exists. If the resource + referred to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus field, + until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied @@ -6462,6 +8029,42 @@ spec: - type type: object type: array + currentVolumeAttributesClassName: + description: currentVolumeAttributesClassName is the current + name of the VolumeAttributesClass the PVC is using. + When unset, there is no VolumeAttributeClass applied + to this PersistentVolumeClaim This is an alpha field + and requires enabling VolumeAttributesClass feature. + type: string + modifyVolumeStatus: + description: ModifyVolumeStatus represents the status + object of ControllerModifyVolume operation. When this + is unset, there is no ModifyVolume operation being attempted. + This is an alpha field and requires enabling VolumeAttributesClass + feature. + properties: + status: + description: "status is the status of the ControllerModifyVolume + operation. It can be in any of following states: + \ - Pending Pending indicates that the PersistentVolumeClaim + cannot be modified due to unmet requirements, such + as the specified VolumeAttributesClass not existing. + \ - InProgress InProgress indicates that the + volume is being modified. - Infeasible Infeasible + indicates that the request has been rejected as + invalid by the CSI driver. To \t resolve the error, + a valid VolumeAttributesClass needs to be specified. + Note: New statuses can be added in the future. Consumers + should check for unknown statuses and fail appropriately." + type: string + targetVolumeAttributesClassName: + description: targetVolumeAttributesClassName is the + name of the VolumeAttributesClass the PVC currently + being reconciled + type: string + required: + - status + type: object phase: description: phase represents the current phase of PersistentVolumeClaim. type: string @@ -7113,32 +8716,6 @@ spec: status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' properties: - claims: - description: "Claims lists the names - of resources, defined in spec.resourceClaims, - that are used by this container. \n - This is an alpha field and requires - enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. - It can only be set for containers." - items: - description: ResourceClaim references - one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the - name of one entry in pod.spec.resourceClaims - of the Pod where this field - is used. It makes that resource - available inside a container. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -7227,6 +8804,32 @@ spec: of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName + may be used to set the VolumeAttributesClass + used by this claim. If specified, the + CSI driver will create or update the volume + with the attributes defined in the corresponding + VolumeAttributesClass. This has a different + purpose than storageClassName, it can + be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s + not allowed to reset this field to empty + string once it is set. If unspecified + and the PersistentVolumeClaim is unbound, + the default VolumeAttributesClass will + be set by the persistentvolume controller + if it exists. If the resource referred + to by volumeAttributesClass does not exist, + this PersistentVolumeClaim will be set + to a Pending state, as reflected by the + modifyVolumeStatus field, until such as + a resource exists. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the + VolumeAttributesClass feature gate to + be enabled.' + type: string volumeMode: description: volumeMode defines what type of volume is required by the claim. Value @@ -7626,6 +9229,113 @@ spec: description: Projection that may be projected along with other supported volume types properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a + pod to access the `.spec.trustBundle` field + of ClusterTrustBundle objects in an auto-updating + file. \n Alpha, gated by the ClusterTrustBundleProjection + feature gate. \n ClusterTrustBundle objects + can either be selected by name, or by the + combination of signer name and a label selector. + \n Kubelet performs aggressive normalization + of the PEM contents written into the pod + filesystem. Esoteric PEM features such + as inter-block comments and block headers + are stripped. Certificates are deduplicated. + The ordering of certificates within the + file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only + has effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as + "match nothing". If set but empty, + interpreted as "match everything". + properties: + matchExpressions: + description: matchExpressions is a + list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a + set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values + array must be non-empty. If + the operator is Exists or + DoesNotExist, the values array + must be empty. This array + is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive + with signerName and labelSelector. + type: string + optional: + description: If true, don't block pod + startup if the referenced ClusterTrustBundle(s) + aren't available. If using name, then + the named ClusterTrustBundle is allowed + not to exist. If using signerName, + then the combination of signerName and + labelSelector is allowed to match zero + ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified + and deduplicated. + type: string + required: + - path + type: object configMap: description: configMap information about the configMap data to project @@ -8248,15 +9958,6 @@ spec: storage: true subresources: status: {} - conversion: - strategy: Webhook - webhook: - conversionReviewVersions: ["v1beta1","v1beta2"] - clientConfig: - service: - namespace: redis-operator - name: webhook-service - path: /convert status: acceptedNames: kind: "" diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml index 906382035..3506cf20d 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml @@ -1699,6 +1699,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -5767,6 +5936,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6556,6 +6894,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6974,6 +7481,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml index 8cd05c666..d6b10f5c5 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml @@ -455,6 +455,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6383,70 +6552,239 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object - required: - - image - type: object - kubernetesConfig: - description: KubernetesConfig will be the JSON struct for Basic Redis - Config - properties: - ignoreAnnotations: - items: - type: string - type: array - image: - type: string - imagePullPolicy: - description: PullPolicy describes a policy for if/when to pull - a container image - type: string - imagePullSecrets: - items: - description: LocalObjectReference contains enough information - to let you locate the referenced object inside the same namespace. - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - type: object - type: array - redisSecret: - description: ExistingPasswordSecret is the struct to access the - existing secret - properties: - key: - type: string - name: - type: string - type: object - resources: - description: ResourceRequirements describes the compute resource - requirements. + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. properties: - claims: - description: "Claims lists the names of resources, defined - in spec.resourceClaims, that are used by this container. - \n This is an alpha field and requires enabling the DynamicResourceAllocation - feature gate. \n This field is immutable. It can only be - set for containers." - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: Name must match the name of one entry in - pod.spec.resourceClaims of the Pod where this field - is used. It makes that resource available inside a - container. + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + required: + - image + type: object + kubernetesConfig: + description: KubernetesConfig will be the JSON struct for Basic Redis + Config + properties: + ignoreAnnotations: + items: + type: string + type: array + image: + type: string + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + imagePullSecrets: + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + redisSecret: + description: ExistingPasswordSecret is the struct to access the + existing secret + properties: + key: + type: string + name: + type: string + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: additionalProperties: anyOf: - type: integer @@ -6879,6 +7217,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -10314,6 +10821,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml index 0c3f696b1..e14a87912 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redisreplications.yaml @@ -1701,6 +1701,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -5775,6 +5944,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6564,6 +6902,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -6982,6 +7489,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 00eb3b94e..3915039ce 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -3398,6 +3398,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -4194,6 +4363,175 @@ spec: Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in both + SecurityContext and PodSecurityContext. When both are set, + the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must be set if type is "Localhost". Must NOT + be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also be + set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image type: object @@ -4720,6 +5058,178 @@ spec: cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext holds security configuration that + will be applied to a container. Some fields are present in + both SecurityContext and PodSecurityContext. When both are + set, the values in SecurityContext take precedence. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by + the container runtime. Note that this field cannot be + set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent to + root on the host. Defaults to false. Note that this field + cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to + use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a + non-root user. If true, the Kubelet will validate the + image at runtime to ensure that it does not run as UID + 0 (root) and fail to start the container if it does. If + unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value specified + in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a + random SELinux context for each container. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name is + windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile + must be preconfigured on the node to work. Must be + a descending path, relative to the kubelet's configured + seccomp profile location. Must be set if type is "Localhost". + Must NOT be set for any other type. + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - + a profile defined in a file on the node should be + used. RuntimeDefault - the container runtime default + profile should be used. Unconfined - no profile should + be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. All of a Pod's + containers must have the same effective HostProcess + value (it is not allowed to have a mix of HostProcess + containers and non-HostProcess containers). In addition, + if HostProcess is true then HostNetwork must also + be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object required: - image - name diff --git a/docs/content/en/docs/CRD Reference/Redis API/_index.md b/docs/content/en/docs/CRD Reference/Redis API/_index.md index b639bb502..1e01279c0 100644 --- a/docs/content/en/docs/CRD Reference/Redis API/_index.md +++ b/docs/content/en/docs/CRD Reference/Redis API/_index.md @@ -253,6 +253,7 @@ _Appears in:_ | `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | | `imagePullPolicy` _[ImagePullPolicy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy)_ | | | `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | #### RedisFollower @@ -323,6 +324,7 @@ _Appears in:_ | `imagePullPolicy` _[ImagePullPolicy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy)_ | | | `resources` _[ResourceRequirements](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#resourcerequirements-v1-core)_ | | | `env` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#envvar-v1-core)_ | | +| `securityContext` _[PodSecurityContext](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#podsecuritycontext-v1-core)_ | | #### Storage diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go index 1934fa291..bfecb9ab2 100644 --- a/k8sutils/redis-cluster.go +++ b/k8sutils/redis-cluster.go @@ -84,6 +84,7 @@ func generateRedisClusterInitContainerParams(cr *redisv1beta2.RedisCluster) init AdditionalEnvVariable: initContainer.EnvVars, Command: initContainer.Command, Arguments: initContainer.Args, + SecurityContext: initContainer.SecurityContext, } if cr.Spec.Storage != nil { @@ -171,6 +172,7 @@ func generateRedisClusterContainerParams(cl kubernetes.Interface, logger logr.Lo if cr.Spec.RedisExporter != nil { containerProp.RedisExporterImage = cr.Spec.RedisExporter.Image containerProp.RedisExporterImagePullPolicy = cr.Spec.RedisExporter.ImagePullPolicy + containerProp.RedisExporterSecurityContext = cr.Spec.RedisExporter.SecurityContext if cr.Spec.RedisExporter.Resources != nil { containerProp.RedisExporterResources = cr.Spec.RedisExporter.Resources diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 1d1c1d14c..5610aa17f 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -145,6 +145,7 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) if cr.Spec.RedisExporter != nil { containerProp.RedisExporterImage = cr.Spec.RedisExporter.Image containerProp.RedisExporterImagePullPolicy = cr.Spec.RedisExporter.ImagePullPolicy + containerProp.RedisExporterSecurityContext = cr.Spec.RedisExporter.SecurityContext if cr.Spec.RedisExporter.Resources != nil { containerProp.RedisExporterResources = cr.Spec.RedisExporter.Resources @@ -188,6 +189,7 @@ func generateRedisReplicationInitContainerParams(cr *redisv1beta2.RedisReplicati AdditionalEnvVariable: initContainer.EnvVars, Command: initContainer.Command, Arguments: initContainer.Args, + SecurityContext: initContainer.SecurityContext, } if cr.Spec.Storage != nil { diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index e76a7837f..9c4b4afac 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -132,6 +132,7 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in AdditionalEnvVariable: initContainer.EnvVars, Command: initContainer.Command, Arguments: initContainer.Args, + SecurityContext: initContainer.SecurityContext, } } return initcontainerProp @@ -162,6 +163,7 @@ func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes if cr.Spec.RedisExporter != nil { containerProp.RedisExporterImage = cr.Spec.RedisExporter.Image containerProp.RedisExporterImagePullPolicy = cr.Spec.RedisExporter.ImagePullPolicy + containerProp.RedisExporterSecurityContext = cr.Spec.RedisExporter.SecurityContext if cr.Spec.RedisExporter.Resources != nil { containerProp.RedisExporterResources = cr.Spec.RedisExporter.Resources diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 7a481ae95..65bcd9f7d 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -150,6 +150,7 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar if cr.Spec.RedisExporter.EnvVars != nil { containerProp.RedisExporterEnv = cr.Spec.RedisExporter.EnvVars } + containerProp.RedisExporterSecurityContext = cr.Spec.RedisExporter.SecurityContext } if cr.Spec.ReadinessProbe != nil { containerProp.ReadinessProbe = cr.Spec.ReadinessProbe @@ -186,6 +187,7 @@ func generateRedisStandaloneInitContainerParams(cr *redisv1beta2.Redis) initCont AdditionalEnvVariable: initContainer.EnvVars, Command: initContainer.Command, Arguments: initContainer.Args, + SecurityContext: initContainer.SecurityContext, } if cr.Spec.Storage != nil { diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index 2a0a5c675..b742b9864 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -117,6 +117,7 @@ type containerParameters struct { RedisExporterResources *corev1.ResourceRequirements RedisExporterEnv *[]corev1.EnvVar RedisExporterPort *int + RedisExporterSecurityContext *corev1.SecurityContext Role string EnabledPassword *bool SecretName *string @@ -145,6 +146,7 @@ type initContainerParameters struct { AdditionalEnvVariable *[]corev1.EnvVar AdditionalVolume []corev1.Volume AdditionalMountPath []corev1.VolumeMount + SecurityContext *corev1.SecurityContext } // CreateOrUpdateStateFul method will create or update Redis service @@ -436,6 +438,7 @@ func generateContainerDef(name string, containerParams containerParameters, clus Name: sidecar.Name, Image: sidecar.Image, ImagePullPolicy: sidecar.ImagePullPolicy, + SecurityContext: sidecar.SecurityContext, } if sidecar.Command != nil { container.Command = sidecar.Command @@ -471,6 +474,7 @@ func generateInitContainerDef(name string, initcontainerParams initContainerPara Command: initcontainerParams.Command, Args: initcontainerParams.Arguments, VolumeMounts: getVolumeMount(name, initcontainerParams.PersistenceEnabled, false, false, nil, mountpath, nil, nil), + SecurityContext: initcontainerParams.SecurityContext, }, } @@ -538,6 +542,7 @@ func enableRedisMonitoring(params containerParameters) corev1.Container { Protocol: corev1.ProtocolTCP, }, }, + SecurityContext: params.RedisExporterSecurityContext, } if params.RedisExporterResources != nil { exporterDefinition.Resources = *params.RedisExporterResources From 4afc8c2d169f093caf60d8fd0b9eb0f9c478f22e Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 15 Jun 2024 18:21:18 +0800 Subject: [PATCH 190/203] test: cluster connection must be run after ready (#989) * test: cluster connection must be run after ready Signed-off-by: drivebyer * remove assert Signed-off-by: drivebyer * fix Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- .../v1beta2/acl-user/redis-cluster/ready-cluster.yaml | 2 ++ .../v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml | 2 ++ .../v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml | 2 ++ .../v1beta2/password/redis-cluster/ready-cluster.yaml | 2 ++ .../v1beta2/pvc-name/redis-cluster/ready-cluster.yaml | 2 ++ .../v1beta2/scaling/redis-cluster/cluster-status-00.yaml | 4 ++-- .../v1beta2/teardown/redis-cluster/ready-cluster.yaml | 2 ++ 7 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml index 004498aff..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/acl-user/redis-cluster/ready-cluster.yaml @@ -6,3 +6,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready diff --git a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml index fb6f17085..8228c1660 100644 --- a/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/ignore-annots/redis-cluster/ready-cluster.yaml @@ -8,3 +8,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready diff --git a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml index 004498aff..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/keep-pvc/redis-cluster/ready-cluster.yaml @@ -6,3 +6,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready diff --git a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml index 004498aff..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/password/redis-cluster/ready-cluster.yaml @@ -6,3 +6,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready diff --git a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml index 004498aff..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/pvc-name/redis-cluster/ready-cluster.yaml @@ -6,3 +6,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready diff --git a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml index 3d3d27ef6..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml +++ b/tests/e2e-chainsaw/v1beta2/scaling/redis-cluster/cluster-status-00.yaml @@ -4,7 +4,7 @@ kind: RedisCluster metadata: name: redis-cluster-v1beta2 status: + readyFollowerReplicas: 3 + readyLeaderReplicas: 3 state: Ready reason: RedisCluster is ready - readyLeaderReplicas: 3 - readyFollowerReplicas: 3 diff --git a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml index 004498aff..a0708b5a5 100644 --- a/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml +++ b/tests/e2e-chainsaw/v1beta2/teardown/redis-cluster/ready-cluster.yaml @@ -6,3 +6,5 @@ metadata: status: readyFollowerReplicas: 3 readyLeaderReplicas: 3 + state: Ready + reason: RedisCluster is ready From 052d2e5e0d21b88ba6b9d5d4e9b31e51ae182a6d Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 15 Jun 2024 18:21:48 +0800 Subject: [PATCH 191/203] fix: watchNamespace value does not take effect in chart (#990) Signed-off-by: drivebyer --- charts/redis-operator/Chart.yaml | 2 +- charts/redis-operator/templates/operator-deployment.yaml | 6 +++--- charts/redis-operator/values.yaml | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/charts/redis-operator/Chart.yaml b/charts/redis-operator/Chart.yaml index 4d7a00851..2be22a517 100644 --- a/charts/redis-operator/Chart.yaml +++ b/charts/redis-operator/Chart.yaml @@ -1,6 +1,6 @@ --- apiVersion: v2 -version: 0.16.2 +version: 0.16.3 appVersion: "0.17.0" description: Provides easy redis setup definitions for Kubernetes services, and deployment. engine: gotpl diff --git a/charts/redis-operator/templates/operator-deployment.yaml b/charts/redis-operator/templates/operator-deployment.yaml index 1dea377a0..a5565d558 100644 --- a/charts/redis-operator/templates/operator-deployment.yaml +++ b/charts/redis-operator/templates/operator-deployment.yaml @@ -48,10 +48,10 @@ spec: {{- end }} env: - name: ENABLE_WEBHOOKS - value: "{{ .Values.redisOperator.webhook | toString }}" - {{- if .WATCH_NAMESPACE }} + value: {{ .Values.redisOperator.webhook | quote }} + {{- if .Values.redisOperator.watchNamespace }} - name: WATCH_NAMESPACE - value: {{ .WATCH_NAMESPACE }} + value: {{ .Values.redisOperator.watchNamespace | quote }} {{- end }} {{- range $env := .Values.redisOperator.env }} - name: {{ $env.name }} diff --git a/charts/redis-operator/values.yaml b/charts/redis-operator/values.yaml index ce7f7490e..4371f8bef 100644 --- a/charts/redis-operator/values.yaml +++ b/charts/redis-operator/values.yaml @@ -13,9 +13,8 @@ redisOperator: # Additional arguments for redis-operator container extraArgs: [] - - # - -zap-log-level=error - watch_namespace: "" + # When not specified, the operator will watch all namespaces. It can be set to a specific namespace or multiple namespaces separated by commas. + watchNamespace: "" env: [] webhook: false From b6194b03c4371fcdd370d489de07b246ab8fc336 Mon Sep 17 00:00:00 2001 From: yangw Date: Sat, 15 Jun 2024 20:58:01 +0800 Subject: [PATCH 192/203] feat: add automountServiceAccountToken values for deployment and serviceaccnount (#991) feat: add automountServiceAccountToken values for deployment and serviceaccount Signed-off-by: drivebyer --- charts/redis-operator/Chart.yaml | 2 +- charts/redis-operator/readme.md | 68 ++++++++++--------- .../templates/operator-deployment.yaml | 1 + .../templates/service-account.yaml | 1 + charts/redis-operator/values.yaml | 4 ++ 5 files changed, 42 insertions(+), 34 deletions(-) diff --git a/charts/redis-operator/Chart.yaml b/charts/redis-operator/Chart.yaml index 2be22a517..bebddf8ea 100644 --- a/charts/redis-operator/Chart.yaml +++ b/charts/redis-operator/Chart.yaml @@ -1,6 +1,6 @@ --- apiVersion: v2 -version: 0.16.3 +version: 0.16.4 appVersion: "0.17.0" description: Provides easy redis setup definitions for Kubernetes services, and deployment. engine: gotpl diff --git a/charts/redis-operator/readme.md b/charts/redis-operator/readme.md index af4be36d2..9490f52ab 100644 --- a/charts/redis-operator/readme.md +++ b/charts/redis-operator/readme.md @@ -74,39 +74,41 @@ kubectl create secret tls --key tls.key --cert tls.crt -n ## Default Values -| Parameter | Description | Default | -|-------------------------------------|------------------------------------|--------------------------------------------------------------| -| `redisOperator.name` | Operator name | `redis-operator` | -| `redisOperator.imageName` | Image repository | `quay.io/opstree/redis-operator` | -| `redisOperator.imageTag` | Image tag | `{{appVersion}}` | -| `redisOperator.imagePullPolicy` | Image pull policy | `Always` | -| `redisOperator.podAnnotations` | Additional pod annotations | `{}` | -| `redisOperator.podLabels` | Additional Pod labels | `{}` | -| `redisOperator.extraArgs` | Additional arguments for the operator | `{}` | -| `redisOperator.watch_namespace` | Namespace for the operator to watch | `""` | -| `redisOperator.env` | Environment variables for the operator | `{}` | -| `redisOperator.webhook` | Enable webhook | `false` | -| `resources.limits.cpu` | CPU limit | `500m` | -| `resources.limits.memory` | Memory limit | `500Mi` | -| `resources.requests.cpu` | CPU request | `500m` | -| `resources.requests.memory` | Memory request | `500Mi` | -| `replicas` | Number of replicas | `1` | -| `serviceAccountName` | Service account name | `redis-operator` | -| `certificate.name` | Certificate name | `serving-cert` | -| `certificate.secretName` | Certificate secret name | `webhook-server-cert` | -| `issuer.type` | Issuer type | `selfSigned` | -| `issuer.name` | Issuer name | `redis-operator-issuer` | -| `issuer.email` | Issuer email | `shubham.gupta@opstree.com` | -| `issuer.server` | Issuer server URL | `https://acme-v02.api.letsencrypt.org/directory` | -| `issuer.privateKeySecretName` | Private key secret name | `letsencrypt-prod` | -| `certManager.enabled` | Enable cert-manager | `false` | +| Parameter | Description | Default | +|-----------------------------------------------|----------------------------------------|--------------------------------------------------| +| `redisOperator.name` | Operator name | `redis-operator` | +| `redisOperator.imageName` | Image repository | `quay.io/opstree/redis-operator` | +| `redisOperator.imageTag` | Image tag | `{{appVersion}}` | +| `redisOperator.imagePullPolicy` | Image pull policy | `Always` | +| `redisOperator.podAnnotations` | Additional pod annotations | `{}` | +| `redisOperator.podLabels` | Additional Pod labels | `{}` | +| `redisOperator.extraArgs` | Additional arguments for the operator | `{}` | +| `redisOperator.watchNamespace` | Namespace for the operator to watch | `""` | +| `redisOperator.env` | Environment variables for the operator | `{}` | +| `redisOperator.webhook` | Enable webhook | `false` | +| `redisOperator.automountServiceAccountToken` | Automount service account token | `true` | +| `resources.limits.cpu` | CPU limit | `500m` | +| `resources.limits.memory` | Memory limit | `500Mi` | +| `resources.requests.cpu` | CPU request | `500m` | +| `resources.requests.memory` | Memory request | `500Mi` | +| `replicas` | Number of replicas | `1` | +| `serviceAccountName` | Service account name | `redis-operator` | +| `serviceAccount.automountServiceAccountToken` | Automount service account token | `true` | +| `certificate.name` | Certificate name | `serving-cert` | +| `certificate.secretName` | Certificate secret name | `webhook-server-cert` | +| `issuer.type` | Issuer type | `selfSigned` | +| `issuer.name` | Issuer name | `redis-operator-issuer` | +| `issuer.email` | Issuer email | `shubham.gupta@opstree.com` | +| `issuer.server` | Issuer server URL | `https://acme-v02.api.letsencrypt.org/directory` | +| `issuer.privateKeySecretName` | Private key secret name | `letsencrypt-prod` | +| `certManager.enabled` | Enable cert-manager | `false` | ## Scheduling Parameters -| Parameter | Description | Default | -|-------------------------|--------------------------------------------|----------| -| `priorityClassName` | Priority class name for the pods | `""` | -| `nodeSelector` | Labels for pod assignment | `{}` | -| `tolerateAllTaints` | Whether to tolerate all node taints | `false` | -| `tolerations` | Taints to tolerate | `[]` | -| `affinity` | Affinity rules for pod assignment | `{}` | +| Parameter | Description | Default | +|---------------------|-------------------------------------|---------| +| `priorityClassName` | Priority class name for the pods | `""` | +| `nodeSelector` | Labels for pod assignment | `{}` | +| `tolerateAllTaints` | Whether to tolerate all node taints | `false` | +| `tolerations` | Taints to tolerate | `[]` | +| `affinity` | Affinity rules for pod assignment | `{}` | diff --git a/charts/redis-operator/templates/operator-deployment.yaml b/charts/redis-operator/templates/operator-deployment.yaml index a5565d558..eb05d945d 100644 --- a/charts/redis-operator/templates/operator-deployment.yaml +++ b/charts/redis-operator/templates/operator-deployment.yaml @@ -21,6 +21,7 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} spec: + automountServiceAccountToken: {{ .Values.redisOperator.automountServiceAccountToken }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: diff --git a/charts/redis-operator/templates/service-account.yaml b/charts/redis-operator/templates/service-account.yaml index f1cbdcca7..085089e06 100644 --- a/charts/redis-operator/templates/service-account.yaml +++ b/charts/redis-operator/templates/service-account.yaml @@ -1,6 +1,7 @@ --- apiVersion: v1 kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} metadata: name: {{ .Values.redisOperator.name }} namespace: {{ .Release.Namespace }} diff --git a/charts/redis-operator/values.yaml b/charts/redis-operator/values.yaml index 4371f8bef..bd65e00ee 100644 --- a/charts/redis-operator/values.yaml +++ b/charts/redis-operator/values.yaml @@ -17,6 +17,7 @@ redisOperator: watchNamespace: "" env: [] webhook: false + automountServiceAccountToken: true resources: @@ -31,6 +32,9 @@ replicas: 1 serviceAccountName: redis-operator +serviceAccount: + automountServiceAccountToken: true + service: name: webhook-service namespace: redis-operator From 2838af46d20ea80f5e9f3f46b0ea43c9ecf6c981 Mon Sep 17 00:00:00 2001 From: yangw Date: Sun, 16 Jun 2024 23:30:24 +0800 Subject: [PATCH 193/203] fix: ReadyReplicas need to be checked in `IsStatefulSetReady` (#993) Signed-off-by: drivebyer --- controllers/rediscluster_controller.go | 16 ++-------------- k8sutils/statefulset.go | 5 ++++- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go index 6e4b9fa99..969d44291 100644 --- a/controllers/rediscluster_controller.go +++ b/controllers/rediscluster_controller.go @@ -116,18 +116,11 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request if err != nil { return intctrlutil.RequeueWithError(err, reqLogger, "") } - err = k8sutils.ReconcileRedisPodDisruptionBudget(instance, "leader", instance.Spec.RedisLeader.PodDisruptionBudget, r.K8sClient) if err != nil { return intctrlutil.RequeueWithError(err, reqLogger, "") } - // todo: remove me after watch statefulset in controller - redisLeaderInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-leader") - if err != nil { - return intctrlutil.RequeueWithError(err, reqLogger, "") - } - if r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") { // Mark the cluster status as initializing if there are no follower nodes if (instance.Status.ReadyLeaderReplicas == 0 && instance.Status.ReadyFollowerReplicas == 0) || @@ -153,11 +146,6 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request return intctrlutil.RequeueWithError(err, reqLogger, "") } } - // todo: remove me after watch statefulset in controller - redisFollowerInfo, err := k8sutils.GetStatefulSet(r.K8sClient, r.Log, instance.GetNamespace(), instance.GetName()+"-follower") - if err != nil { - return intctrlutil.RequeueWithError(err, reqLogger, "") - } if !(r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-leader") && r.IsStatefulSetReady(ctx, instance.Namespace, instance.Name+"-follower")) { return intctrlutil.Reconciled() @@ -172,7 +160,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } if nc := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, ""); nc != totalReplicas { - reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Leaders.Ready", redisLeaderInfo.Status.ReadyReplicas, "Followers.Ready", redisFollowerInfo.Status.ReadyReplicas) + reqLogger.Info("Creating redis cluster by executing cluster creation commands") leaderCount := k8sutils.CheckRedisNodeCount(ctx, r.K8sClient, r.Log, instance, "leader") if leaderCount != leaderReplicas { reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas) @@ -188,7 +176,7 @@ func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request } } } else { - if followerReplicas > 0 && redisFollowerInfo.Status.ReadyReplicas == followerReplicas { + if followerReplicas > 0 { reqLogger.Info("All leader are part of the cluster, adding follower/replicas", "Leaders.Count", leaderCount, "Instance.Size", leaderReplicas, "Follower.Replicas", followerReplicas) k8sutils.ExecuteRedisReplicationCommand(ctx, r.K8sClient, r.Log, instance) } else { diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go index b742b9864..10d5f0288 100644 --- a/k8sutils/statefulset.go +++ b/k8sutils/statefulset.go @@ -74,7 +74,10 @@ func (s *StatefulSetService) IsStatefulSetReady(ctx context.Context, namespace, logger.V(1).Info("StatefulSet is not ready", "Status.ObservedGeneration", sts.Status.ObservedGeneration, "ObjectMeta.Generation", sts.ObjectMeta.Generation) return false } - + if int(sts.Status.ReadyReplicas) != replicas { + logger.V(1).Info("StatefulSet is not ready", "Status.ReadyReplicas", sts.Status.ReadyReplicas, "Replicas", replicas) + return false + } return true } From 4f5f721c0dde8632bf0cb7c83e6381974f38f522 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:57:20 +0530 Subject: [PATCH 194/203] test: cover getSidecars (#997) Signed-off-by: Mahesh Kumar --- k8sutils/statefulset_test.go | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index b0c0fc505..8b081de2c 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -1432,3 +1432,42 @@ func TestGenerateStatefulSetsDef(t *testing.T) { }) } } + +func TestGetSidecars(t *testing.T) { + tests := []struct { + name string + sideCars *[]redisv1beta2.Sidecar + expectedSidecar []redisv1beta2.Sidecar + }{ + { + name: "TEST1_Present", + sideCars: &[]redisv1beta2.Sidecar{ + { + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + expectedSidecar: []redisv1beta2.Sidecar{ + { + Command: []string{"sh", "-c", "redis-cli -h $(hostname) -p ${REDIS_PORT} ping"}, + }, + }, + }, + { + name: "TEST2_Not_Present", + sideCars: &[]redisv1beta2.Sidecar{}, + expectedSidecar: []redisv1beta2.Sidecar{}, + }, + { + name: "TEST2_Nil", + sideCars: nil, + expectedSidecar: []redisv1beta2.Sidecar{}, + }, + } + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + result := getSidecars(test.sideCars) + assert.Equal(t, test.expectedSidecar, result) + }) + } +} From 67941336749e3faaaba60d0b1b468d596c5677f8 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar <64207192+k3mahesh@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:02:00 +0530 Subject: [PATCH 195/203] test: Cover Createorupdatestateful (#968) * test:CreateOrUpdateStateFul test case Signed-off-by: Mahesh Kumar * createorupdatestateful-test cover Signed-off-by: Mahesh Kumar * test:createorupdatestateful fixing liniting Signed-off-by: Mahesh Kumar * fixing linting Signed-off-by: Mahesh Kumar * test: createorupdatestateful cover Signed-off-by: Mahesh Kumar * test: fixing linting Signed-off-by: Mahesh Kumar * test: fixed liniting Signed-off-by: opstree * test: added new test case with error Signed-off-by: Mahesh Kumar --------- Signed-off-by: Mahesh Kumar Signed-off-by: opstree Co-authored-by: opstree --- k8sutils/statefulset_test.go | 173 +++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/k8sutils/statefulset_test.go b/k8sutils/statefulset_test.go index 8b081de2c..f7d8ea7ae 100644 --- a/k8sutils/statefulset_test.go +++ b/k8sutils/statefulset_test.go @@ -411,6 +411,179 @@ func TestUpdateStatefulSet(t *testing.T) { } } +func TestCreateOrUpdateStateFul(t *testing.T) { + logger := logr.Discard() + tests := []struct { + name string + stsParams statefulSetParameters + stsOwnerDef metav1.OwnerReference + initContainerParams initContainerParameters + containerParams containerParameters + sidecar *[]redisv1beta2.Sidecar + existingStatefulSet appsv1.StatefulSetSpec + updatedStatefulSet appsv1.StatefulSetSpec + stsPresent bool + expectErr error + }{ + { + name: "Test1_Create_Statefulset", + stsParams: statefulSetParameters{ + Replicas: ptr.To(int32(4)), + }, + stsOwnerDef: metav1.OwnerReference{ + Name: "test-sts", + }, + initContainerParams: initContainerParameters{ + Image: "redis-init:latest", + }, + containerParams: containerParameters{ + Image: "redis:latest", + ReadinessProbe: &corev1.Probe{ + InitialDelaySeconds: int32(5), + }, + LivenessProbe: &corev1.Probe{ + InitialDelaySeconds: int32(5), + }, + }, + sidecar: &[]redisv1beta2.Sidecar{ + { + Sidecar: common.Sidecar{ + Name: "redis-sidecare", + }, + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + }, + }, + existingStatefulSet: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(4)), + }, + stsPresent: false, + }, + { + name: "Test2_udpate_Statefulset", + stsParams: statefulSetParameters{ + Replicas: ptr.To(int32(4)), + }, + stsOwnerDef: metav1.OwnerReference{ + Name: "test-sts", + }, + initContainerParams: initContainerParameters{ + Image: "redis-init:latest", + }, + containerParams: containerParameters{ + Image: "redis:latest", + ReadinessProbe: &corev1.Probe{ + InitialDelaySeconds: int32(5), + }, + LivenessProbe: &corev1.Probe{ + InitialDelaySeconds: int32(5), + }, + }, + sidecar: &[]redisv1beta2.Sidecar{ + { + Sidecar: common.Sidecar{ + Name: "redis-sidecare", + }, + Command: []string{"/bin/bash", "-c", "/app/restore.bash"}, + }, + }, + existingStatefulSet: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(4)), + }, + updatedStatefulSet: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(6)), + }, + stsPresent: true, + }, + { + name: "Test3_Create_Statefulset_With_Error", + stsParams: statefulSetParameters{ + Replicas: ptr.To(int32(4)), + }, + stsOwnerDef: metav1.OwnerReference{ + Name: "test-sts", + }, + initContainerParams: initContainerParameters{ + Image: "redis-init:latest", + }, + containerParams: containerParameters{ + Image: "redis:latest", + ReadinessProbe: &corev1.Probe{ + InitialDelaySeconds: int32(5), + }, + LivenessProbe: &corev1.Probe{ + InitialDelaySeconds: int32(5), + }, + }, + sidecar: &[]redisv1beta2.Sidecar{}, + existingStatefulSet: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(4)), + }, + updatedStatefulSet: appsv1.StatefulSetSpec{ + Replicas: ptr.To(int32(-6)), + }, + stsPresent: false, + expectErr: kerrors.NewBadRequest("Invalid Value of Replicas"), + }, + } + + assert := assert.New(t) + + for i := range tests { + test := tests[i] + t.Run(test.name, func(t *testing.T) { + var client *k8sClientFake.Clientset + + if test.stsPresent { + existingSts := appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + Spec: *test.existingStatefulSet.DeepCopy(), + } + + updatedSts := appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "test-ns", + }, + Spec: *test.updatedStatefulSet.DeepCopy(), + } + if test.stsPresent { + client = k8sClientFake.NewSimpleClientset(existingSts.DeepCopy()) + } else { + client = k8sClientFake.NewSimpleClientset() + } + err := CreateOrUpdateStateFul(client, logger, updatedSts.GetNamespace(), updatedSts.ObjectMeta, test.stsParams, test.stsOwnerDef, test.initContainerParams, test.containerParams, test.sidecar) + if test.expectErr != nil { + assert.Error(err, "Expected Error while updating Statefulset") + assert.Equal(test.expectErr, err) + } else { + assert.NoError(err, "Error while updating Statefulset") + } + if err == nil { + getUpdatedSts, err := client.AppsV1().StatefulSets(updatedSts.GetNamespace()).Get(context.TODO(), updatedSts.GetName(), metav1.GetOptions{}) + assert.NoError(err) + assert.NotEqual(getUpdatedSts.DeepCopy(), existingSts.DeepCopy(), "StatefulSet Updated") + } + } else { + updatedSts := appsv1.StatefulSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sts", + Namespace: "", + }, + Spec: *test.updatedStatefulSet.DeepCopy(), + } + + client = k8sClientFake.NewSimpleClientset() + + err := CreateOrUpdateStateFul(client, logger, updatedSts.GetNamespace(), updatedSts.ObjectMeta, test.stsParams, test.stsOwnerDef, test.initContainerParams, test.containerParams, test.sidecar) + assert.Nil(err) + } + }) + } +} + func TestEnableRedisMonitoring(t *testing.T) { tests := []struct { name string From 909d9e4a7fceee98c6e7e5f43efc95882869cde5 Mon Sep 17 00:00:00 2001 From: Laurentiu Soica Date: Wed, 19 Jun 2024 10:18:17 +0300 Subject: [PATCH 196/203] feat: add support for extra volume mounts for redis sentinel (#994) * feat: add support for extra volume mounts for redis sentinel Signed-off-by: laurentiusoica * fix: add tests Signed-off-by: laurentiusoica * fix: yaml lint Signed-off-by: laurentiusoica * fix: docs Signed-off-by: laurentiusoica --------- Signed-off-by: laurentiusoica Co-authored-by: laurentiusoica --- api/v1beta2/redissentinel_types.go | 1 + api/v1beta2/zz_generated.deepcopy.go | 5 + .../redis-operator/crds/redis-sentinel.yaml | 1745 +++++++++++++++++ ...s.redis.opstreelabs.in_redissentinels.yaml | 1745 +++++++++++++++++ .../en/docs/CRD Reference/Redis API/_index.md | 14 + k8sutils/redis-sentinel.go | 8 + k8sutils/redis-sentinel_test.go | 35 + tests/testdata/redis-sentinel.yaml | 7 + 8 files changed, 3560 insertions(+) diff --git a/api/v1beta2/redissentinel_types.go b/api/v1beta2/redissentinel_types.go index 53837c04b..bca8c8672 100644 --- a/api/v1beta2/redissentinel_types.go +++ b/api/v1beta2/redissentinel_types.go @@ -28,6 +28,7 @@ type RedisSentinelSpec struct { ServiceAccountName *string `json:"serviceAccountName,omitempty"` TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"` EnvVars *[]corev1.EnvVar `json:"env,omitempty"` + VolumeMount *common.AdditionalVolume `json:"volumeMount,omitempty"` } func (cr *RedisSentinelSpec) GetSentinelCounts(t string) int32 { diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 71323c66c..63c729e0f 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -857,6 +857,11 @@ func (in *RedisSentinelSpec) DeepCopyInto(out *RedisSentinelSpec) { } } } + if in.VolumeMount != nil { + in, out := &in.VolumeMount, &out.VolumeMount + *out = new(api.AdditionalVolume) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisSentinelSpec. diff --git a/charts/redis-operator/crds/redis-sentinel.yaml b/charts/redis-operator/crds/redis-sentinel.yaml index 3915039ce..42305a4ed 100644 --- a/charts/redis-operator/crds/redis-sentinel.yaml +++ b/charts/redis-operator/crds/redis-sentinel.yaml @@ -5277,6 +5277,1751 @@ spec: type: string type: object type: array + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the + blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure managed + data disk (only in managed availability set). defaults + to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados user + name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume in + cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If a + key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the + associated CSI driver which will determine the default + filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to + the secret object containing sensitive information + to pass to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the + secret object contains more than one secret, all secret + references are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. Consult + your driver's documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name and namespace + are supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to set + permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict with + other options that affect the file mode, like + fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path. Must + be utf-8 encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default is + "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The size + limit is also applicable for memory medium. The maximum + usage on memory medium EmptyDir would be the minimum + value between the SizeLimit specified here and the + sum of memory limits of all containers in a pod. The + default is nil which means that the limit is undefined. + More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is + tied to the pod that defines it - it will be created before + the pod starts, and deleted when the pod is removed. \n + Use this if: a) the volume is only needed while the pod + runs, b) features of normal volumes like restoring from + snapshot or capacity tracking are needed, c) the storage + driver is specified through a storage class, and d) the + storage driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between this + volume type and PersistentVolumeClaim). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + Use CSI for light-weight local ephemeral volumes if the + CSI driver is meant to be used that way - see the documentation + of the driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes at the + same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC + to provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the + PVC will be deleted together with the pod. The name + of the PVC will be `-` where + `` is the name from the `PodSpec.Volumes` + array entry. Pod validation will reject the pod if + the concatenated name is not valid for a PVC (for + example, too long). \n An existing PVC with that name + that is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by mistake. + Starting the pod is then blocked until the unrelated + PVC is removed. If such a pre-created PVC is meant + to be used by the pod, the PVC has to updated with + an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may + be useful when manually reconstructing a broken cluster. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be rejected + during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the + PVC that gets created from this template. The + same fields as in a PersistentVolumeClaim are + also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to + specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, it + will create a new volume based on the contents + of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents + will be copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource when + dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, + if a non-empty volume is desired. This may + be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding + will only succeed if the type of the specified + object matches some installed volume populator + or dynamic provisioner. This field will replace + the functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same + value automatically if one of them is empty + and the other is non-empty. When namespace + is specified in dataSourceRef, dataSource + isn''t set to the same value and must be empty. + There are three important differences between + dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, + dataSourceRef allows any non-core object, + as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves + all values, and generates an error if a disallowed + value is specified. * While dataSource only + allows local objects, dataSourceRef allows + objects in any namespaces. (Beta) Using + this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using + the namespace field of dataSourceRef requires + the CrossNamespaceVolumeDataSource feature + gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note that + when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. (Alpha) This + field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than + previous value but must still be higher than + capacity recorded in the status field of the + claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of + the StorageClass required by the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may + be used to set the VolumeAttributesClass used + by this claim. If specified, the CSI driver + will create or update the volume with the + attributes defined in the corresponding VolumeAttributesClass. + This has a different purpose than storageClassName, + it can be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not + allowed to reset this field to empty string + once it is set. If unspecified and the PersistentVolumeClaim + is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller + if it exists. If the resource referred to + by volumeAttributesClass does not exist, this + PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus + field, until such as a resource exists. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. Value of + Filesystem is implied when not included in + claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. TODO: how do we prevent + errors in the filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs + and lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use + for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". The default filesystem + depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if + no secret object is specified. If the secret object + contains more than one secret, all secrets are passed + to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored + as metadata -> name on the dataset for Flocker should + be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then + exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an + InitContainer that clones the repo using git, then mount + the EmptyDir into the Pod''s container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is supplied, + the volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. Defaults + to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or + directory on the host machine that is directly exposed + to the container. This is generally used for system agents + or other privileged things that are allowed to see the + host machine. Most containers will NOT need this. More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write.' + properties: + path: + description: 'path of the directory on the host. If + the path is a symlink, it will follow the link to + the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that + uses an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + The portal is either an IP or ip_addr:port if the + port is other than default (typically TCP ports 860 + and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. The + Portal is either an IP or ip_addr:port if the port + is other than default (typically TCP ports 860 and + 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and + unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Directories within the path are not affected by this + setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a pod + to access the `.spec.trustBundle` field of ClusterTrustBundle + objects in an auto-updating file. \n Alpha, + gated by the ClusterTrustBundleProjection feature + gate. \n ClusterTrustBundle objects can either + be selected by name, or by the combination of + signer name and a label selector. \n Kubelet + performs aggressive normalization of the PEM + contents written into the pod filesystem. Esoteric + PEM features such as inter-block comments and + block headers are stripped. Certificates are + deduplicated. The ordering of certificates within + the file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only has + effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as "match + nothing". If set but empty, interpreted + as "match everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive with + signerName and labelSelector. + type: string + optional: + description: If true, don't block pod startup + if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the + named ClusterTrustBundle is allowed not + to exist. If using signerName, then the + combination of signerName and labelSelector + is allowed to match zero ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified and + deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + ConfigMap will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. Paths + must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether the + ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about the + downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and + 0777 or a decimal value between 0 + and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path. Must be utf-8 + encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + Secret will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the Secret, the volume setup will error + unless it is marked optional. Paths must + be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if + the token is older than 80 percent of its + time to live or if the token is older than + 24 hours.Defaults to 1 hour and must be + at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to + the mount point of the file to project the + token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is + no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults + to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string as + host:port pair (multiple entries are separated with + commas) which acts as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is + rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default is + admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for + ScaleIO user and other sensitive information. If this + is not provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair + in the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, the + listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is + specified which is not present in the Secret, the + volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in + the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within + StorageOS for tighter integration. Set VolumeName + to any name to override the default behaviour. Set + to "default" if you are not using namespaces within + StorageOS. Namespaces that do not pre-exist within + StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object required: - clusterSize - kubernetesConfig diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml index 3915039ce..42305a4ed 100644 --- a/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml +++ b/config/crd/bases/redis.redis.opstreelabs.in_redissentinels.yaml @@ -5277,6 +5277,1751 @@ spec: type: string type: object type: array + volumeMount: + description: Additional Volume is provided by user that is mounted + on the pods + properties: + mountPath: + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volume: + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'awsElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty).' + format: int32 + type: integer + readOnly: + description: 'readOnly value true will force the readOnly + setting in VolumeMounts. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'volumeID is unique ID of the persistent + disk resource in AWS (Amazon EBS volume). More info: + https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: azureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'cachingMode is the Host Caching mode: + None, Read Only, Read Write.' + type: string + diskName: + description: diskName is the Name of the data disk in + the blob storage + type: string + diskURI: + description: diskURI is the URI of data disk in the + blob storage + type: string + fsType: + description: fsType is Filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + kind: + description: 'kind expected values are Shared: multiple + blob disks per storage account Dedicated: single + blob disk per storage account Managed: azure managed + data disk (only in managed availability set). defaults + to shared' + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: azureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: secretName is the name of secret that + contains Azure Storage Account Name and Key + type: string + shareName: + description: shareName is the azure share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: cephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'monitors is Required: Monitors is a collection + of Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'path is Optional: Used as the mounted + root, rather than the full Ceph tree, default is /' + type: string + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'secretFile is Optional: SecretFile is + the path to key ring for User, default is /etc/ceph/user.secret + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'secretRef is Optional: SecretRef is reference + to the authentication secret for User, default is + empty. More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is optional: User is the rados user + name, default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Examples: "ext4", "xfs", "ntfs". Implicitly + inferred to be "ext4" if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'secretRef is optional: points to a secret + object containing parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeID: + description: 'volumeID used to identify the volume in + cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: configMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'defaultMode is optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items if unspecified, each key-value pair + in the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If a + key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: optional specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + csi: + description: csi (Container Storage Interface) represents + ephemeral storage that is handled by certain external + CSI drivers (Beta feature). + properties: + driver: + description: driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: fsType to mount. Ex. "ext4", "xfs", "ntfs". + If not provided, the empty value is passed to the + associated CSI driver which will determine the default + filesystem to apply. + type: string + nodePublishSecretRef: + description: nodePublishSecretRef is a reference to + the secret object containing sensitive information + to pass to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the + secret object contains more than one secret, all secret + references are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + readOnly: + description: readOnly specifies a read-only configuration + for the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: volumeAttributes stores driver-specific + properties that are passed to the CSI driver. Consult + your driver's documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: downwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name and namespace + are supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to set + permissions on this file, must be an octal value + between 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode + bits. If not specified, the volume defaultMode + will be used. This might be in conflict with + other options that affect the file mode, like + fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path. Must + be utf-8 encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'emptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'medium represents what type of storage + medium should back this directory. The default is + "" which means to use the node''s default medium. + Must be an empty string (default) or Memory. More + info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'sizeLimit is the total amount of local + storage required for this EmptyDir volume. The size + limit is also applicable for memory medium. The maximum + usage on memory medium EmptyDir would be the minimum + value between the SizeLimit specified here and the + sum of memory limits of all containers in a pod. The + default is nil which means that the limit is undefined. + More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + description: "ephemeral represents a volume that is handled + by a cluster storage driver. The volume's lifecycle is + tied to the pod that defines it - it will be created before + the pod starts, and deleted when the pod is removed. \n + Use this if: a) the volume is only needed while the pod + runs, b) features of normal volumes like restoring from + snapshot or capacity tracking are needed, c) the storage + driver is specified through a storage class, and d) the + storage driver supports dynamic volume provisioning through + \ a PersistentVolumeClaim (see EphemeralVolumeSource + for more information on the connection between this + volume type and PersistentVolumeClaim). \n Use PersistentVolumeClaim + or one of the vendor-specific APIs for volumes that persist + for longer than the lifecycle of an individual pod. \n + Use CSI for light-weight local ephemeral volumes if the + CSI driver is meant to be used that way - see the documentation + of the driver for more information. \n A pod can use both + types of ephemeral volumes and persistent volumes at the + same time." + properties: + volumeClaimTemplate: + description: "Will be used to create a stand-alone PVC + to provision the volume. The pod in which this EphemeralVolumeSource + is embedded will be the owner of the PVC, i.e. the + PVC will be deleted together with the pod. The name + of the PVC will be `-` where + `` is the name from the `PodSpec.Volumes` + array entry. Pod validation will reject the pod if + the concatenated name is not valid for a PVC (for + example, too long). \n An existing PVC with that name + that is not owned by the pod will *not* be used for + the pod to avoid using an unrelated volume by mistake. + Starting the pod is then blocked until the unrelated + PVC is removed. If such a pre-created PVC is meant + to be used by the pod, the PVC has to updated with + an owner reference to the pod once the pod exists. + Normally this should not be necessary, but it may + be useful when manually reconstructing a broken cluster. + \n This field is read-only and no changes will be + made by Kubernetes to the PVC after it has been created. + \n Required, must not be nil." + properties: + metadata: + description: May contain labels and annotations + that will be copied into the PVC when creating + it. No other fields are allowed and will be rejected + during validation. + type: object + spec: + description: The specification for the PersistentVolumeClaim. + The entire content is copied unchanged into the + PVC that gets created from this template. The + same fields as in a PersistentVolumeClaim are + also valid here. + properties: + accessModes: + description: 'accessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to + specify either: * An existing VolumeSnapshot + object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) + If the provisioner or an external controller + can support the specified data source, it + will create a new volume based on the contents + of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents + will be copied to dataSourceRef, and dataSourceRef + contents will be copied to dataSource when + dataSourceRef.namespace is not specified. + If the namespace is specified, then dataSourceRef + will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + dataSourceRef: + description: 'dataSourceRef specifies the object + from which to populate the volume with data, + if a non-empty volume is desired. This may + be any object from a non-empty API group (non + core object) or a PersistentVolumeClaim object. + When this field is specified, volume binding + will only succeed if the type of the specified + object matches some installed volume populator + or dynamic provisioner. This field will replace + the functionality of the dataSource field + and as such if both fields are non-empty, + they must have the same value. For backwards + compatibility, when namespace isn''t specified + in dataSourceRef, both fields (dataSource + and dataSourceRef) will be set to the same + value automatically if one of them is empty + and the other is non-empty. When namespace + is specified in dataSourceRef, dataSource + isn''t set to the same value and must be empty. + There are three important differences between + dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, + dataSourceRef allows any non-core object, + as well as PersistentVolumeClaim objects. + * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves + all values, and generates an error if a disallowed + value is specified. * While dataSource only + allows local objects, dataSourceRef allows + objects in any namespaces. (Beta) Using + this field requires the AnyVolumeDataSource + feature gate to be enabled. (Alpha) Using + the namespace field of dataSourceRef requires + the CrossNamespaceVolumeDataSource feature + gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + namespace: + description: Namespace is the namespace + of resource being referenced Note that + when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant + object is required in the referent namespace + to allow that namespace's owner to accept + the reference. See the ReferenceGrant + documentation for details. (Alpha) This + field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum + resources the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify + resource requirements that are lower than + previous value but must still be higher than + capacity recorded in the status field of the + claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over + volumes to consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'storageClassName is the name of + the StorageClass required by the claim. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeAttributesClassName: + description: 'volumeAttributesClassName may + be used to set the VolumeAttributesClass used + by this claim. If specified, the CSI driver + will create or update the volume with the + attributes defined in the corresponding VolumeAttributesClass. + This has a different purpose than storageClassName, + it can be changed after the claim is created. + An empty string value means that no VolumeAttributesClass + will be applied to the claim but it''s not + allowed to reset this field to empty string + once it is set. If unspecified and the PersistentVolumeClaim + is unbound, the default VolumeAttributesClass + will be set by the persistentvolume controller + if it exists. If the resource referred to + by volumeAttributesClass does not exist, this + PersistentVolumeClaim will be set to a Pending + state, as reflected by the modifyVolumeStatus + field, until such as a resource exists. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass + (Alpha) Using this field requires the VolumeAttributesClass + feature gate to be enabled.' + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. Value of + Filesystem is implied when not included in + claim spec. + type: string + volumeName: + description: volumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - spec + type: object + type: object + fc: + description: fc represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: 'fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. TODO: how do we prevent + errors in the filesystem from compromising the machine' + type: string + lun: + description: 'lun is Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'readOnly is Optional: Defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'targetWWNs is Optional: FC target worldwide + names (WWNs)' + items: + type: string + type: array + wwids: + description: 'wwids Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs + and lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: flexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: driver is the name of the driver to use + for this volume. + type: string + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". The default filesystem + depends on FlexVolume script. + type: string + options: + additionalProperties: + type: string + description: 'options is Optional: this field holds + extra command options if any.' + type: object + readOnly: + description: 'readOnly is Optional: defaults to false + (read/write). ReadOnly here will force the ReadOnly + setting in VolumeMounts.' + type: boolean + secretRef: + description: 'secretRef is Optional: secretRef is reference + to the secret object containing sensitive information + to pass to the plugin scripts. This may be empty if + no secret object is specified. If the secret object + contains more than one secret, all secrets are passed + to the plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: datasetName is Name of the dataset stored + as metadata -> name on the dataset for Flocker should + be considered as deprecated + type: string + datasetUUID: + description: datasetUUID is the UUID of the dataset. + This is unique identifier of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'gcePersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then + exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'fsType is filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'partition is the partition in the volume + that you want to mount. If omitted, the default is + to mount by volume name. Examples: For volume /dev/sda1, + you specify the partition as "1". Similarly, the volume + partition for /dev/sda is "0" (or you can leave the + property empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'pdName is unique name of the PD resource + in GCE. Used to identify the disk in GCE. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'gitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an + InitContainer that clones the repo using git, then mount + the EmptyDir into the Pod''s container.' + properties: + directory: + description: directory is the target directory name. + Must not contain or start with '..'. If '.' is supplied, + the volume directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: repository is the URL + type: string + revision: + description: revision is the commit hash for the specified + revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'glusterfs represents a Glusterfs mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'endpoints is the endpoint name that details + Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'readOnly here will force the Glusterfs + volume to be mounted with read-only permissions. Defaults + to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'hostPath represents a pre-existing file or + directory on the host machine that is directly exposed + to the container. This is generally used for system agents + or other privileged things that are allowed to see the + host machine. Most containers will NOT need this. More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write.' + properties: + path: + description: 'path of the directory on the host. If + the path is a symlink, it will follow the link to + the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'iscsi represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: chapAuthDiscovery defines whether support + iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: chapAuthSession defines whether support + iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: initiatorName is the custom iSCSI Initiator + Name. If initiatorName is specified with iscsiInterface + simultaneously, new iSCSI interface : will be created for the connection. + type: string + iqn: + description: iqn is the target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iscsiInterface is the interface Name that + uses an iSCSI transport. Defaults to 'default' (tcp). + type: string + lun: + description: lun represents iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: portals is the iSCSI Target Portal List. + The portal is either an IP or ip_addr:port if the + port is other than default (typically TCP ports 860 + and 3260). + items: + type: string + type: array + readOnly: + description: readOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: secretRef is the CHAP Secret for iSCSI + target and initiator authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + targetPortal: + description: targetPortal is iSCSI Target Portal. The + Portal is either an IP or ip_addr:port if the port + is other than default (typically TCP ports 860 and + 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'name of the volume. Must be a DNS_LABEL and + unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'nfs represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'readOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'persistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'claimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: readOnly Will force the ReadOnly setting + in VolumeMounts. Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: photonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + pdID: + description: pdID is the ID that identifies Photon Controller + persistent disk + type: string + required: + - pdID + type: object + portworxVolume: + description: portworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: fSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: volumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: projected items for all in one resources secrets, + configmaps, and downward API + properties: + defaultMode: + description: defaultMode are the mode bits used to set + permissions on created files by default. Must be an + octal value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal and decimal + values, JSON requires decimal values for mode bits. + Directories within the path are not affected by this + setting. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set. + format: int32 + type: integer + sources: + description: sources is the list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + clusterTrustBundle: + description: "ClusterTrustBundle allows a pod + to access the `.spec.trustBundle` field of ClusterTrustBundle + objects in an auto-updating file. \n Alpha, + gated by the ClusterTrustBundleProjection feature + gate. \n ClusterTrustBundle objects can either + be selected by name, or by the combination of + signer name and a label selector. \n Kubelet + performs aggressive normalization of the PEM + contents written into the pod filesystem. Esoteric + PEM features such as inter-block comments and + block headers are stripped. Certificates are + deduplicated. The ordering of certificates within + the file is arbitrary, and Kubelet may change + the order over time." + properties: + labelSelector: + description: Select all ClusterTrustBundles + that match this label selector. Only has + effect if signerName is set. Mutually-exclusive + with name. If unset, interpreted as "match + nothing". If set but empty, interpreted + as "match everything". + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + name: + description: Select a single ClusterTrustBundle + by object name. Mutually-exclusive with + signerName and labelSelector. + type: string + optional: + description: If true, don't block pod startup + if the referenced ClusterTrustBundle(s) + aren't available. If using name, then the + named ClusterTrustBundle is allowed not + to exist. If using signerName, then the + combination of signerName and labelSelector + is allowed to match zero ClusterTrustBundles. + type: boolean + path: + description: Relative path from the volume + root to write the bundle. + type: string + signerName: + description: Select all ClusterTrustBundles + that match this signer name. Mutually-exclusive + with name. The contents of all selected + ClusterTrustBundles will be unified and + deduplicated. + type: string + required: + - path + type: object + configMap: + description: configMap information about the configMap + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + ConfigMap will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. Paths + must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional specify whether the + ConfigMap or its keys must be defined + type: boolean + type: object + downwardAPI: + description: downwardAPI information about the + downwardAPI data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and + 0777 or a decimal value between 0 + and 511. YAML accepts both octal and + decimal values, JSON requires decimal + values for mode bits. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path. Must be utf-8 + encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: secret information about the secret + data to project + properties: + items: + description: items if unspecified, each key-value + pair in the Data field of the referenced + Secret will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the Secret, the volume setup will error + unless it is marked optional. Paths must + be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode + bits used to set permissions on this + file. Must be an octal value between + 0000 and 0777 or a decimal value between + 0 and 511. YAML accepts both octal + and decimal values, JSON requires + decimal values for mode bits. If not + specified, the volume defaultMode + will be used. This might be in conflict + with other options that affect the + file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: path is the relative path + of the file to map the key to. May + not be an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: optional field specify whether + the Secret or its key must be defined + type: boolean + type: object + serviceAccountToken: + description: serviceAccountToken is information + about the serviceAccountToken data to project + properties: + audience: + description: audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: expirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if + the token is older than 80 percent of its + time to live or if the token is older than + 24 hours.Defaults to 1 hour and must be + at least 10 minutes. + format: int64 + type: integer + path: + description: path is the path relative to + the mount point of the file to project the + token into. + type: string + required: + - path + type: object + type: object + type: array + type: object + quobyte: + description: quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: group to map volume access to Default is + no group + type: string + readOnly: + description: readOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults + to false. + type: boolean + registry: + description: registry represents a single or multiple + Quobyte Registry services specified as a string as + host:port pair (multiple entries are separated with + commas) which acts as the central registry for volumes + type: string + tenant: + description: tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: user to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'rbd represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'fsType is the filesystem type of the volume + that you want to mount. Tip: Ensure that the filesystem + type is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'image is the rados image name. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'monitors is a collection of Ceph monitors. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'pool is the rados pool name. Default is + rbd. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'readOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'secretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'user is the rados user name. Default is + admin. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: scaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: gateway is the host address of the ScaleIO + API Gateway. + type: string + protectionDomain: + description: protectionDomain is the name of the ScaleIO + Protection Domain for the configured storage. + type: string + readOnly: + description: readOnly Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef references to the secret for + ScaleIO user and other sensitive information. If this + is not provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + sslEnabled: + description: sslEnabled Flag enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: storageMode indicates whether the storage + for a volume should be ThickProvisioned or ThinProvisioned. + Default is ThinProvisioned. + type: string + storagePool: + description: storagePool is the ScaleIO Storage Pool + associated with the protection domain. + type: string + system: + description: system is the name of the storage system + as configured in ScaleIO. + type: string + volumeName: + description: volumeName is the name of a volume already + created in the ScaleIO system that is associated with + this volume source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'defaultMode is Optional: mode bits used + to set permissions on created files by default. Must + be an octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal and + decimal values, JSON requires decimal values for mode + bits. Defaults to 0644. Directories within the path + are not affected by this setting. This might be in + conflict with other options that affect the file mode, + like fsGroup, and the result can be other mode bits + set.' + format: int32 + type: integer + items: + description: items If unspecified, each key-value pair + in the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, the + listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is + specified which is not present in the Secret, the + volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: key is the key to project. + type: string + mode: + description: 'mode is Optional: mode bits used + to set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume + defaultMode will be used. This might be in conflict + with other options that affect the file mode, + like fsGroup, and the result can be other mode + bits set.' + format: int32 + type: integer + path: + description: path is the relative path of the + file to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: optional field specify whether the Secret + or its keys must be defined + type: boolean + secretName: + description: 'secretName is the name of the secret in + the pod''s namespace to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: storageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: fsType is the filesystem type to mount. + Must be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: readOnly defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: secretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeName: + description: volumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: volumeNamespace specifies the scope of + the volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within + StorageOS for tighter integration. Set VolumeName + to any name to override the default behaviour. Set + to "default" if you are not using namespaces within + StorageOS. Namespaces that do not pre-exist within + StorageOS will be created. + type: string + type: object + vsphereVolume: + description: vsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: fsType is filesystem type to mount. Must + be a filesystem type supported by the host operating + system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + storagePolicyID: + description: storagePolicyID is the storage Policy Based + Management (SPBM) profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: storagePolicyName is the storage Policy + Based Management (SPBM) profile name. + type: string + volumePath: + description: volumePath is the path that identifies + vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object required: - clusterSize - kubernetesConfig diff --git a/docs/content/en/docs/CRD Reference/Redis API/_index.md b/docs/content/en/docs/CRD Reference/Redis API/_index.md index 1e01279c0..f0331d16c 100644 --- a/docs/content/en/docs/CRD Reference/Redis API/_index.md +++ b/docs/content/en/docs/CRD Reference/Redis API/_index.md @@ -57,6 +57,19 @@ _Appears in:_ | `imagePullSecrets` _[LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#localobjectreference-v1-core)_ | | | `updateStrategy` _[StatefulSetUpdateStrategy](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#statefulsetupdatestrategy-v1-apps)_ | | +#### VolumeMount + +Mount External Volumes + +_Appears in:_ + +- [RedisSentinel](#redissentinelspec) + +| Field | Description | +| --- | --- | +| `volume` _[Volume Array](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volume-v1-core)_ | | +| `mountPath` _[VolumeMount Array](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#volumemount-v1-core)_ | | + #### Redis Redis is the Schema for the redis API @@ -202,6 +215,7 @@ _Appears in:_ | `livenessProbe` _[Probe](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#probe-v1-core)_ | | | `sidecars` _[Sidecar](#sidecar)_ | | | `serviceAccountName` _string_ | | +| `volumeMount` _[VolumeMount](#volumemount)_ | | #### RedisConfig diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 9c4b4afac..6f83d37bc 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -134,6 +134,10 @@ func generateRedisSentinelInitContainerParams(cr *redisv1beta2.RedisSentinel) in Arguments: initContainer.Args, SecurityContext: initContainer.SecurityContext, } + if cr.Spec.VolumeMount != nil { + initcontainerProp.AdditionalVolume = cr.Spec.VolumeMount.Volume + initcontainerProp.AdditionalMountPath = cr.Spec.VolumeMount.MountPath + } } return initcontainerProp } @@ -153,6 +157,10 @@ func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars } + if cr.Spec.VolumeMount != nil { + containerProp.AdditionalVolume = cr.Spec.VolumeMount.Volume + containerProp.AdditionalMountPath = cr.Spec.VolumeMount.MountPath + } if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil { containerProp.EnabledPassword = &trueProperty containerProp.SecretName = cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index 473f8786a..eb19e5d1b 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -12,6 +12,7 @@ import ( "github.com/go-logr/logr" "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/yaml" @@ -175,6 +176,23 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { Value: "custom_value_2", }, }, + AdditionalVolume: []v1.Volume{ + { + Name: "redis-config", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + AdditionalMountPath: []v1.VolumeMount{ + { + Name: "redis-config", + ReadOnly: false, + MountPath: "/etc/redis", + SubPath: "", + SubPathExpr: "", + }, + }, } data, err := os.ReadFile(path) @@ -235,6 +253,23 @@ func Test_generateRedisSentinelInitContainerParams(t *testing.T) { }, }, }, + AdditionalVolume: []v1.Volume{ + { + Name: "redis-config", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + AdditionalMountPath: []v1.VolumeMount{ + { + Name: "redis-config", + ReadOnly: false, + MountPath: "/etc/redis", + SubPath: "", + SubPathExpr: "", + }, + }, } data, err := os.ReadFile(path) diff --git a/tests/testdata/redis-sentinel.yaml b/tests/testdata/redis-sentinel.yaml index f102f92f2..a183960c5 100644 --- a/tests/testdata/redis-sentinel.yaml +++ b/tests/testdata/redis-sentinel.yaml @@ -116,3 +116,10 @@ spec: secretKeyRef: name: env-secrets key: CLUSTER_NAMESPACE + volumeMount: + mountPath: + - mountPath: /etc/redis + name: redis-config + volume: + - emptyDir: {} + name: redis-config From c58d54f69fa153c4047ec14c9f1670dc3dcbbc3c Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 19 Jun 2024 20:58:01 +0800 Subject: [PATCH 197/203] fix: add default port to enable `SENTINEL_PORT` environment (#999) * fix: add default port to enable `SENTINEL_PORT` environment Signed-off-by: drivebyer * fix test Signed-off-by: drivebyer --------- Signed-off-by: drivebyer --- k8sutils/redis-replication.go | 2 +- k8sutils/redis-sentinel.go | 1 + k8sutils/redis-sentinel_test.go | 1 + k8sutils/redis-standalone.go | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/k8sutils/redis-replication.go b/k8sutils/redis-replication.go index 5610aa17f..545d9b079 100644 --- a/k8sutils/redis-replication.go +++ b/k8sutils/redis-replication.go @@ -125,7 +125,7 @@ func generateRedisReplicationContainerParams(cr *redisv1beta2.RedisReplication) ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - Port: ptr.To(6379), + Port: ptr.To(redisPort), } if cr.Spec.EnvVars != nil { containerProp.EnvVars = cr.Spec.EnvVars diff --git a/k8sutils/redis-sentinel.go b/k8sutils/redis-sentinel.go index 6f83d37bc..1a985b1eb 100644 --- a/k8sutils/redis-sentinel.go +++ b/k8sutils/redis-sentinel.go @@ -152,6 +152,7 @@ func generateRedisSentinelContainerParams(ctx context.Context, client kubernetes ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, + Port: ptr.To(sentinelPort), AdditionalEnvVariable: getSentinelEnvVariable(ctx, client, logger, cr, dcl), } if cr.Spec.EnvVars != nil { diff --git a/k8sutils/redis-sentinel_test.go b/k8sutils/redis-sentinel_test.go index eb19e5d1b..1eae1a4a1 100644 --- a/k8sutils/redis-sentinel_test.go +++ b/k8sutils/redis-sentinel_test.go @@ -176,6 +176,7 @@ func Test_generateRedisSentinelContainerParams(t *testing.T) { Value: "custom_value_2", }, }, + Port: ptr.To(26379), AdditionalVolume: []v1.Volume{ { Name: "redis-config", diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go index 65bcd9f7d..b53cff6ff 100644 --- a/k8sutils/redis-standalone.go +++ b/k8sutils/redis-standalone.go @@ -121,7 +121,7 @@ func generateRedisStandaloneContainerParams(cr *redisv1beta2.Redis) containerPar ImagePullPolicy: cr.Spec.KubernetesConfig.ImagePullPolicy, Resources: cr.Spec.KubernetesConfig.Resources, SecurityContext: cr.Spec.SecurityContext, - Port: ptr.To(6379), + Port: ptr.To(redisPort), } if cr.Spec.EnvVars != nil { From dd4e8e107cc8a53b5d947459e5f90db3e38de731 Mon Sep 17 00:00:00 2001 From: Mathieu Cesbron <45229023+MathieuCesbron@users.noreply.github.com> Date: Fri, 21 Jun 2024 09:18:29 +0200 Subject: [PATCH 198/203] chore: remove latest version for conversion webhook (#760) Remove latest version for conversion webhook Signed-off-by: Mathieu Cesbron --- config/crd/patches/webhook_in_redis.yaml | 2 +- config/crd/patches/webhook_in_redisclusters.yaml | 2 +- config/crd/patches/webhook_in_redisreplications.yaml | 2 +- config/crd/patches/webhook_in_redissentinels.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/crd/patches/webhook_in_redis.yaml b/config/crd/patches/webhook_in_redis.yaml index 70f9636d5..b251b837d 100644 --- a/config/crd/patches/webhook_in_redis.yaml +++ b/config/crd/patches/webhook_in_redis.yaml @@ -12,4 +12,4 @@ spec: namespace: ot-operators name: webhook-service path: /convert - conversionReviewVersions: ["v1beta2", "v1beta1"] + conversionReviewVersions: ["v1beta1"] diff --git a/config/crd/patches/webhook_in_redisclusters.yaml b/config/crd/patches/webhook_in_redisclusters.yaml index ad3894e42..d83136c68 100644 --- a/config/crd/patches/webhook_in_redisclusters.yaml +++ b/config/crd/patches/webhook_in_redisclusters.yaml @@ -12,4 +12,4 @@ spec: namespace: ot-operators name: webhook-service path: /convert - conversionReviewVersions: ["v1beta2", "v1beta1"] \ No newline at end of file + conversionReviewVersions: ["v1beta1"] diff --git a/config/crd/patches/webhook_in_redisreplications.yaml b/config/crd/patches/webhook_in_redisreplications.yaml index d0d5882f0..c7fccf806 100644 --- a/config/crd/patches/webhook_in_redisreplications.yaml +++ b/config/crd/patches/webhook_in_redisreplications.yaml @@ -12,4 +12,4 @@ spec: namespace: ot-operators name: webhook-service path: /convert - conversionReviewVersions: ["v1beta2", "v1beta1"] + conversionReviewVersions: ["v1beta1"] diff --git a/config/crd/patches/webhook_in_redissentinels.yaml b/config/crd/patches/webhook_in_redissentinels.yaml index 01214cbdd..a78e591ed 100644 --- a/config/crd/patches/webhook_in_redissentinels.yaml +++ b/config/crd/patches/webhook_in_redissentinels.yaml @@ -12,4 +12,4 @@ spec: namespace: ot-operators name: webhook-service path: /convert - conversionReviewVersions: ["v1beta2", "v1beta1"] + conversionReviewVersions: ["v1beta1"] From f1080f572236440d206be6bd39f67d577ca847b4 Mon Sep 17 00:00:00 2001 From: Laurentiu Soica Date: Sat, 22 Jun 2024 17:17:56 +0300 Subject: [PATCH 199/203] feat: allow rbac to pe externally provisioned (#1005) * feat: allow rbac to pe externally provisioned Signed-off-by: laurentiusoica * fix: add new parameter in docs Signed-off-by: laurentiusoica --------- Signed-off-by: laurentiusoica Co-authored-by: laurentiusoica --- charts/redis-operator/readme.md | 1 + charts/redis-operator/templates/role-binding.yaml | 2 ++ charts/redis-operator/templates/role.yaml | 2 ++ charts/redis-operator/templates/service-account.yaml | 2 ++ charts/redis-operator/values.yaml | 2 ++ 5 files changed, 9 insertions(+) diff --git a/charts/redis-operator/readme.md b/charts/redis-operator/readme.md index 9490f52ab..63c12c6ca 100644 --- a/charts/redis-operator/readme.md +++ b/charts/redis-operator/readme.md @@ -92,6 +92,7 @@ kubectl create secret tls --key tls.key --cert tls.crt -n | `resources.requests.cpu` | CPU request | `500m` | | `resources.requests.memory` | Memory request | `500Mi` | | `replicas` | Number of replicas | `1` | +| `rbac.enabled` | Feature flag for rbac resources | `true` | | `serviceAccountName` | Service account name | `redis-operator` | | `serviceAccount.automountServiceAccountToken` | Automount service account token | `true` | | `certificate.name` | Certificate name | `serving-cert` | diff --git a/charts/redis-operator/templates/role-binding.yaml b/charts/redis-operator/templates/role-binding.yaml index a1aaa585d..1ea08b001 100644 --- a/charts/redis-operator/templates/role-binding.yaml +++ b/charts/redis-operator/templates/role-binding.yaml @@ -1,3 +1,4 @@ +{{- if .Values.rbac.enabled }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -19,3 +20,4 @@ roleRef: kind: ClusterRole name: {{ .Values.redisOperator.name }} apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/charts/redis-operator/templates/role.yaml b/charts/redis-operator/templates/role.yaml index 600e1be8b..61b89710b 100644 --- a/charts/redis-operator/templates/role.yaml +++ b/charts/redis-operator/templates/role.yaml @@ -1,3 +1,4 @@ +{{- if .Values.rbac.enabled }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -124,3 +125,4 @@ rules: - patch - update - watch +{{- end }} diff --git a/charts/redis-operator/templates/service-account.yaml b/charts/redis-operator/templates/service-account.yaml index 085089e06..024f7ec2d 100644 --- a/charts/redis-operator/templates/service-account.yaml +++ b/charts/redis-operator/templates/service-account.yaml @@ -1,3 +1,4 @@ +{{- if .Values.rbac.enabled }} --- apiVersion: v1 kind: ServiceAccount @@ -13,3 +14,4 @@ metadata: app.kubernetes.io/version : {{ .Chart.AppVersion }} app.kubernetes.io/component: service-account app.kubernetes.io/part-of : {{ .Release.Name }} +{{- end }} diff --git a/charts/redis-operator/values.yaml b/charts/redis-operator/values.yaml index bd65e00ee..47ef96d48 100644 --- a/charts/redis-operator/values.yaml +++ b/charts/redis-operator/values.yaml @@ -30,6 +30,8 @@ resources: replicas: 1 +rbac: + enabled: true serviceAccountName: redis-operator serviceAccount: From 224c2860d2c9b38ec11af5a4f14160d7cd3f4f40 Mon Sep 17 00:00:00 2001 From: yangw Date: Sun, 23 Jun 2024 11:04:27 +0800 Subject: [PATCH 200/203] feat: add redis/redisreplication/redissentinel/rediscluster chart (#1007) Signed-off-by: drivebyer --- .github/workflows/publish-charts.yaml | 13 +- charts/redis-cluster/Chart.yaml | 21 ++ charts/redis-cluster/README.md | 66 +++++++ charts/redis-cluster/templates/_helpers.tpl | 90 +++++++++ .../redis-cluster/templates/extra-config.yaml | 17 ++ .../templates/follower-service.yaml | 29 +++ .../redis-cluster/templates/follower-sm.yaml | 27 +++ .../templates/leader-service.yaml | 29 +++ charts/redis-cluster/templates/leader-sm.yaml | 27 +++ .../templates/redis-cluster.yaml | 85 ++++++++ charts/redis-cluster/values.yaml | 184 ++++++++++++++++++ charts/redis-replication/.helmignore | 23 +++ charts/redis-replication/Chart.yaml | 22 +++ .../redis-replication/templates/_helpers.tpl | 63 ++++++ .../templates/extra-config.yaml | 17 ++ .../templates/redis-replication.yaml | 88 +++++++++ .../templates/replication-service.yaml | 29 +++ .../templates/servicemonitor.yaml | 27 +++ charts/redis-replication/values.yaml | 149 ++++++++++++++ charts/redis-sentinel/.helmignore | 23 +++ charts/redis-sentinel/Chart.yaml | 21 ++ charts/redis-sentinel/templates/_helpers.tpl | 63 ++++++ .../templates/extra-config.yaml | 17 ++ .../templates/redis-sentinel.yaml | 97 +++++++++ charts/redis-sentinel/templates/service.yaml | 29 +++ charts/redis-sentinel/values.yaml | 148 ++++++++++++++ charts/redis/Chart.yaml | 22 +++ charts/redis/README.md | 60 ++++++ charts/redis/templates/_helpers.tpl | 63 ++++++ charts/redis/templates/extra-config.yaml | 17 ++ charts/redis/templates/redis-standalone.yaml | 86 ++++++++ charts/redis/templates/service.yaml | 29 +++ charts/redis/templates/servicemonitor.yaml | 27 +++ charts/redis/values.yaml | 145 ++++++++++++++ 34 files changed, 1850 insertions(+), 3 deletions(-) create mode 100644 charts/redis-cluster/Chart.yaml create mode 100644 charts/redis-cluster/README.md create mode 100644 charts/redis-cluster/templates/_helpers.tpl create mode 100644 charts/redis-cluster/templates/extra-config.yaml create mode 100644 charts/redis-cluster/templates/follower-service.yaml create mode 100644 charts/redis-cluster/templates/follower-sm.yaml create mode 100644 charts/redis-cluster/templates/leader-service.yaml create mode 100644 charts/redis-cluster/templates/leader-sm.yaml create mode 100644 charts/redis-cluster/templates/redis-cluster.yaml create mode 100644 charts/redis-cluster/values.yaml create mode 100644 charts/redis-replication/.helmignore create mode 100644 charts/redis-replication/Chart.yaml create mode 100644 charts/redis-replication/templates/_helpers.tpl create mode 100644 charts/redis-replication/templates/extra-config.yaml create mode 100644 charts/redis-replication/templates/redis-replication.yaml create mode 100644 charts/redis-replication/templates/replication-service.yaml create mode 100644 charts/redis-replication/templates/servicemonitor.yaml create mode 100644 charts/redis-replication/values.yaml create mode 100644 charts/redis-sentinel/.helmignore create mode 100644 charts/redis-sentinel/Chart.yaml create mode 100644 charts/redis-sentinel/templates/_helpers.tpl create mode 100644 charts/redis-sentinel/templates/extra-config.yaml create mode 100644 charts/redis-sentinel/templates/redis-sentinel.yaml create mode 100644 charts/redis-sentinel/templates/service.yaml create mode 100644 charts/redis-sentinel/values.yaml create mode 100644 charts/redis/Chart.yaml create mode 100644 charts/redis/README.md create mode 100644 charts/redis/templates/_helpers.tpl create mode 100644 charts/redis/templates/extra-config.yaml create mode 100644 charts/redis/templates/redis-standalone.yaml create mode 100644 charts/redis/templates/service.yaml create mode 100644 charts/redis/templates/servicemonitor.yaml create mode 100644 charts/redis/values.yaml diff --git a/.github/workflows/publish-charts.yaml b/.github/workflows/publish-charts.yaml index a72b453e8..b02af6181 100644 --- a/.github/workflows/publish-charts.yaml +++ b/.github/workflows/publish-charts.yaml @@ -59,7 +59,7 @@ jobs: - name: Install and test Redis Related Helm charts run: | kubectl cluster-info --context kind-kind - chart_dirs=("redis-operator") + chart_dirs=("redis-operator" "redis" "redis-cluster" "redis-replication" "redis-sentinel") for dir in "${chart_dirs[@]}" do if [[ -f ./charts/$dir/Chart.yaml ]]; then @@ -104,8 +104,15 @@ jobs: run: | helm repo add jetstack https://charts.jetstack.io helm repo update - helm dependency update charts/redis-operator - helm package charts/redis-operator -d .cr-release-packages + + chart_dirs=("redis-operator" "redis" "redis-cluster" "redis-replication" "redis-sentinel") + for dir in "${chart_dirs[@]}" + do + if [[ -f ./charts/$dir/Chart.yaml ]]; then + helm dependency update ./charts/$dir/ + fi + helm package charts/$dir -d .cr-release-packages + done - name: Install chart-releaser uses: helm/chart-releaser-action@v1.5.0 diff --git a/charts/redis-cluster/Chart.yaml b/charts/redis-cluster/Chart.yaml new file mode 100644 index 000000000..f16e6c8af --- /dev/null +++ b/charts/redis-cluster/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: redis-cluster +description: Provides easy redis setup definitions for Kubernetes services, and deployment. +version: 0.16.0 +appVersion: "0.16.0" +home: https://github.com/ot-container-kit/redis-operator +sources: + - https://github.com/ot-container-kit/redis-operator +maintainers: + - name: iamabhishek-dubey + - name: sandy724 + - name: shubham-cmyk +keywords: +- operator +- redis +- opstree +- kubernetes +- openshift +- redis-exporter +icon: https://github.com/OT-CONTAINER-KIT/redis-operator/raw/master/static/redis-operator-logo.svg +type: application diff --git a/charts/redis-cluster/README.md b/charts/redis-cluster/README.md new file mode 100644 index 000000000..733637001 --- /dev/null +++ b/charts/redis-cluster/README.md @@ -0,0 +1,66 @@ +# Redis Cluster + +Redis is a key-value based distributed database, this helm chart is for redis cluster setup. This helm chart needs [Redis Operator](../redis-operator) inside Kubernetes cluster. The redis cluster definition can be modified or changed by [values.yaml](./values.yaml). + +```shell +helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/ + +helm install ot-helm/redis-cluster \ + --set redisCluster.clusterSize=3 --namespace +``` + +Redis setup can be upgraded by using `helm upgrade` command:- + +```shell +helm upgrade ot-helm/redis-cluster --install \ + --set redisCluster.clusterSize=5 --namespace +``` + +For uninstalling the chart:- + +```shell +helm delete --namespace +``` + +## Pre-Requisities + +- Kubernetes 1.15+ +- Helm 3.X +- Redis Operator 0.7.0 + +## Parameters + +| **Name** | **Default Value** | **Description** | +|------------------------------------|--------------------------------|-----------------------------------------------------------------------------------------------| +| `imagePullSecrets` | [] | List of image pull secrets, in case redis image is getting pull from private registry | +| `redisCluster.clusterSize` | 3 | Size of the redis cluster leader and follower nodes | +| `redisCluster.clusterVersion` | v7 | Major version of Redis setup, values can be v6 or v7 | +| `redisCluster.persistenceEnabled` | true | Persistence should be enabled or not in the Redis cluster setup | +| `redisCluster.secretName` | redis-secret | Name of the existing secret in Kubernetes | +| `redisCluster.secretKey` | password | Name of the existing secret key in Kubernetes | +| `redisCluster.image` | quay.io/opstree/redis | Name of the redis image | +| `redisCluster.tag` | v6.2 | Tag of the redis image | +| `redisCluster.imagePullPolicy` | IfNotPresent | Image Pull Policy of the redis image | +| `redisCluster.leaderServiceType` | ClusterIP | Kubernetes service type for Redis Leader | +| `redisCluster.followerServiceType` | ClusterIP | Kubernetes service type for Redis Follower | +| `redisCluster.name` | "" | Overwrites the name for the charts resources instead of the Release name | +| `externalService.enabled` | false | If redis service needs to be exposed using LoadBalancer or NodePort | +| `externalService.annotations` | {} | Kubernetes service related annotations | +| `externalService.serviceType` | NodePort | Kubernetes service type for exposing service, values - ClusterIP, NodePort, and LoadBalancer | +| `externalService.port` | 6379 | Port number on which redis external service should be exposed | +| `serviceMonitor.enabled` | false | Servicemonitor to monitor redis with Prometheus | +| `serviceMonitor.interval` | 30s | Interval at which metrics should be scraped. | +| `serviceMonitor.scrapeTimeout` | 10s | Timeout after which the scrape is ended | +| `serviceMonitor.namespace` | monitoring | Namespace in which Prometheus operator is running | +| `redisExporter.enabled` | true | Redis exporter should be deployed or not | +| `redisExporter.image` | quay.io/opstree/redis-exporter | Name of the redis exporter image | +| `redisExporter.tag` | v6.2 | Tag of the redis exporter image | +| `redisExporter.imagePullPolicy` | IfNotPresent | Image Pull Policy of the redis exporter image | +| `redisExporter.env` | [] | Extra environment variables which needs to be added in redis exporter | +| `sidecars` | [] | Sidecar for redis pods | +| `nodeSelector` | {} | NodeSelector for redis statefulset | +| `priorityClassName` | "" | Priority class name for the redis statefulset | +| `storageSpec` | {} | Storage configuration for redis setup | +| `securityContext` | {} | Security Context for redis pods for changing system or kernel level parameters | +| `affinity` | {} | Affinity for node and pods for redis statefulset | +| `tolerations` | [] | Tolerations for redis statefulset | diff --git a/charts/redis-cluster/templates/_helpers.tpl b/charts/redis-cluster/templates/_helpers.tpl new file mode 100644 index 000000000..0dd154eb4 --- /dev/null +++ b/charts/redis-cluster/templates/_helpers.tpl @@ -0,0 +1,90 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Define common labels */}} +{{- define "common.labels" -}} +app.kubernetes.io/name: {{ .Values.redisCluster.name | default .Release.Name }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Values.redisCluster.name | default .Release.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +app.kubernetes.io/component: middleware +{{- if .Values.labels }} +{{- range $labelkey, $labelvalue := .Values.labels }} +{{ $labelkey}}: {{ $labelvalue }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Helper for Redis Cluster (leader & follower) */}} +{{- define "redis.role" -}} +{{- if .affinity }} +affinity: + {{- toYaml .affinity | nindent 2 }} +{{- end }} +{{- if .tolerations }} +tolerations: + {{- toYaml .tolerations | nindent 2 }} +{{- end }} +{{- if .pdb.enabled }} +pdb: + enabled: {{ .pdb.enabled }} + maxUnavailable: {{ .pdb.maxUnavailable }} + minAvailable: {{ .pdb.minAvailable }} +{{- end }} +{{- if .nodeSelector }} +nodeSelector: + {{- toYaml .nodeSelector | nindent 2 }} +{{- end }} +{{- if .securityContext }} +securityContext: + {{- toYaml .securityContext | nindent 2 }} +{{- end }} +{{- end -}} + +{{/* Generate sidecar properties */}} +{{- define "sidecar.properties" -}} +{{- with .Values.sidecars }} +name: {{ .name }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate init container properties */}} +{{- define "initContainer.properties" -}} +{{- with .Values.initContainer }} +{{- if .enabled }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- if .command }} +command: +{{ toYaml .command | nindent 2 }} +{{- end }} +{{- if .args }} +args: +{{ toYaml .args | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + diff --git a/charts/redis-cluster/templates/extra-config.yaml b/charts/redis-cluster/templates/extra-config.yaml new file mode 100644 index 000000000..755c4d366 --- /dev/null +++ b/charts/redis-cluster/templates/extra-config.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.externalConfig.enabled true }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.redisCluster.name | default .Release.Name }}-ext-config + labels: + app.kubernetes.io/name: {{ .Values.redisCluster.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisCluster.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +data: + redis-additional.conf: | + {{ .Values.externalConfig.data | nindent 4 }} +{{- end }} diff --git a/charts/redis-cluster/templates/follower-service.yaml b/charts/redis-cluster/templates/follower-service.yaml new file mode 100644 index 000000000..6fa645529 --- /dev/null +++ b/charts/redis-cluster/templates/follower-service.yaml @@ -0,0 +1,29 @@ +{{- if and (gt (int .Values.redisCluster.follower.replicas) 0) (eq .Values.externalService.enabled true) }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.redisCluster.name | default .Release.Name }}-follower-external-service +{{- if .Values.externalService.annotations }} + annotations: +{{ toYaml .Values.externalService.annotations | indent 4 }} +{{- end }} + labels: + app.kubernetes.io/name: {{ .Values.redisCluster.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisCluster.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + type: {{ .Values.externalService.serviceType }} + selector: + app: {{ .Values.redisCluster.name | default .Release.Name }}-follower + redis_setup_type: cluster + role: follower + ports: + - protocol: TCP + port: {{ .Values.externalService.port }} + targetPort: 6379 + name: client +{{- end }} diff --git a/charts/redis-cluster/templates/follower-sm.yaml b/charts/redis-cluster/templates/follower-sm.yaml new file mode 100644 index 000000000..c1f199776 --- /dev/null +++ b/charts/redis-cluster/templates/follower-sm.yaml @@ -0,0 +1,27 @@ +{{- if and (eq .Values.serviceMonitor.enabled true) (gt (int .Values.redisCluster.follower.replicas) 0) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ .Values.redisCluster.name | default .Release.Name }}-follower-prometheus-monitoring + labels: + app.kubernetes.io/name: {{ .Values.redisCluster.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisCluster.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + selector: + matchLabels: + app: {{ .Values.redisCluster.name | default .Release.Name }}-follower + redis_setup_type: cluster + role: follower + endpoints: + - port: redis-exporter + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + namespaceSelector: + matchNames: + - {{ .Values.serviceMonitor.namespace }} +{{- end }} diff --git a/charts/redis-cluster/templates/leader-service.yaml b/charts/redis-cluster/templates/leader-service.yaml new file mode 100644 index 000000000..e7cedd864 --- /dev/null +++ b/charts/redis-cluster/templates/leader-service.yaml @@ -0,0 +1,29 @@ +{{- if and (gt (int .Values.redisCluster.leader.replicas) 0) (eq .Values.externalService.enabled true) }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.redisCluster.name | default .Release.Name }}-leader-external-service +{{- if .Values.externalService.annotations }} + annotations: +{{ toYaml .Values.externalService.annotations | indent 4 }} +{{- end }} + labels: + app.kubernetes.io/name: {{ .Values.redisCluster.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisCluster.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + type: {{ .Values.externalService.serviceType }} + selector: + app: {{ .Values.redisCluster.name | default .Release.Name }}-leader + redis_setup_type: cluster + role: leader + ports: + - protocol: TCP + port: {{ .Values.externalService.port }} + targetPort: 6379 + name: client +{{- end }} diff --git a/charts/redis-cluster/templates/leader-sm.yaml b/charts/redis-cluster/templates/leader-sm.yaml new file mode 100644 index 000000000..1fabfab1d --- /dev/null +++ b/charts/redis-cluster/templates/leader-sm.yaml @@ -0,0 +1,27 @@ +{{- if and (eq .Values.serviceMonitor.enabled true) (gt (int .Values.redisCluster.leader.replicas) 0) }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ .Values.redisCluster.name | default .Release.Name }}-leader-prometheus-monitoring + labels: + app.kubernetes.io/name: {{ .Values.redisCluster.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisCluster.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + selector: + matchLabels: + app: {{ .Values.redisCluster.name | default .Release.Name }}-leader + redis_setup_type: cluster + role: leader + endpoints: + - port: redis-exporter + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + namespaceSelector: + matchNames: + - {{ .Values.serviceMonitor.namespace }} +{{- end }} diff --git a/charts/redis-cluster/templates/redis-cluster.yaml b/charts/redis-cluster/templates/redis-cluster.yaml new file mode 100644 index 000000000..84a0a1ad1 --- /dev/null +++ b/charts/redis-cluster/templates/redis-cluster.yaml @@ -0,0 +1,85 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisCluster +metadata: + name: {{ .Values.redisCluster.name | default .Release.Name }} + labels: {{- include "common.labels" . | nindent 4 }} +spec: + clusterSize: {{ .Values.redisCluster.clusterSize }} + persistenceEnabled: {{ .Values.redisCluster.persistenceEnabled }} + clusterVersion: {{ .Values.redisCluster.clusterVersion }} + + redisLeader: {{- include "redis.role" .Values.redisCluster.leader | nindent 4 }} + replicas: {{ .Values.redisCluster.leader.replicas }} + {{- if .Values.externalConfig.enabled }} + redisConfig: + additionalRedisConfig: "{{ .Values.redisCluster.name | default .Release.Name }}-ext-config" + {{- end }} + + redisFollower: {{- include "redis.role" .Values.redisCluster.follower | nindent 4 }} + replicas: {{ .Values.redisCluster.follower.replicas }} + {{- if .Values.externalConfig.enabled }} + redisConfig: + additionalRedisConfig: "{{ .Values.redisCluster.name | default .Release.Name }}-ext-config" + {{- end }} + + redisExporter: + enabled: {{ .Values.redisExporter.enabled }} + image: "{{ .Values.redisExporter.image }}:{{ .Values.redisExporter.tag }}" + imagePullPolicy: "{{ .Values.redisExporter.imagePullPolicy }}" + {{- if .Values.redisExporter.resources}} + resources: {{ toYaml .Values.redisExporter.resources | nindent 6 }} + {{- end }} + {{- if .Values.redisExporter.env }} + env: {{ toYaml .Values.redisExporter.env | nindent 6 }} + {{- end }} + + kubernetesConfig: + image: "{{ .Values.redisCluster.image }}:{{ .Values.redisCluster.tag }}" + imagePullPolicy: "{{ .Values.redisCluster.imagePullPolicy }}" + {{- if .Values.redisCluster.imagePullSecrets}} + imagePullSecrets: {{ toYaml .Values.redisCluster.imagePullSecrets | nindent 4 }} + {{- end }} + {{- if .Values.redisCluster.resources}} + resources: {{ toYaml .Values.redisCluster.resources | nindent 6 }} + {{- end }} + {{- if and .Values.redisCluster.redisSecret.secretName .Values.redisCluster.redisSecret.secretKey }} + redisSecret: + name: {{ .Values.redisCluster.redisSecret.secretName | quote }} + key: {{ .Values.redisCluster.redisSecret.secretKey | quote }} + {{- end }} + + {{- if .Values.storageSpec }} + storage: {{ toYaml .Values.storageSpec | nindent 4 }} + {{- end }} + {{- if and .Values.priorityClassName (ne .Values.priorityClassName "") }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.podSecurityContext }} + podSecurityContext: {{ toYaml .Values.podSecurityContext | nindent 4 }} + {{- end }} + {{- if and .Values.TLS.ca .Values.TLS.cert .Values.TLS.key .Values.TLS.secret.secretName }} + TLS: + ca: {{ .Values.TLS.ca | quote }} + cert: {{ .Values.TLS.cert | quote }} + key: {{ .Values.TLS.key | quote }} + secret: + secretName: {{ .Values.TLS.secret.secretName | quote }} + {{- end }} + {{- if and .Values.acl.secret (ne .Values.acl.secret.secretName "") }} + acl: + secret: + secretName: {{ .Values.acl.secret.secretName | quote }} + {{- end }} + {{- if and .Values.sidecars (ne .Values.sidecars.name "") (ne .Values.sidecars.image "") }} + sidecars: {{ include "sidecar.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.initContainer .Values.initContainer.enabled (ne .Values.initContainer.image "") }} + initContainer: {{ include "initContainer.properties" | nindent 4 }} + {{- end }} + {{- if .Values.env }} + env: {{ toYaml .Values.env | nindent 4 }} + {{- end }} + {{- if and .Values.serviceAccountName (ne .Values.serviceAccountName "") }} + serviceAccountName: "{{ .Values.serviceAccountName }}" + {{- end }} diff --git a/charts/redis-cluster/values.yaml b/charts/redis-cluster/values.yaml new file mode 100644 index 000000000..4e77a20df --- /dev/null +++ b/charts/redis-cluster/values.yaml @@ -0,0 +1,184 @@ +--- +redisCluster: + name: "" + clusterSize: 3 + clusterVersion: v7 + persistenceEnabled: true + image: quay.io/opstree/redis + tag: v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: {} + # - name: Secret with Registry credentials + redisSecret: + secretName: "" + secretKey: "" + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + leader: + replicas: 3 + serviceType: ClusterIP + affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: disktype + # operator: In + # values: + # - ssd + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + nodeSelector: null + # memory: medium + securityContext: {} + pdb: + enabled: false + maxUnavailable: 1 + minAvailable: 1 + + follower: + replicas: 3 + serviceType: ClusterIP + affinity: null + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: disktype + # operator: In + # values: + # - ssd + tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + nodeSelector: null + # memory: medium + securityContext: {} + pdb: + enabled: false + maxUnavailable: 1 + minAvailable: 1 + +labels: {} +# foo: bar +# test: echo + + +externalConfig: + enabled: false + data: | + tcp-keepalive 400 + slowlog-max-len 158 + stream-node-max-bytes 2048 + +externalService: + enabled: false + # annotations: + # foo: bar + serviceType: LoadBalancer + port: 6379 + +serviceMonitor: + enabled: false + interval: 30s + scrapeTimeout: 10s + namespace: monitoring + +redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter + tag: "v1.44.0" + imagePullPolicy: IfNotPresent + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + env: [] + # - name: VAR_NAME + # value: "value1" + +sidecars: + name: "" + image: "" + imagePullPolicy: "IfNotPresent" + resources: + limits: + cpu: "100m" + memory: "128Mi" + requests: + cpu: "50m" + memory: "64Mi" + env: {} + # - name: MY_ENV_VAR + # value: "my-env-var-value" + +initContainer: + enabled: false + image: "" + imagePullPolicy: "IfNotPresent" + resources: {} + # requests: + # memory: "64Mi" + # cpu: "250m" + # limits: + # memory: "128Mi" + # cpu: "500m" + env: [] + command: [] + args: [] + +priorityClassName: "" + +storageSpec: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + nodeConfVolume: true + nodeConfVolumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # selector: {} + +podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + + +# serviceAccountName: redis-sa + +TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: "" + +acl: + secret: + secretName: "" + +env: [] + # - name: VAR_NAME + # value: "value1" + +serviceAccountName: "" diff --git a/charts/redis-replication/.helmignore b/charts/redis-replication/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/redis-replication/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/redis-replication/Chart.yaml b/charts/redis-replication/Chart.yaml new file mode 100644 index 000000000..00562b51a --- /dev/null +++ b/charts/redis-replication/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +name: redis-replication +description: Provides easy redis setup definitions for Kubernetes services, and deployment. +type: application +engine: gotpl +maintainers: + - name: iamabhishek-dubey + - name: sandy724 + - name: shubham-cmyk +sources: + - https://github.com/ot-container-kit/redis-operator +version: 0.16.0 +appVersion: "0.16.0" +home: https://github.com/ot-container-kit/redis-operator +keywords: +- operator +- redis +- opstree +- kubernetes +- openshift +- redis-exporter +icon: https://github.com/OT-CONTAINER-KIT/redis-operator/raw/master/static/redis-operator-logo.svg diff --git a/charts/redis-replication/templates/_helpers.tpl b/charts/redis-replication/templates/_helpers.tpl new file mode 100644 index 000000000..cfc58681b --- /dev/null +++ b/charts/redis-replication/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Define common labels */}} +{{- define "common.labels" -}} +app.kubernetes.io/name: {{ .Release.Name }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +app.kubernetes.io/component: middleware +{{- if .Values.labels }} +{{- range $labelkey, $labelvalue := .Values.labels }} +{{ $labelkey}}: {{ $labelvalue }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate init container properties */}} +{{- define "initContainer.properties" -}} +{{- with .Values.initContainer }} +{{- if .enabled }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- if .command }} +command: +{{ toYaml .command | nindent 2 }} +{{- end }} +{{- if .args }} +args: +{{ toYaml .args | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate sidecar properties */}} +{{- define "sidecar.properties" -}} +{{- with .Values.sidecars }} +name: {{ .name }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/redis-replication/templates/extra-config.yaml b/charts/redis-replication/templates/extra-config.yaml new file mode 100644 index 000000000..d143cdb20 --- /dev/null +++ b/charts/redis-replication/templates/extra-config.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.externalConfig.enabled true }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.redisReplication.name | default .Release.Name }}-ext-config + labels: + app.kubernetes.io/name: {{ .Values.redisReplication.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisReplication.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +data: + redis-additional.conf: | + {{ .Values.externalConfig.data | nindent 4 }} +{{- end }} diff --git a/charts/redis-replication/templates/redis-replication.yaml b/charts/redis-replication/templates/redis-replication.yaml new file mode 100644 index 000000000..ea89f23b0 --- /dev/null +++ b/charts/redis-replication/templates/redis-replication.yaml @@ -0,0 +1,88 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisReplication +metadata: + name: {{ .Values.redisReplication.name | default .Release.Name }} + labels: {{- include "common.labels" . | nindent 4 }} +spec: + clusterSize: {{ .Values.redisReplication.clusterSize }} + kubernetesConfig: + image: "{{ .Values.redisReplication.image }}:{{ .Values.redisReplication.tag }}" + imagePullPolicy: "{{ .Values.redisReplication.imagePullPolicy }}" + {{- if .Values.redisReplication.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.redisReplication.imagePullSecrets | nindent 4 }} + {{- end }} + {{- if .Values.redisReplication.resources}} + resources: {{ toYaml .Values.redisReplication.resources | nindent 6 }} + {{- end }} + {{- if and .Values.redisReplication.redisSecret.secretName .Values.redisReplication.redisSecret.secretKey }} + redisSecret: + name: {{ .Values.redisReplication.redisSecret.secretName | quote }} + key: {{ .Values.redisReplication.redisSecret.secretKey | quote }} + {{- end }} + {{- if .Values.redisReplication.ignoreAnnotations}} + ignoreAnnotations: {{ toYaml .Values.redisReplication.ignoreAnnotations | nindent 6 }} + {{- end }} + + redisExporter: + enabled: {{ .Values.redisExporter.enabled }} + image: "{{ .Values.redisExporter.image }}:{{ .Values.redisExporter.tag }}" + imagePullPolicy: "{{ .Values.redisExporter.imagePullPolicy }}" + {{- if .Values.redisExporter.resources}} + resources: {{ toYaml .Values.redisExporter.resources | nindent 6 }} + {{- end }} + {{- if .Values.redisExporter.env }} + env: {{ toYaml .Values.redisExporter.env | nindent 6 }} + {{- end }} + + {{- if .Values.externalConfig.enabled }} + redisConfig: + additionalRedisConfig: "{{ .Values.redisReplication.name | default .Release.Name }}-ext-config" + {{- end }} + {{- if .Values.storageSpec }} + storage: {{ toYaml .Values.storageSpec | nindent 4 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 4 }} + {{- end }} + {{- if .Values.podSecurityContext }} + podSecurityContext: {{ toYaml .Values.podSecurityContext | nindent 4 }} + {{- end }} + {{- if .Values.securityContext }} + securityContext: {{ toYaml .Values.securityContext | nindent 4 }} + {{- end }} + {{- if and .Values.priorityClassName (ne .Values.priorityClassName "") }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 4 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 4 }} + {{- end }} + {{- if and .Values.TLS.ca .Values.TLS.cert .Values.TLS.key .Values.TLS.secret.secretName }} + TLS: + ca: {{ .Values.TLS.ca | quote }} + cert: {{ .Values.TLS.cert | quote }} + key: {{ .Values.TLS.key | quote }} + secret: + secretName: {{ .Values.TLS.secret.secretName | quote }} + {{- end }} + {{- if and .Values.acl.secret (ne .Values.acl.secret.secretName "") }} + acl: + secret: + secretName: {{ .Values.acl.secret.secretName | quote }} + {{- end }} + {{- if and .Values.initContainer .Values.initContainer.enabled (ne .Values.initContainer.image "") }} + initContainer: {{ include "initContainer.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.sidecars (ne .Values.sidecars.name "") (ne .Values.sidecars.image "") }} + sidecars: {{ include "sidecar.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.serviceAccountName (ne .Values.serviceAccountName "") }} + serviceAccountName: "{{ .Values.serviceAccountName }}" + {{- end }} + {{- if .Values.env }} + env: {{ toYaml .Values.env | nindent 4 }} + {{- end }} + diff --git a/charts/redis-replication/templates/replication-service.yaml b/charts/redis-replication/templates/replication-service.yaml new file mode 100644 index 000000000..f9a3a7e05 --- /dev/null +++ b/charts/redis-replication/templates/replication-service.yaml @@ -0,0 +1,29 @@ +{{- if eq .Values.externalService.enabled true }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.redisReplication.name | default .Release.Name }}-external-service +{{- if .Values.externalService.annotations }} + annotations: +{{ toYaml .Values.externalService.annotations | indent 4 }} +{{- end }} + labels: + app.kubernetes.io/name: {{ .Values.redisReplication.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisReplication.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + type: {{ .Values.externalService.serviceType }} + selector: + app: {{ .Values.redisReplication.name | default .Release.Name }} + redis_setup_type: replication + role: replication + ports: + - protocol: TCP + port: {{ .Values.externalService.port }} + targetPort: 6379 + name: client +{{- end }} diff --git a/charts/redis-replication/templates/servicemonitor.yaml b/charts/redis-replication/templates/servicemonitor.yaml new file mode 100644 index 000000000..1eaef343a --- /dev/null +++ b/charts/redis-replication/templates/servicemonitor.yaml @@ -0,0 +1,27 @@ +{{- if eq .Values.serviceMonitor.enabled true }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ .Values.redisReplication.name | default .Release.Name }}-prometheus-monitoring + labels: + app.kubernetes.io/name: {{ .Values.redisReplication.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisReplication.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + selector: + matchLabels: + app: {{ .Values.redisReplication.name | default .Release.Name }} + redis_setup_type: replication + role: replication + endpoints: + - port: redis-exporter + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + namespaceSelector: + matchNames: + - {{ .Values.serviceMonitor.namespace }} +{{- end }} diff --git a/charts/redis-replication/values.yaml b/charts/redis-replication/values.yaml new file mode 100644 index 000000000..b2afb5ca2 --- /dev/null +++ b/charts/redis-replication/values.yaml @@ -0,0 +1,149 @@ +--- +redisReplication: + name: "" + clusterSize: 3 + image: quay.io/opstree/redis + tag: v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + # - name: Secret with Registry credentials + redisSecret: + secretName: "" + secretKey: "" + serviceType: ClusterIP + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + ignoreAnnotations: [] + # - "redis.opstreelabs.in/ignore" + +# Overwite name for resources +# name: "" + +labels: {} +# foo: bar +# test: echo + +externalConfig: + enabled: false + data: | + tcp-keepalive 400 + slowlog-max-len 158 + stream-node-max-bytes 2048 + +externalService: + enabled: false + # annotations: + # foo: bar + serviceType: NodePort + port: 6379 + +serviceMonitor: + enabled: false + interval: 30s + scrapeTimeout: 10s + namespace: monitoring + +redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter + tag: "v1.44.0" + imagePullPolicy: IfNotPresent + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + env: [] + # - name: VAR_NAME + # value: "value1" + +initContainer: + enabled: false + image: "" + imagePullPolicy: "IfNotPresent" + resources: {} + # requests: + # memory: "64Mi" + # cpu: "250m" + # limits: + # memory: "128Mi" + # cpu: "500m" + env: [] + command: [] + args: [] + +sidecars: + name: "" + image: "" + imagePullPolicy: "IfNotPresent" + resources: + limits: + cpu: "100m" + memory: "128Mi" + requests: + cpu: "50m" + memory: "64Mi" + env: [] + # - name: MY_ENV_VAR + # value: "my-env-var-value" + +priorityClassName: "" + +nodeSelector: {} + # memory: medium + +storageSpec: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # selector: {} + +podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + +securityContext: {} + +affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: disktype + # operator: In + # values: + # - ssd + +tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + +serviceAccountName: "" + +TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: "" + +acl: + secret: + secretName: "" + +env: [] + # - name: VAR_NAME + # value: "value1" diff --git a/charts/redis-sentinel/.helmignore b/charts/redis-sentinel/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/redis-sentinel/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/redis-sentinel/Chart.yaml b/charts/redis-sentinel/Chart.yaml new file mode 100644 index 000000000..e03c8dbba --- /dev/null +++ b/charts/redis-sentinel/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: redis-sentinel +description: Provides easy redis setup definitions for Kubernetes services, and deployment. +version: 0.16.0 +appVersion: "0.16.0" +home: https://github.com/ot-container-kit/redis-operator +sources: + - https://github.com/ot-container-kit/redis-operator +maintainers: + - name: iamabhishek-dubey + - name: sandy724 + - name: shubham-cmyk +keywords: +- operator +- redis +- opstree +- kubernetes +- openshift +- redis-exporter +icon: https://github.com/OT-CONTAINER-KIT/redis-operator/raw/master/static/redis-operator-logo.svg +type: application diff --git a/charts/redis-sentinel/templates/_helpers.tpl b/charts/redis-sentinel/templates/_helpers.tpl new file mode 100644 index 000000000..c918548fd --- /dev/null +++ b/charts/redis-sentinel/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Define common labels */}} +{{- define "common.labels" -}} +app.kubernetes.io/name: {{ .Release.Name }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +app.kubernetes.io/component: middleware +{{- if .Values.labels }} +{{- range $labelkey, $labelvalue := .Values.labels }} +{{ $labelkey}}: {{ $labelvalue }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate init container properties */}} +{{- define "initContainer.properties" -}} +{{- with .Values.initContainer }} +{{- if .enabled }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- if .command }} +command: +{{ toYaml .command | nindent 2 }} +{{- end }} +{{- if .args }} +args: +{{ toYaml .args | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate sidecar properties */}} +{{- define "sidecar.properties" -}} +{{- with .Values.sidecars }} +name: {{ .name }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} diff --git a/charts/redis-sentinel/templates/extra-config.yaml b/charts/redis-sentinel/templates/extra-config.yaml new file mode 100644 index 000000000..400fc3c5a --- /dev/null +++ b/charts/redis-sentinel/templates/extra-config.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.externalConfig.enabled true }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.redisSentinel.name | default .Release.Name }}-ext-config + labels: + app.kubernetes.io/name: {{ .Values.redisSentinel.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisSentinel.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +data: + redis-sentinel-additional.conf: | + {{ .Values.externalConfig.data | nindent 4 }} +{{- end }} diff --git a/charts/redis-sentinel/templates/redis-sentinel.yaml b/charts/redis-sentinel/templates/redis-sentinel.yaml new file mode 100644 index 000000000..c65ad5843 --- /dev/null +++ b/charts/redis-sentinel/templates/redis-sentinel.yaml @@ -0,0 +1,97 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: RedisSentinel +metadata: + name: {{ .Values.redisSentinel.name | default .Release.Name }} + labels: {{- include "common.labels" . | nindent 4 }} +spec: + clusterSize: {{ .Values.redisSentinel.clusterSize }} +# Sentinel Config + redisSentinelConfig: + redisReplicationName: {{ .Values.redisSentinelConfig.redisReplicationName}} + masterGroupName : {{ .Values.redisSentinelConfig.masterGroupName | default "myMaster" | quote}} + redisPort: {{ .Values.redisSentinelConfig.redisPort | default "6379" | quote}} + quorum: {{ .Values.redisSentinelConfig.quorum | default "2" | quote}} + parallelSyncs: {{ .Values.redisSentinelConfig.parallelSyncs | default "1" | quote}} + failoverTimeout: {{ .Values.redisSentinelConfig.failoverTimeout | default "180000" | quote}} + downAfterMilliseconds: {{ .Values.redisSentinelConfig.downAfterMilliseconds | default "30000" | quote}} + {{- if eq .Values.externalConfig.enabled true }} + additionalSentinelConfig: {{ .Values.redisSentinel.name | default .Release.Name }}-ext-config + {{- end }} + + kubernetesConfig: + image: "{{ .Values.redisSentinel.image }}:{{ .Values.redisSentinel.tag }}" + imagePullPolicy: "{{ .Values.redisSentinel.imagePullPolicy }}" + {{- if .Values.redisSentinel.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.redisSentinel.imagePullSecrets | nindent 4 }} + {{- end }} + {{- if .Values.redisSentinel.resources}} + resources: {{ toYaml .Values.redisSentinel.resources | nindent 6 }} + {{- end }} + {{- if and .Values.redisSentinel.redisSecret.secretName .Values.redisSentinel.redisSecret.secretKey }} + redisSecret: + name: {{ .Values.redisSentinel.redisSecret.secretName | quote }} + key: {{ .Values.redisSentinel.redisSecret.secretKey | quote }} + {{- end }} + {{- if .Values.redisSentinel.ignoreAnnotations}} + ignoreAnnotations: {{ toYaml .Values.redisSentinel.ignoreAnnotations | nindent 6 }} + {{- end }} + + redisExporter: + enabled: {{ .Values.redisExporter.enabled }} + image: "{{ .Values.redisExporter.image }}:{{ .Values.redisExporter.tag }}" + imagePullPolicy: "{{ .Values.redisExporter.imagePullPolicy }}" + {{- if .Values.redisExporter.resources}} + resources: {{ toYaml .Values.redisExporter.resources | nindent 6 }} + {{- end }} + {{- if .Values.redisExporter.env }} + env: {{ toYaml .Values.redisExporter.env | nindent 6 }} + {{- end }} + + {{- if .Values.externalConfig.enabled }} + redisConfig: + additionalRedisConfig: "{{ .Values.redisSentinel.name | default .Release.Name }}-ext-config" + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 4 }} + {{- end }} + {{- if .Values.podSecurityContext }} + podSecurityContext: {{ toYaml .Values.podSecurityContext | nindent 4 }} + {{- end }} + {{- if .Values.securityContext }} + securityContext: {{ toYaml .Values.securityContext | nindent 4 }} + {{- end }} + {{- if and .Values.priorityClassName (ne .Values.priorityClassName "") }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 4 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 4 }} + {{- end }} + {{- if and .Values.TLS.ca .Values.TLS.cert .Values.TLS.key .Values.TLS.secret.secretName }} + TLS: + ca: {{ .Values.TLS.ca | quote }} + cert: {{ .Values.TLS.cert | quote }} + key: {{ .Values.TLS.key | quote }} + secret: + secretName: {{ .Values.TLS.secret.secretName | quote }} + {{- end }} + {{- if and .Values.acl.secret (ne .Values.acl.secret.secretName "") }} + acl: + secret: + secretName: {{ .Values.acl.secret.secretName | quote }} + {{- end }} + {{- if and .Values.initContainer .Values.initContainer.enabled (ne .Values.initContainer.image "") }} + initContainer: {{ include "initContainer.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.sidecars (ne .Values.sidecars.name "") (ne .Values.sidecars.image "") }} + sidecars: {{ include "sidecar.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.serviceAccountName (ne .Values.serviceAccountName "") }} + serviceAccountName: "{{ .Values.serviceAccountName }}" + {{- end }} + {{- if .Values.env }} + env: {{ toYaml .Values.env | nindent 4 }} + {{- end }} diff --git a/charts/redis-sentinel/templates/service.yaml b/charts/redis-sentinel/templates/service.yaml new file mode 100644 index 000000000..112da8b0b --- /dev/null +++ b/charts/redis-sentinel/templates/service.yaml @@ -0,0 +1,29 @@ +{{- if eq .Values.externalService.enabled true }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.redisSentinel.name | default .Release.Name }}-external-service +{{- if .Values.externalService.annotations }} + annotations: +{{ toYaml .Values.externalService.annotations | indent 4 }} +{{- end }} + labels: + app.kubernetes.io/name: {{ .Values.redisSentinel.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisSentinel.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + type: {{ .Values.externalService.serviceType }} + selector: + app: {{ .Values.redisSentinel.name | default .Release.Name }} + redis_setup_type: sentinel + role: sentinel + ports: + - protocol: TCP + port: {{ .Values.externalService.port }} + targetPort: 26379 + name: client +{{- end }} diff --git a/charts/redis-sentinel/values.yaml b/charts/redis-sentinel/values.yaml new file mode 100644 index 000000000..43d8c86a2 --- /dev/null +++ b/charts/redis-sentinel/values.yaml @@ -0,0 +1,148 @@ +--- +redisSentinel: + name: "" + clusterSize: 3 + image: quay.io/opstree/redis-sentinel + tag: v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + # - name: Secret with Registry credentials + redisSecret: + secretName: "" + secretKey: "" + serviceType: ClusterIP + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + ignoreAnnotations: [] + # - "redis.opstreelabs.in/ignore" + +# Overwite name for resources +# name: "" + +labels: {} +# foo: bar +# test: echo + +redisSentinelConfig: + redisReplicationName: "redis-replication" + masterGroupName: "" + redisPort: "" + quorum: "" + parallelSyncs: "" + failoverTimeout: "" + downAfterMilliseconds: "" + +externalConfig: + enabled: false + data: | + tcp-keepalive 400 + slowlog-max-len 158 + stream-node-max-bytes 2048 + +externalService: + enabled: false + # annotations: + # foo: bar + serviceType: NodePort + port: 26379 + +serviceMonitor: + enabled: false + interval: 30s + scrapeTimeout: 10s + namespace: monitoring + +redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter + tag: "v1.44.0" + imagePullPolicy: IfNotPresent + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + env: [] + # - name: VAR_NAME + # value: "value1" + +initContainer: + enabled: false + image: "" + imagePullPolicy: "IfNotPresent" + resources: {} + # requests: + # memory: "64Mi" + # cpu: "250m" + # limits: + # memory: "128Mi" + # cpu: "500m" + env: [] + command: [] + args: [] + +sidecars: + name: "" + image: "" + imagePullPolicy: "IfNotPresent" + resources: + limits: + cpu: "100m" + memory: "128Mi" + requests: + cpu: "50m" + memory: "64Mi" + env: [] + # - name: MY_ENV_VAR + # value: "my-env-var-value" + +priorityClassName: "" + +nodeSelector: {} + # memory: medium + +podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + +securityContext: {} + +affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: disktype + # operator: In + # values: + # - ssd + +tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + +serviceAccountName: "" + +TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: "" + +acl: + secret: + secretName: "" + +env: [] + # - name: VAR_NAME + # value: "value1" diff --git a/charts/redis/Chart.yaml b/charts/redis/Chart.yaml new file mode 100644 index 000000000..1b94f548f --- /dev/null +++ b/charts/redis/Chart.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: v2 +name: redis +description: Provides easy redis setup definitions for Kubernetes services, and deployment. +version: 0.16.0 +appVersion: "0.16.0" +home: https://github.com/ot-container-kit/redis-operator +sources: + - https://github.com/ot-container-kit/redis-operator +maintainers: + - name: iamabhishek-dubey + - name: sandy724 + - name: shubham-cmyk +keywords: +- operator +- redis +- opstree +- kubernetes +- openshift +- redis-exporter +icon: https://github.com/OT-CONTAINER-KIT/redis-operator/raw/master/static/redis-operator-logo.svg +type: application diff --git a/charts/redis/README.md b/charts/redis/README.md new file mode 100644 index 000000000..a506943c8 --- /dev/null +++ b/charts/redis/README.md @@ -0,0 +1,60 @@ +# Redis + +Redis is a key-value based distributed database, this helm chart is for only standalone setup. This helm chart needs [Redis Operator](../redis-operator) inside Kubernetes cluster. The redis definition can be modified or changed by [values.yaml](./values.yaml). + +```shell +helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/ +helm install ot-helm/redis --namespace +``` + +Redis setup can be upgraded by using `helm upgrade` command:- + +```shell +helm upgrade ot-helm/redis --install --namespace +``` + +For uninstalling the chart:- + +```shell +helm delete --namespace +``` + +## Pre-Requisities + +- Kubernetes 1.15+ +- Helm 3.X +- Redis Operator 0.7.0 + +## Parameters + +| **Name** | **Value** | **Description** | +|-----------------------------------|--------------------------------|-----------------------------------------------------------------------------------------------| +| `imagePullSecrets` | [] | List of image pull secrets, in case redis image is getting pull from private registry | +| `redisStandalone.secretName` | redis-secret | Name of the existing secret in Kubernetes | +| `redisStandalone.secretKey` | password | Name of the existing secret key in Kubernetes | +| `redisStandalone.image` | quay.io/opstree/redis | Name of the redis image | +| `redisStandalone.tag` | v6.2 | Tag of the redis image | +| `redisStandalone.imagePullPolicy` | IfNotPresent | Image Pull Policy of the redis image | +| `redisStandalone.serviceType` | ClusterIP | Kubernetes service type for Redis | +| `redisStandalone.resources` | {} | Request and limits for redis statefulset | +| `redisStandalone.name` | "" | Overwrites the name for the charts resources instead of the Release name | +| `externalService.enabled` | false | If redis service needs to be exposed using LoadBalancer or NodePort | +| `externalService.annotations` | {} | Kubernetes service related annotations | +| `externalService.serviceType` | NodePort | Kubernetes service type for exposing service, values - ClusterIP, NodePort, and LoadBalancer | +| `externalService.port` | 6379 | Port number on which redis external service should be exposed | +| `serviceMonitor.enabled` | false | Servicemonitor to monitor redis with Prometheus | +| `serviceMonitor.interval` | 30s | Interval at which metrics should be scraped. | +| `serviceMonitor.scrapeTimeout` | 10s | Timeout after which the scrape is ended | +| `serviceMonitor.namespace` | monitoring | Namespace in which Prometheus operator is running | +| `redisExporter.enabled` | true | Redis exporter should be deployed or not | +| `redisExporter.image` | quay.io/opstree/redis-exporter | Name of the redis exporter image | +| `redisExporter.tag` | v6.2 | Tag of the redis exporter image | +| `redisExporter.imagePullPolicy` | IfNotPresent | Image Pull Policy of the redis exporter image | +| `redisExporter.env` | [] | Extra environment variables which needs to be added in redis exporter | +| `sidecars` | [] | Sidecar for redis pods | +| `nodeSelector` | {} | NodeSelector for redis statefulset | +| `priorityClassName` | "" | Priority class name for the redis statefulset | +| `storageSpec` | {} | Storage configuration for redis setup | +| `securityContext` | {} | Security Context for redis pods for changing system or kernel level parameters | +| `affinity` | {} | Affinity for node and pod for redis statefulset | +| `tolerations` | [] | Tolerations for redis statefulset | diff --git a/charts/redis/templates/_helpers.tpl b/charts/redis/templates/_helpers.tpl new file mode 100644 index 000000000..698c901ea --- /dev/null +++ b/charts/redis/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* Define common labels */}} +{{- define "common.labels" -}} +app.kubernetes.io/name: {{ .Values.redisStandalone.name | default .Release.Name }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/instance: {{ .Values.redisStandalone.name | default .Release.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +app.kubernetes.io/component: middleware +{{- if .Values.labels }} +{{- range $labelkey, $labelvalue := .Values.labels }} +{{ $labelkey}}: {{ $labelvalue }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate init container properties */}} +{{- define "initContainer.properties" -}} +{{- with .Values.initContainer }} +{{- if .enabled }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- if .command }} +command: +{{ toYaml .command | nindent 2 }} +{{- end }} +{{- if .args }} +args: +{{ toYaml .args | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* Generate sidecar properties */}} +{{- define "sidecar.properties" -}} +{{- with .Values.sidecars }} +name: {{ .name }} +image: {{ .image }} +{{- if .imagePullPolicy }} +imagePullPolicy: {{ .imagePullPolicy }} +{{- end }} +{{- if .resources }} +resources: + {{ toYaml .resources | nindent 2 }} +{{- end }} +{{- if .env }} +env: +{{ toYaml .env | nindent 2 }} +{{- end }} +{{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/redis/templates/extra-config.yaml b/charts/redis/templates/extra-config.yaml new file mode 100644 index 000000000..d1eb804dc --- /dev/null +++ b/charts/redis/templates/extra-config.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.externalConfig.enabled true }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Values.redisStandalone.name | default .Release.Name }}-ext-config + labels: + app.kubernetes.io/name: {{ .Values.redisStandalone.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisStandalone.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +data: + redis-additional.conf: | + {{ .Values.externalConfig.data | nindent 4 }} +{{- end }} diff --git a/charts/redis/templates/redis-standalone.yaml b/charts/redis/templates/redis-standalone.yaml new file mode 100644 index 000000000..c48775035 --- /dev/null +++ b/charts/redis/templates/redis-standalone.yaml @@ -0,0 +1,86 @@ +--- +apiVersion: redis.redis.opstreelabs.in/v1beta2 +kind: Redis +metadata: + name: {{ .Values.redisStandalone.name | default .Release.Name }} + labels: {{- include "common.labels" . | nindent 4 }} +spec: + kubernetesConfig: + image: "{{ .Values.redisStandalone.image }}:{{ .Values.redisStandalone.tag }}" + imagePullPolicy: "{{ .Values.redisStandalone.imagePullPolicy }}" + {{- if .Values.redisStandalone.imagePullSecrets }} + imagePullSecrets: {{ toYaml .Values.redisStandalone.imagePullSecrets | nindent 4 }} + {{- end }} + {{- if .Values.redisStandalone.resources}} + resources: {{ toYaml .Values.redisStandalone.resources | nindent 6 }} + {{- end }} + {{- if and .Values.redisStandalone.redisSecret.secretName .Values.redisStandalone.redisSecret.secretKey }} + redisSecret: + name: {{ .Values.redisStandalone.redisSecret.secretName | quote }} + key: {{ .Values.redisStandalone.redisSecret.secretKey | quote }} + {{- end }} + {{- if .Values.redisStandalone.ignoreAnnotations}} + ignoreAnnotations: {{ toYaml .Values.redisStandalone.ignoreAnnotations | nindent 6 }} + {{- end }} + + redisExporter: + enabled: {{ .Values.redisExporter.enabled }} + image: "{{ .Values.redisExporter.image }}:{{ .Values.redisExporter.tag }}" + imagePullPolicy: "{{ .Values.redisExporter.imagePullPolicy }}" + {{- if .Values.redisExporter.resources}} + resources: {{ toYaml .Values.redisExporter.resources | nindent 6 }} + {{- end }} + {{- if .Values.redisExporter.env }} + env: {{ toYaml .Values.redisExporter.env | nindent 6 }} + {{- end }} + + {{- if .Values.externalConfig.enabled }} + redisConfig: + additionalRedisConfig: "{{ .Values.redisStandalone.name | default .Release.Name }}-ext-config" + {{- end }} + {{- if .Values.storageSpec }} + storage: {{ toYaml .Values.storageSpec | nindent 4 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 4 }} + {{- end }} + {{- if .Values.podSecurityContext }} + podSecurityContext: {{ toYaml .Values.podSecurityContext | nindent 4 }} + {{- end }} + {{- if .Values.securityContext }} + securityContext: {{ toYaml .Values.securityContext | nindent 4 }} + {{- end }} + {{- if and .Values.priorityClassName (ne .Values.priorityClassName "") }} + priorityClassName: "{{ .Values.priorityClassName }}" + {{- end }} + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 4 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 4 }} + {{- end }} + {{- if and .Values.TLS.ca .Values.TLS.cert .Values.TLS.key .Values.TLS.secret.secretName }} + TLS: + ca: {{ .Values.TLS.ca | quote }} + cert: {{ .Values.TLS.cert | quote }} + key: {{ .Values.TLS.key | quote }} + secret: + secretName: {{ .Values.TLS.secret.secretName | quote }} + {{- end }} + {{- if and .Values.acl.secret (ne .Values.acl.secret.secretName "") }} + acl: + secret: + secretName: {{ .Values.acl.secret.secretName | quote }} + {{- end }} + {{- if and .Values.initContainer .Values.initContainer.enabled (ne .Values.initContainer.image "") }} + initContainer: {{ include "initContainer.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.sidecars (ne .Values.sidecars.name "") (ne .Values.sidecars.image "") }} + sidecars: {{ include "sidecar.properties" | nindent 4 }} + {{- end }} + {{- if and .Values.serviceAccountName (ne .Values.serviceAccountName "") }} + serviceAccountName: "{{ .Values.serviceAccountName }}" + {{- end }} + {{- if .Values.env }} + env: {{ toYaml .Values.env | nindent 4 }} + {{- end }} diff --git a/charts/redis/templates/service.yaml b/charts/redis/templates/service.yaml new file mode 100644 index 000000000..32e98cb8b --- /dev/null +++ b/charts/redis/templates/service.yaml @@ -0,0 +1,29 @@ +{{- if eq .Values.externalService.enabled true }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.redisStandalone.name | default .Release.Name }}-external-service +{{- if .Values.externalService.annotations }} + annotations: +{{ toYaml .Values.externalService.annotations | indent 4 }} +{{- end }} + labels: + app.kubernetes.io/name: {{ .Values.redisStandalone.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisStandalone.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + type: {{ .Values.externalService.serviceType }} + selector: + app: {{ .Values.redisStandalone.name | default .Release.Name }} + redis_setup_type: standalone + role: standalone + ports: + - protocol: TCP + port: {{ .Values.externalService.port }} + targetPort: 6379 + name: client +{{- end }} diff --git a/charts/redis/templates/servicemonitor.yaml b/charts/redis/templates/servicemonitor.yaml new file mode 100644 index 000000000..883f16b58 --- /dev/null +++ b/charts/redis/templates/servicemonitor.yaml @@ -0,0 +1,27 @@ +{{- if eq .Values.serviceMonitor.enabled true }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ .Values.redisStandalone.name | default .Release.Name }}-prometheus-monitoring + labels: + app.kubernetes.io/name: {{ .Values.redisStandalone.name | default .Release.Name }} + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Values.redisStandalone.name | default .Release.Name }} + app.kubernetes.io/version: {{ .Chart.AppVersion }} + app.kubernetes.io/component: middleware +spec: + selector: + matchLabels: + app: {{ .Values.redisStandalone.name | default .Release.Name }} + redis_setup_type: standalone + role: standalone + endpoints: + - port: redis-exporter + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + namespaceSelector: + matchNames: + - {{ .Values.serviceMonitor.namespace }} +{{- end }} diff --git a/charts/redis/values.yaml b/charts/redis/values.yaml new file mode 100644 index 000000000..e929a2ebe --- /dev/null +++ b/charts/redis/values.yaml @@ -0,0 +1,145 @@ +--- +redisStandalone: + name: "" + image: quay.io/opstree/redis + tag: v7.0.12 + imagePullPolicy: IfNotPresent + imagePullSecrets: [] + # - name: Secret with Registry credentials + redisSecret: + secretName: "" + secretKey: "" + serviceType: ClusterIP + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + ignoreAnnotations: [] + # - "redis.opstreelabs.in/ignore" + +labels: {} +# foo: bar +# test: echo + +externalConfig: + enabled: false + data: | + tcp-keepalive 400 + slowlog-max-len 158 + stream-node-max-bytes 2048 + +externalService: + enabled: false + # annotations: + # foo: bar + serviceType: NodePort + port: 6379 + +serviceMonitor: + enabled: false + interval: 30s + scrapeTimeout: 10s + namespace: monitoring + +redisExporter: + enabled: false + image: quay.io/opstree/redis-exporter + tag: "v1.44.0" + imagePullPolicy: IfNotPresent + resources: {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 100m + # memory: 128Mi + env: [] + # - name: VAR_NAME + # value: "value1" + +initContainer: + enabled: false + image: "" + imagePullPolicy: "IfNotPresent" + resources: {} + # requests: + # memory: "64Mi" + # cpu: "250m" + # limits: + # memory: "128Mi" + # cpu: "500m" + env: [] + command: [] + args: [] + +sidecars: + name: "" + image: "" + imagePullPolicy: "IfNotPresent" + resources: + limits: + cpu: "100m" + memory: "128Mi" + requests: + cpu: "50m" + memory: "64Mi" + env: [] + # - name: MY_ENV_VAR + # value: "my-env-var-value" + +priorityClassName: "" + +nodeSelector: {} + # memory: medium + +storageSpec: + volumeClaimTemplate: + spec: + # storageClassName: standard + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + # selector: {} + +podSecurityContext: + runAsUser: 1000 + fsGroup: 1000 + +securityContext: {} + +affinity: {} + # nodeAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: disktype + # operator: In + # values: + # - ssd + +tolerations: [] + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + +serviceAccountName: "" + +TLS: + ca: ca.key + cert: tls.crt + key: tls.key + secret: + secretName: "" + +acl: + secret: + secretName: "" + +env: [] + # - name: VAR_NAME + # value: "value1" From 02fb1207217b417c4e402277baba1f96c73798b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Jun 2024 11:06:11 +0800 Subject: [PATCH 201/203] chore(deps): bump docker/build-push-action from 3 to 6 (#998) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 3 to 6. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v3...v6) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yaml | 2 +- .github/workflows/publish-image.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b65692fee..550d7ebdc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -100,7 +100,7 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Build multi-arch image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . platforms: linux/arm64,linux/amd64 diff --git a/.github/workflows/publish-image.yaml b/.github/workflows/publish-image.yaml index f4b1c37fc..eb0e4c14f 100644 --- a/.github/workflows/publish-image.yaml +++ b/.github/workflows/publish-image.yaml @@ -34,7 +34,7 @@ jobs: echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - name: Build and Push Operator image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 with: context: . file: Dockerfile From 08eb5eb2364aaa77f62b4b2740d17863c956deef Mon Sep 17 00:00:00 2001 From: yangw Date: Sun, 23 Jun 2024 19:31:02 +0800 Subject: [PATCH 202/203] docs: fix example broken links (#1008) Signed-off-by: drivebyer --- .../en/docs/Getting Started/Cluster/_index.md | 26 +++++++++---------- .../Getting Started/Replication/_index.md | 26 +++++++++---------- .../docs/Getting Started/Sentinel/_index.md | 26 +++++++++---------- .../docs/Getting Started/Standalone/_index.md | 26 +++++++++---------- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/docs/content/en/docs/Getting Started/Cluster/_index.md b/docs/content/en/docs/Getting Started/Cluster/_index.md index 7570dbae0..f881b7d05 100644 --- a/docs/content/en/docs/Getting Started/Cluster/_index.md +++ b/docs/content/en/docs/Getting Started/Cluster/_index.md @@ -66,19 +66,19 @@ c2b74bd2a360068db01dfc8f00b8d0b012e21215 10.42.1.177:6379@16379 slave 528438a759 ## YAML Installation -[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: - -- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/additional_config) -- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/advance_config) -- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/affinity) -- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/disruption_budget) -- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/external_service) -- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/password_protected) -- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/private_registry) -- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/probes) -- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/redis_monitoring) -- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/tls_enabled) -- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/upgrade-strategy) +[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: + +- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/additional_config) +- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/advance_config) +- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/affinity) +- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/disruption_budget) +- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/external_service) +- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/password_protected) +- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/private_registry) +- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/probes) +- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/redis_monitoring) +- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/tls_enabled) +- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/upgrade-strategy) A sample manifest for deploying redis cluster: diff --git a/docs/content/en/docs/Getting Started/Replication/_index.md b/docs/content/en/docs/Getting Started/Replication/_index.md index f9c7d710d..298cc0077 100644 --- a/docs/content/en/docs/Getting Started/Replication/_index.md +++ b/docs/content/en/docs/Getting Started/Replication/_index.md @@ -54,19 +54,19 @@ If all the pods are in the running, then we can check the health of the redis re ## YAML Installation -[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: - -- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/additional_config) -- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/advance_config) -- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/affinity) -- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/disruption_budget) -- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/external_service) -- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/password_protected) -- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/private_registry) -- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/probes) -- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/redis_monitoring) -- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/tls_enabled) -- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/upgrade-strategy) +[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: + +- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/additional_config) +- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/advance_config) +- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/affinity) +- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/disruption_budget) +- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/external_service) +- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/password_protected) +- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/private_registry) +- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/probes) +- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/redis_monitoring) +- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/tls_enabled) +- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/upgrade-strategy) A sample manifest for deploying redis replication-cluster: diff --git a/docs/content/en/docs/Getting Started/Sentinel/_index.md b/docs/content/en/docs/Getting Started/Sentinel/_index.md index f84ac0b86..b6f917726 100644 --- a/docs/content/en/docs/Getting Started/Sentinel/_index.md +++ b/docs/content/en/docs/Getting Started/Sentinel/_index.md @@ -47,19 +47,19 @@ redis-sentinel-2 1/1 Running 0 2m10s ## YAML Installation -[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: - -- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/additional_config) -- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/advance_config) -- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/affinity) -- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/disruption_budget) -- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/external_service) -- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/password_protected) -- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/private_registry) -- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/probes) -- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/redis_monitoring) -- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/tls_enabled) -- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/upgrade-strategy) +[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: + +- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/additional_config) +- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/advance_config) +- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/affinity) +- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/disruption_budget) +- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/external_service) +- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/password_protected) +- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/private_registry) +- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/probes) +- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/redis_monitoring) +- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/tls_enabled) +- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/upgrade-strategy) A basic sample manifest for sentinel redis: diff --git a/docs/content/en/docs/Getting Started/Standalone/_index.md b/docs/content/en/docs/Getting Started/Standalone/_index.md index 76d71f9bb..8bb2fd3a5 100644 --- a/docs/content/en/docs/Getting Started/Standalone/_index.md +++ b/docs/content/en/docs/Getting Started/Standalone/_index.md @@ -44,19 +44,19 @@ redis-0 1/1 Running 0 56s ## YAML Installation -[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: - -- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/additional_config) -- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/advance_config) -- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/affinity) -- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/disruption_budget) -- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/external_service) -- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/password_protected) -- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/private_registry) -- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/probes) -- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/redis_monitoring) -- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/tls_enabled) -- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/upgrade-strategy) +[Examples](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2) folder has different types of manifests for different scenarios and features. There are these YAML examples present in this directory: + +- [additional_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/additional_config) +- [advance_config](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/advance_config) +- [affinity](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/affinity) +- [disruption_budget](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/disruption_budget) +- [external_service](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/external_service) +- [password_protected](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/password_protected) +- [private_registry](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/private_registry) +- [probes](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/probes) +- [redis_monitoring](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/redis_monitoring) +- [tls_enabled](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/tls_enabled) +- [upgrade_strategy](https://github.com/OT-CONTAINER-KIT/redis-operator/tree/master/example/v1beta2/upgrade-strategy) A basic sample manifest for standalone redis: From 0dddaeac9af0c6c3d5ad558ee16a53762141a6af Mon Sep 17 00:00:00 2001 From: yangw Date: Wed, 10 Jul 2024 14:31:55 +0800 Subject: [PATCH 203/203] feat: add redisReplicationPassword values to connect secured replication (#1021) feat: add redisReplicationPassword values to connect secured replication cluster Signed-off-by: drivebyer --- charts/redis-sentinel/Chart.yaml | 4 ++-- charts/redis-sentinel/templates/redis-sentinel.yaml | 6 ++++++ charts/redis-sentinel/values.yaml | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/charts/redis-sentinel/Chart.yaml b/charts/redis-sentinel/Chart.yaml index e03c8dbba..6bb96122f 100644 --- a/charts/redis-sentinel/Chart.yaml +++ b/charts/redis-sentinel/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 name: redis-sentinel description: Provides easy redis setup definitions for Kubernetes services, and deployment. -version: 0.16.0 -appVersion: "0.16.0" +version: 0.16.1 +appVersion: "0.16.1" home: https://github.com/ot-container-kit/redis-operator sources: - https://github.com/ot-container-kit/redis-operator diff --git a/charts/redis-sentinel/templates/redis-sentinel.yaml b/charts/redis-sentinel/templates/redis-sentinel.yaml index c65ad5843..491b8ecf0 100644 --- a/charts/redis-sentinel/templates/redis-sentinel.yaml +++ b/charts/redis-sentinel/templates/redis-sentinel.yaml @@ -9,6 +9,12 @@ spec: # Sentinel Config redisSentinelConfig: redisReplicationName: {{ .Values.redisSentinelConfig.redisReplicationName}} + {{- if and .Values.redisSentinelConfig.redisReplicationPassword.secretName .Values.redisSentinelConfig.redisReplicationPassword.secretKey }} + redisReplicationPassword: + secretKeyRef: + name: {{ .Values.redisSentinelConfig.redisReplicationPassword.secretName | quote }} + key: {{ .Values.redisSentinelConfig.redisReplicationPassword.secretKey | quote }} + {{- end }} masterGroupName : {{ .Values.redisSentinelConfig.masterGroupName | default "myMaster" | quote}} redisPort: {{ .Values.redisSentinelConfig.redisPort | default "6379" | quote}} quorum: {{ .Values.redisSentinelConfig.quorum | default "2" | quote}} diff --git a/charts/redis-sentinel/values.yaml b/charts/redis-sentinel/values.yaml index 43d8c86a2..13041b2d7 100644 --- a/charts/redis-sentinel/values.yaml +++ b/charts/redis-sentinel/values.yaml @@ -30,6 +30,9 @@ labels: {} redisSentinelConfig: redisReplicationName: "redis-replication" + redisReplicationPassword: + secretName: "" + secretKey: "" masterGroupName: "" redisPort: "" quorum: ""