@@ -2,6 +2,7 @@ package cluster
22
33import (
44 "bytes"
5+ "fmt"
56 "io/ioutil"
67 "net/http"
78 "testing"
@@ -480,6 +481,140 @@ func TestCheckAndSetGlobalPostgreSQLConfiguration(t *testing.T) {
480481 }
481482}
482483
484+ func TestSyncStandbyClusterConfiguration (t * testing.T ) {
485+ client , _ := newFakeK8sSyncClient ()
486+ clusterName := "acid-standby-cluster"
487+ applicationLabel := "spilo"
488+ namespace := "default"
489+
490+ ctrl := gomock .NewController (t )
491+ defer ctrl .Finish ()
492+
493+ pg := acidv1.Postgresql {
494+ ObjectMeta : metav1.ObjectMeta {
495+ Name : clusterName ,
496+ Namespace : namespace ,
497+ },
498+ Spec : acidv1.PostgresSpec {
499+ NumberOfInstances : int32 (1 ),
500+ Volume : acidv1.Volume {
501+ Size : "1Gi" ,
502+ },
503+ },
504+ }
505+
506+ var cluster = New (
507+ Config {
508+ OpConfig : config.Config {
509+ PatroniAPICheckInterval : time .Duration (1 ),
510+ PatroniAPICheckTimeout : time .Duration (5 ),
511+ PodManagementPolicy : "ordered_ready" ,
512+ Resources : config.Resources {
513+ ClusterLabels : map [string ]string {"application" : applicationLabel },
514+ ClusterNameLabel : "cluster-name" ,
515+ DefaultCPURequest : "300m" ,
516+ DefaultCPULimit : "300m" ,
517+ DefaultMemoryRequest : "300Mi" ,
518+ DefaultMemoryLimit : "300Mi" ,
519+ MinInstances : int32 (- 1 ),
520+ MaxInstances : int32 (- 1 ),
521+ PodRoleLabel : "spilo-role" ,
522+ ResourceCheckInterval : time .Duration (3 ),
523+ ResourceCheckTimeout : time .Duration (10 ),
524+ },
525+ },
526+ }, client , pg , logger , eventRecorder )
527+
528+ cluster .Name = clusterName
529+ cluster .Namespace = namespace
530+
531+ // mocking a config after getConfig is called
532+ mockClient := mocks .NewMockHTTPClient (ctrl )
533+ configJson := `{"ttl": 20}`
534+ r := ioutil .NopCloser (bytes .NewReader ([]byte (configJson )))
535+ response := http.Response {
536+ StatusCode : 200 ,
537+ Body : r ,
538+ }
539+ mockClient .EXPECT ().Get (gomock .Any ()).Return (& response , nil ).AnyTimes ()
540+
541+ // mocking a config after setConfig is called
542+ standbyJson := `{"standby_cluster":{"create_replica_methods":["bootstrap_standby_with_wale","basebackup_fast_xlog"],"restore_command":"envdir \"/run/etc/wal-e.d/env-standby\" /scripts/restore_command.sh \"%f\" \"%p\""}}`
543+ r = ioutil .NopCloser (bytes .NewReader ([]byte (standbyJson )))
544+ response = http.Response {
545+ StatusCode : 200 ,
546+ Body : r ,
547+ }
548+ mockClient .EXPECT ().Do (gomock .Any ()).Return (& response , nil ).AnyTimes ()
549+ p := patroni .New (patroniLogger , mockClient )
550+ cluster .patroni = p
551+
552+ mockPod := newMockPod ("192.168.100.1" )
553+ mockPod .Name = fmt .Sprintf ("%s-0" , clusterName )
554+ mockPod .Namespace = namespace
555+ podLabels := map [string ]string {
556+ "cluster-name" : clusterName ,
557+ "application" : applicationLabel ,
558+ "spilo-role" : "master" ,
559+ }
560+ mockPod .Labels = podLabels
561+ client .PodsGetter .Pods (namespace ).Create (context .TODO (), mockPod , metav1.CreateOptions {})
562+
563+ // create a statefulset
564+ sts , err := cluster .createStatefulSet ()
565+ assert .NoError (t , err )
566+
567+ // check that pods do not have a STANDBY_* environment variable
568+ assert .NotContains (t , sts .Spec .Template .Spec .Containers [0 ].Env , v1.EnvVar {Name : "STANDBY_METHOD" , Value : "STANDBY_WITH_WALE" })
569+
570+ // add standby section
571+ cluster .Spec .StandbyCluster = & acidv1.StandbyDescription {
572+ S3WalPath : "s3://custom/path/to/bucket/" ,
573+ }
574+ cluster .syncStatefulSet ()
575+ updatedSts := cluster .Statefulset
576+
577+ // check that pods do not have a STANDBY_* environment variable
578+ assert .Contains (t , updatedSts .Spec .Template .Spec .Containers [0 ].Env , v1.EnvVar {Name : "STANDBY_METHOD" , Value : "STANDBY_WITH_WALE" })
579+
580+ // this should update the Patroni config
581+ err = cluster .syncStandbyClusterConfiguration ()
582+ assert .NoError (t , err )
583+
584+ configJson = `{"standby_cluster":{"create_replica_methods":["bootstrap_standby_with_wale","basebackup_fast_xlog"],"restore_command":"envdir \"/run/etc/wal-e.d/env-standby\" /scripts/restore_command.sh \"%f\" \"%p\""}, "ttl": 20}`
585+ r = ioutil .NopCloser (bytes .NewReader ([]byte (configJson )))
586+ response = http.Response {
587+ StatusCode : 200 ,
588+ Body : r ,
589+ }
590+ mockClient .EXPECT ().Get (gomock .Any ()).Return (& response , nil ).AnyTimes ()
591+
592+ pods , err := cluster .listPods ()
593+ assert .NoError (t , err )
594+
595+ _ , _ , err = cluster .patroni .GetConfig (& pods [0 ])
596+ assert .NoError (t , err )
597+ // ToDo extend GetConfig to return standy_cluster setting to compare
598+ /*
599+ defaultStandbyParameters := map[string]interface{}{
600+ "create_replica_methods": []string{"bootstrap_standby_with_wale", "basebackup_fast_xlog"},
601+ "restore_command": "envdir \"/run/etc/wal-e.d/env-standby\" /scripts/restore_command.sh \"%f\" \"%p\"",
602+ }
603+ assert.True(t, reflect.DeepEqual(defaultStandbyParameters, standbyCluster))
604+ */
605+ // remove standby section
606+ cluster .Spec .StandbyCluster = & acidv1.StandbyDescription {}
607+ cluster .syncStatefulSet ()
608+ updatedSts2 := cluster .Statefulset
609+
610+ // check that pods do not have a STANDBY_* environment variable
611+ assert .NotContains (t , updatedSts2 .Spec .Template .Spec .Containers [0 ].Env , v1.EnvVar {Name : "STANDBY_METHOD" , Value : "STANDBY_WITH_WALE" })
612+
613+ // this should update the Patroni config again
614+ err = cluster .syncStandbyClusterConfiguration ()
615+ assert .NoError (t , err )
616+ }
617+
483618func TestUpdateSecret (t * testing.T ) {
484619 testName := "test syncing secrets"
485620 client , _ := newFakeK8sSyncSecretsClient ()
0 commit comments