@@ -40,6 +40,7 @@ def setUp(self):
40
40
self .addCleanup (self .harness .cleanup )
41
41
self .harness .begin ()
42
42
self .charm = self .harness .charm
43
+ self ._cluster_name = f"patroni-{ self .charm .app .name } "
43
44
self ._context = {
44
45
"namespace" : self .harness .model .name ,
45
46
"app_name" : self .harness .model .app .name ,
@@ -51,27 +52,75 @@ def setUp(self):
51
52
def use_caplog (self , caplog ):
52
53
self ._caplog = caplog
53
54
55
+ @patch ("charm.PostgresqlOperatorCharm._add_members" )
56
+ @patch ("charm.Client" )
54
57
@patch ("charm.new_password" , return_value = "sekr1t" )
55
58
@patch ("charm.PostgresqlOperatorCharm.get_secret" , return_value = None )
56
59
@patch ("charm.PostgresqlOperatorCharm.set_secret" )
57
60
@patch ("charm.Patroni.reload_patroni_configuration" )
58
61
@patch ("charm.PostgresqlOperatorCharm._patch_pod_labels" )
59
62
@patch ("charm.PostgresqlOperatorCharm._create_services" )
60
- def test_on_leader_elected (self , _ , __ , ___ , _set_secret , _get_secret , _____ ):
61
- # Check that a new password was generated on leader election.
63
+ def test_on_leader_elected (self , _ , __ , ___ , _set_secret , _get_secret , _____ , _client , ______ ):
64
+ # Check that a new password was generated on leader election and nothing is done
65
+ # because the "leader" key is present in the endpoint annotations due to a scale
66
+ # down to zero units.
67
+ with self .harness .hooks_disabled ():
68
+ self .harness .update_relation_data (
69
+ self .rel_id , self .charm .app .name , {"cluster_initialised" : "True" }
70
+ )
71
+ _client .return_value .get .return_value = MagicMock (
72
+ metadata = MagicMock (annotations = ["leader" ])
73
+ )
74
+ _client .return_value .list .side_effect = [
75
+ [MagicMock (metadata = MagicMock (name = "fakeName1" , namespace = "fakeNamespace" ))],
76
+ [MagicMock (metadata = MagicMock (name = "fakeName2" , namespace = "fakeNamespace" ))],
77
+ ]
62
78
self .harness .set_leader ()
63
79
assert _set_secret .call_count == 4
64
80
_set_secret .assert_any_call ("app" , "operator-password" , "sekr1t" )
65
81
_set_secret .assert_any_call ("app" , "replication-password" , "sekr1t" )
66
82
_set_secret .assert_any_call ("app" , "rewind-password" , "sekr1t" )
67
83
_set_secret .assert_any_call ("app" , "monitoring-password" , "sekr1t" )
84
+ _client .return_value .get .assert_called_once_with (
85
+ Endpoints , name = self ._cluster_name , namespace = self .charm .model .name
86
+ )
87
+ _client .return_value .patch .assert_not_called ()
88
+ self .assertIn (
89
+ "cluster_initialised" , self .harness .get_relation_data (self .rel_id , self .charm .app )
90
+ )
68
91
69
- # Trigger a new leader election and check that the password is still the same.
92
+ # Trigger a new leader election and check that the password is still the same, and that the charm
93
+ # fixes the missing "leader" key in the endpoint annotations.
94
+ _client .reset_mock ()
95
+ _client .return_value .get .return_value = MagicMock (metadata = MagicMock (annotations = []))
70
96
_set_secret .reset_mock ()
71
97
_get_secret .return_value = "test"
72
98
self .harness .set_leader (False )
73
99
self .harness .set_leader ()
74
100
assert _set_secret .call_count == 0
101
+ _client .return_value .get .assert_called_once_with (
102
+ Endpoints , name = self ._cluster_name , namespace = self .charm .model .name
103
+ )
104
+ _client .return_value .patch .assert_called_once_with (
105
+ Endpoints ,
106
+ name = self ._cluster_name ,
107
+ namespace = self .charm .model .name ,
108
+ obj = {"metadata" : {"annotations" : {"leader" : "postgresql-k8s-0" }}},
109
+ )
110
+ self .assertNotIn (
111
+ "cluster_initialised" , self .harness .get_relation_data (self .rel_id , self .charm .app )
112
+ )
113
+
114
+ # Test a failure in fixing the "leader" key in the endpoint annotations.
115
+ _client .return_value .patch .side_effect = _FakeApiError
116
+ with self .assertRaises (_FakeApiError ):
117
+ self .harness .set_leader (False )
118
+ self .harness .set_leader ()
119
+
120
+ # Test no failure if the resource doesn't exist.
121
+ _client .return_value .patch .side_effect = _FakeApiError (404 )
122
+ self .harness .set_leader (False )
123
+ self .harness .set_leader ()
75
124
76
125
@patch ("charm.Patroni.rock_postgresql_version" , new_callable = PropertyMock )
77
126
@patch ("charm.Patroni.primary_endpoint_ready" , new_callable = PropertyMock )
@@ -653,28 +702,42 @@ def test_set_secret(self, _, __):
653
702
@patch ("charm.Client" )
654
703
def test_on_stop (self , _client ):
655
704
# Test a successful run of the hook.
656
- with self .assertNoLogs ("charm" , "ERROR" ):
657
- _client .return_value .get .return_value = MagicMock (
658
- metadata = MagicMock (ownerReferences = "fakeOwnerReferences" )
659
- )
660
- _client .return_value .list .side_effect = [
661
- [MagicMock (metadata = MagicMock (name = "fakeName1" , namespace = "fakeNamespace" ))],
662
- [MagicMock (metadata = MagicMock (name = "fakeName2" , namespace = "fakeNamespace" ))],
663
- ]
664
- self .charm .on .stop .emit ()
665
- _client .return_value .get .assert_called_once_with (
666
- res = Pod , name = "postgresql-k8s-0" , namespace = self .charm .model .name
667
- )
668
- for kind in [Endpoints , Service ]:
669
- _client .return_value .list .assert_any_call (
670
- kind ,
671
- namespace = self .charm .model .name ,
672
- labels = {"app.juju.is/created-by" : self .charm .app .name },
705
+ for planned_units , relation_data in {
706
+ 0 : {},
707
+ 1 : {"some-relation-data" : "some-value" },
708
+ }.items ():
709
+ self .harness .set_planned_units (planned_units )
710
+ with self .harness .hooks_disabled ():
711
+ self .harness .update_relation_data (
712
+ self .rel_id ,
713
+ self .charm .unit .name ,
714
+ {"some-relation-data" : "some-value" },
673
715
)
674
- self .assertEqual (_client .return_value .apply .call_count , 2 )
716
+ with self .assertNoLogs ("charm" , "ERROR" ):
717
+ _client .return_value .get .return_value = MagicMock (
718
+ metadata = MagicMock (ownerReferences = "fakeOwnerReferences" )
719
+ )
720
+ _client .return_value .list .side_effect = [
721
+ [MagicMock (metadata = MagicMock (name = "fakeName1" , namespace = "fakeNamespace" ))],
722
+ [MagicMock (metadata = MagicMock (name = "fakeName2" , namespace = "fakeNamespace" ))],
723
+ ]
724
+ self .charm .on .stop .emit ()
725
+ _client .return_value .get .assert_called_once_with (
726
+ res = Pod , name = "postgresql-k8s-0" , namespace = self .charm .model .name
727
+ )
728
+ for kind in [Endpoints , Service ]:
729
+ _client .return_value .list .assert_any_call (
730
+ kind ,
731
+ namespace = self .charm .model .name ,
732
+ labels = {"app.juju.is/created-by" : self .charm .app .name },
733
+ )
734
+ self .assertEqual (_client .return_value .apply .call_count , 2 )
735
+ self .assertEqual (
736
+ self .harness .get_relation_data (self .rel_id , self .charm .unit ), relation_data
737
+ )
738
+ _client .reset_mock ()
675
739
676
740
# Test when the charm fails to get first pod info.
677
- _client .reset_mock ()
678
741
_client .return_value .get .side_effect = _FakeApiError
679
742
with self .assertLogs ("charm" , "ERROR" ) as logs :
680
743
self .charm .on .stop .emit ()
0 commit comments