13
13
PostgreSQLUpdateUserPasswordError ,
14
14
)
15
15
from charms .postgresql_k8s .v0 .postgresql_tls import PostgreSQLTLS
16
- from charms .rolling_ops .v0 .rollingops import RollingOpsManager
16
+ from charms .rolling_ops .v0 .rollingops import RollingOpsManager , RunWithLock
17
17
from lightkube import ApiError , Client , codecs
18
18
from lightkube .models .core_v1 import ServicePort
19
19
from lightkube .resources .core_v1 import Endpoints , Pod , Service
@@ -76,7 +76,6 @@ def __init__(self, *args):
76
76
self ._context = {"namespace" : self ._namespace , "app_name" : self ._name }
77
77
self .cluster_name = f"patroni-{ self ._name } "
78
78
79
- self .framework .observe (self .on .install , self ._on_install )
80
79
self .framework .observe (self .on .config_changed , self ._on_config_changed )
81
80
self .framework .observe (self .on .leader_elected , self ._on_leader_elected )
82
81
self .framework .observe (self .on [PEER ].relation_changed , self ._on_peer_relation_changed )
@@ -211,10 +210,6 @@ def _on_peer_relation_departed(self, event: RelationDepartedEvent) -> None:
211
210
self .postgresql_client_relation .update_read_only_endpoint ()
212
211
self ._remove_from_endpoints (endpoints_to_remove )
213
212
214
- # Update the replication configuration.
215
- self ._patroni .render_postgresql_conf_file ()
216
- self ._patroni .reload_patroni_configuration ()
217
-
218
213
def _on_peer_relation_changed (self , event : RelationChangedEvent ) -> None :
219
214
"""Reconfigure cluster members."""
220
215
# The cluster must be initialized first in the leader unit
@@ -262,11 +257,6 @@ def _on_peer_relation_changed(self, event: RelationChangedEvent) -> None:
262
257
263
258
self .unit .status = ActiveStatus ()
264
259
265
- def _on_install (self , _ ) -> None :
266
- """Event handler for InstallEvent."""
267
- # Creates custom postgresql.conf file.
268
- self ._patroni .render_postgresql_conf_file ()
269
-
270
260
def _on_config_changed (self , _ ) -> None :
271
261
"""Handle the config-changed event."""
272
262
# TODO: placeholder method to implement logic specific to configuration change.
@@ -384,13 +374,6 @@ def _on_leader_elected(self, event: LeaderElectedEvent) -> None:
384
374
385
375
self ._add_members (event )
386
376
387
- # Update the replication configuration.
388
- self ._patroni .render_postgresql_conf_file ()
389
- try :
390
- self ._patroni .reload_patroni_configuration ()
391
- except RetryError :
392
- pass # This error can happen in the first leader election, as Patroni is not running yet.
393
-
394
377
def _create_pgdata (self , container : Container ):
395
378
"""Create the PostgreSQL data directory."""
396
379
path = f"{ self ._storage_path } /pgdata"
@@ -410,9 +393,6 @@ def _on_postgresql_pebble_ready(self, event: WorkloadEvent) -> None:
410
393
# where the volume is mounted with more restrictive permissions.
411
394
self ._create_pgdata (container )
412
395
413
- # Create a new config layer.
414
- new_layer = self ._postgresql_layer ()
415
-
416
396
self .unit .set_workload_version (self ._patroni .rock_postgresql_version )
417
397
418
398
# Defer the initialization of the workload in the replicas
@@ -436,18 +416,8 @@ def _on_postgresql_pebble_ready(self, event: WorkloadEvent) -> None:
436
416
event .defer ()
437
417
return
438
418
439
- # Get the current layer.
440
- current_layer = container .get_plan ()
441
- # Check if there are any changes to layer services.
442
- if current_layer .services != new_layer .services :
443
- # Changes were made, add the new layer.
444
- container .add_layer (self ._postgresql_service , new_layer , combine = True )
445
- logging .info ("Added updated layer 'postgresql' to Pebble plan" )
446
- # TODO: move this file generation to on config changed hook
447
- # when adding configs to this charm.
448
- # Restart it and report a new status to Juju.
449
- container .restart (self ._postgresql_service )
450
- logging .info ("Restarted postgresql service" )
419
+ # Start the database service.
420
+ self ._update_pebble_layers ()
451
421
452
422
# Ensure the member is up and running before marking the cluster as initialised.
453
423
if not self ._patroni .member_started :
@@ -840,6 +810,15 @@ def _postgresql_layer(self) -> Layer:
840
810
"group" : WORKLOAD_OS_GROUP ,
841
811
},
842
812
},
813
+ "checks" : {
814
+ self ._postgresql_service : {
815
+ "override" : "replace" ,
816
+ "level" : "ready" ,
817
+ "http" : {
818
+ "url" : f"{ self ._patroni ._patroni_url } /health" ,
819
+ },
820
+ }
821
+ },
843
822
}
844
823
return Layer (layer_config )
845
824
@@ -878,6 +857,15 @@ def push_tls_files_to_workload(self, container: Container = None) -> None:
878
857
user = WORKLOAD_OS_USER ,
879
858
group = WORKLOAD_OS_GROUP ,
880
859
)
860
+ container .push (
861
+ "/usr/local/share/ca-certificates/ca.crt" ,
862
+ ca ,
863
+ make_dirs = True ,
864
+ permissions = 0o400 ,
865
+ user = WORKLOAD_OS_USER ,
866
+ group = WORKLOAD_OS_GROUP ,
867
+ )
868
+ container .exec (["update-ca-certificates" ]).wait ()
881
869
if cert is not None :
882
870
container .push (
883
871
f"{ self ._storage_path } /{ TLS_CERT_FILE } " ,
@@ -890,8 +878,13 @@ def push_tls_files_to_workload(self, container: Container = None) -> None:
890
878
891
879
self .update_config ()
892
880
893
- def _restart (self , _ ) -> None :
881
+ def _restart (self , event : RunWithLock ) -> None :
894
882
"""Restart PostgreSQL."""
883
+ if not self ._patroni .are_all_members_ready ():
884
+ logger .debug ("Early exit _restart: not all members ready yet" )
885
+ event .defer ()
886
+ return
887
+
895
888
try :
896
889
self ._patroni .restart_postgresql ()
897
890
except RetryError :
@@ -900,6 +893,9 @@ def _restart(self, _) -> None:
900
893
self .unit .status = BlockedStatus (error_message )
901
894
return
902
895
896
+ # Update health check URL.
897
+ self ._update_pebble_layers ()
898
+
903
899
# Start or stop the pgBackRest TLS server service when TLS certificate change.
904
900
self .backup .start_stop_pgbackrest_service ()
905
901
@@ -915,7 +911,6 @@ def update_config(self) -> None:
915
911
backup_id = self .app_peer_data .get ("restoring-backup" ),
916
912
stanza = self .app_peer_data .get ("stanza" ),
917
913
)
918
- self ._patroni .render_postgresql_conf_file ()
919
914
if not self ._patroni .member_started :
920
915
# If Patroni/PostgreSQL has not started yet and TLS relations was initialised,
921
916
# then mark TLS as enabled. This commonly happens when the charm is deployed
@@ -934,6 +929,28 @@ def update_config(self) -> None:
934
929
if restart_postgresql :
935
930
self .on [self .restart_manager .name ].acquire_lock .emit ()
936
931
932
+ def _update_pebble_layers (self ) -> None :
933
+ """Update the pebble layers to keep the health check URL up-to-date."""
934
+ container = self .unit .get_container ("postgresql" )
935
+
936
+ # Get the current layer.
937
+ current_layer = container .get_plan ()
938
+
939
+ # Create a new config layer.
940
+ new_layer = self ._postgresql_layer ()
941
+
942
+ # Check if there are any changes to layer services.
943
+ if current_layer .services != new_layer .services :
944
+ # Changes were made, add the new layer.
945
+ container .add_layer (self ._postgresql_service , new_layer , combine = True )
946
+ logging .info ("Added updated layer 'postgresql' to Pebble plan" )
947
+ container .restart (self ._postgresql_service )
948
+ logging .info ("Restarted postgresql service" )
949
+ if current_layer .checks != new_layer .checks :
950
+ # Changes were made, add the new layer.
951
+ container .add_layer (self ._postgresql_service , new_layer , combine = True )
952
+ logging .info ("Updated health checks" )
953
+
937
954
def _unit_name_to_pod_name (self , unit_name : str ) -> str :
938
955
"""Converts unit name to pod name.
939
956
0 commit comments