@@ -6,18 +6,31 @@ import (
66
77 cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
88 enterprisev4 "github.com/splunk/splunk-operator/api/v4"
9+ pgcConstants "github.com/splunk/splunk-operator/pkg/postgresql/cluster/business/core/types/constants"
910 "github.com/stretchr/testify/assert"
1011 "github.com/stretchr/testify/require"
1112 corev1 "k8s.io/api/core/v1"
1213 apierrors "k8s.io/apimachinery/pkg/api/errors"
1314 "k8s.io/apimachinery/pkg/api/resource"
1415 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1516 "k8s.io/apimachinery/pkg/runtime"
17+ "k8s.io/apimachinery/pkg/runtime/schema"
1618 "k8s.io/utils/ptr"
1719 client "sigs.k8s.io/controller-runtime/pkg/client"
1820 "sigs.k8s.io/controller-runtime/pkg/client/fake"
1921)
2022
23+ type configMapNotFoundClient struct {
24+ client.Client
25+ }
26+
27+ func (c configMapNotFoundClient ) Get (ctx context.Context , key client.ObjectKey , obj client.Object , opts ... client.GetOption ) error {
28+ if _ , ok := obj .(* corev1.ConfigMap ); ok {
29+ return apierrors .NewNotFound (schema.GroupResource {Resource : "configmaps" }, key .Name )
30+ }
31+ return c .Client .Get (ctx , key , obj , opts ... )
32+ }
33+
2134func TestPoolerResourceName (t * testing.T ) {
2235 tests := []struct {
2336 name string
@@ -1136,3 +1149,125 @@ func TestCreateOrUpdateConnectionPoolers(t *testing.T) {
11361149 assert .Equal (t , int32 (1 ), * ro .Spec .Instances )
11371150 })
11381151}
1152+
1153+ func TestComponentStateTriggerConditions (t * testing.T ) {
1154+ t .Parallel ()
1155+
1156+ ctx := t .Context ()
1157+ scheme := runtime .NewScheme ()
1158+ require .NoError (t , corev1 .AddToScheme (scheme ))
1159+
1160+ exampleCm := & corev1.ConfigMap {
1161+ ObjectMeta : metav1.ObjectMeta {
1162+ Name : "pg1-config" ,
1163+ Namespace : "default" ,
1164+ },
1165+ Data : map [string ]string {
1166+ "CLUSTER_RW_ENDPOINT" : "pg1-rw.default" ,
1167+ "CLUSTER_RO_ENDPOINT" : "pg1-ro.default" ,
1168+ "DEFAULT_CLUSTER_PORT" : "5432" ,
1169+ "SUPER_USER_SECRET_REF" : "pg1-secret" ,
1170+ },
1171+ }
1172+ examplePgCluster := & enterprisev4.PostgresCluster {
1173+ ObjectMeta : metav1.ObjectMeta {
1174+ Name : "pg1" ,
1175+ Namespace : "default" ,
1176+ },
1177+ Status : enterprisev4.PostgresClusterStatus {
1178+ Resources : & enterprisev4.PostgresClusterResources {
1179+ ConfigMapRef : & corev1.LocalObjectReference {Name : "pg1-config" },
1180+ SuperUserSecretRef : & corev1.SecretKeySelector {
1181+ LocalObjectReference : corev1.LocalObjectReference {Name : "pg1-secret" },
1182+ Key : "password" ,
1183+ },
1184+ },
1185+ },
1186+ }
1187+ exampleSecret := & corev1.Secret {
1188+ ObjectMeta : metav1.ObjectMeta {
1189+ Name : "pg1-secret" ,
1190+ Namespace : "default" ,
1191+ },
1192+ Data : map [string ][]byte {
1193+ "password" : []byte ("s3cr3t" ),
1194+ },
1195+ }
1196+
1197+ // TODO: as soon as coupling is addressed, remove this monster of a test.
1198+ combinations := []struct {
1199+ name string
1200+ componentChecks []clusterReadynessCheck
1201+ requeue []bool
1202+ expectedResult bool
1203+ message string
1204+ }{
1205+ {
1206+ name : "Provisioner ready, pooler pending, sync not successful" ,
1207+ componentChecks : []clusterReadynessCheck {
1208+ newProvisionerHealthCheck (examplePgCluster .DeepCopy (), & cnpgv1.Cluster {Status : cnpgv1.ClusterStatus {Phase : cnpgv1 .PhaseHealthy }}),
1209+ newPoolerHealthCheck (nil , nil , true , false ),
1210+ },
1211+ requeue : []bool {false , false },
1212+ expectedResult : false ,
1213+ message : "Provisioner is ready but pooler is pending, don't fire" ,
1214+ },
1215+ {
1216+ name : "Provisioner ready, pooler ready, configMap failed, sync not successful" ,
1217+ componentChecks : []clusterReadynessCheck {
1218+ newProvisionerHealthCheck (examplePgCluster , & cnpgv1.Cluster {Status : cnpgv1.ClusterStatus {Phase : cnpgv1 .PhaseHealthy }}),
1219+ newPoolerHealthCheck (nil , nil , false , false ),
1220+ newConfigMapHealthCheck (
1221+ configMapNotFoundClient {
1222+ Client : fake .NewClientBuilder ().
1223+ WithScheme (scheme ).
1224+ Build (),
1225+ },
1226+ examplePgCluster .DeepCopy (),
1227+ ),
1228+ },
1229+ requeue : []bool {false , false , true },
1230+ expectedResult : false ,
1231+ message : "Provisioner and pooler ready are not enough when ConfigMap check returns NotFound/pending" ,
1232+ },
1233+ {
1234+ name : "Sync successful, all components ready." ,
1235+ componentChecks : []clusterReadynessCheck {
1236+ newProvisionerHealthCheck (examplePgCluster , & cnpgv1.Cluster {Status : cnpgv1.ClusterStatus {Phase : cnpgv1 .PhaseHealthy }}),
1237+ newPoolerHealthCheck (nil , nil , false , false ),
1238+ newConfigMapHealthCheck (
1239+ fake .NewClientBuilder ().
1240+ WithScheme (scheme ).
1241+ WithObjects (exampleCm ).
1242+ Build (),
1243+ examplePgCluster .DeepCopy (),
1244+ ),
1245+ newSecretHealthCheck (
1246+ fake .NewClientBuilder ().
1247+ WithScheme (scheme ).
1248+ WithObjects (exampleSecret ).
1249+ Build (),
1250+ examplePgCluster .DeepCopy (),
1251+ ),
1252+ },
1253+ requeue : []bool {false , false , false , false },
1254+ expectedResult : true ,
1255+ message : "" ,
1256+ },
1257+ }
1258+
1259+ for _ , tt := range combinations {
1260+ t .Run (tt .name , func (t * testing.T ) {
1261+ t .Parallel ()
1262+
1263+ state := pgcConstants .EmptyState
1264+ for i , check := range tt .componentChecks {
1265+ info , _ := check .Condition (ctx )
1266+ state |= info .State
1267+ assert .Equal (t , tt .requeue [i ], info .Result .RequeueAfter > 0 )
1268+ }
1269+ assert .Equal (t , tt .expectedResult , state & pgcConstants .ComponentsReady == pgcConstants .ComponentsReady ,
1270+ tt .message )
1271+ })
1272+ }
1273+ }
0 commit comments