12
12
CollectStatusEvent ,
13
13
ConfigChangedEvent ,
14
14
InstallEvent ,
15
+ ModelError ,
15
16
Object ,
17
+ SecretChangedEvent ,
18
+ SecretNotFoundError ,
16
19
StartEvent ,
17
20
UpdateStatusEvent ,
18
21
)
@@ -54,6 +57,7 @@ def __init__(
54
57
self .framework .observe (self .charm .on .start , self ._on_start )
55
58
self .framework .observe (self .charm .on .install , self ._on_install )
56
59
self .framework .observe (self .charm .on .config_changed , self ._on_config_changed )
60
+ self .framework .observe (self .charm .on .secret_changed , self ._on_secret_changed )
57
61
self .framework .observe (self .charm .on .update_status , self ._on_update_status )
58
62
self .framework .observe (self .charm .on .collect_unit_status , self ._on_collect_unit_status )
59
63
self .framework .observe (self .charm .on .collect_app_status , self ._on_collect_app_status )
@@ -75,21 +79,20 @@ def _on_start(self, event: StartEvent) -> None:
75
79
return
76
80
77
81
try :
78
- if self .charm .unit .is_leader ():
79
- self .state .cluster .cluster_name = self .charm .config .cluster_name
80
- self .state .cluster .seeds = [self .state .unit .peer_url ]
81
82
self .config_manager .render_env (
82
83
cassandra_limit_memory_mb = 1024 if self .charm .config .profile == "testing" else None
83
84
)
85
+ if self .charm .unit .is_leader ():
86
+ self .state .cluster .cluster_name = self .charm .config .cluster_name
87
+ self .state .cluster .seeds = [self .state .unit .peer_url ]
88
+ self .state .cluster .cassandra_password_secret = self ._acquire_cassandra_password ()
89
+ self ._start_password_change (event )
90
+ return
84
91
except ValidationError as e :
85
92
logger .debug (f"Config haven't passed validation: { e } " )
86
93
event .defer ()
87
94
return
88
95
89
- if not self .state .cluster .cassandra_password_secret :
90
- self ._start_password_change (event )
91
- return
92
-
93
96
self .config_manager .render_cassandra_config (
94
97
cluster_name = self .state .cluster .cluster_name ,
95
98
listen_address = self .state .unit .ip ,
@@ -98,9 +101,27 @@ def _on_start(self, event: StartEvent) -> None:
98
101
)
99
102
self .charm .on [str (self .bootstrap_manager .name )].acquire_lock .emit ()
100
103
104
+ def _acquire_cassandra_password (self ) -> str :
105
+ if self .charm .config .system_users :
106
+ try :
107
+ if (
108
+ password := self .model .get_secret (id = self .charm .config .system_users )
109
+ .get_content (refresh = True )
110
+ .get ("cassandra-password" )
111
+ ):
112
+ return password
113
+ except SecretNotFoundError :
114
+ # TODO: logging.
115
+ pass
116
+ except ModelError :
117
+ pass
118
+ if self .state .cluster .cassandra_password_secret :
119
+ return self .state .cluster .cassandra_password_secret
120
+ return self .workload .generate_password ()
121
+
101
122
def _start_password_change (self , event : StartEvent ) -> None :
102
123
self .config_manager .render_cassandra_config (
103
- cluster_name = self .charm . config .cluster_name ,
124
+ cluster_name = self .state . cluster .cluster_name ,
104
125
listen_address = "127.0.0.1" ,
105
126
seeds = ["127.0.0.1:7000" ],
106
127
authentication = False ,
@@ -113,25 +134,31 @@ def _finalize_password_change(self, event: StartEvent) -> None:
113
134
if not self .cluster_manager .is_healthy :
114
135
event .defer ()
115
136
return
116
- password = self .workload . generate_password ()
117
- self . database_manager . update_system_user_password ( "cassandra" , password )
118
- self . state . cluster . cassandra_password_secret = password
119
- self .cluster_manager .flush_tables ( "system_auth" , [ "roles" ] )
137
+ self .database_manager . update_system_user_password (
138
+ "cassandra" , self . state . cluster . cassandra_password_secret
139
+ )
140
+ self .cluster_manager .prepare_shutdown ( )
120
141
self .config_manager .render_cassandra_config (
121
- cluster_name = self .charm . config .cluster_name ,
142
+ cluster_name = self .state . cluster .cluster_name ,
122
143
listen_address = self .state .unit .ip ,
123
144
seeds = self .state .cluster .seeds ,
124
145
authentication = True ,
125
146
)
126
147
self .charm .on [str (self .bootstrap_manager .name )].acquire_lock .emit ()
127
148
128
- def _on_config_changed (self , _ : ConfigChangedEvent ) -> None :
129
- if self .state .unit .workload_state not in [
130
- UnitWorkloadState . STARTING ,
131
- UnitWorkloadState .ACTIVE ,
132
- ]:
149
+ def _on_config_changed (self , event : ConfigChangedEvent ) -> None :
150
+ if self .state .unit .workload_state == UnitWorkloadState . INSTALLING :
151
+ return
152
+ if self . state . unit . workload_state != UnitWorkloadState .ACTIVE :
153
+ event . defer ()
133
154
return
134
155
try :
156
+ if self .charm .unit .is_leader () and self .state .cluster .cassandra_password_secret != (
157
+ password := self ._acquire_cassandra_password ()
158
+ ):
159
+ self .database_manager .update_system_user_password ("cassandra" , password )
160
+ self .state .cluster .cassandra_password_secret = password
161
+ self .cluster_manager .prepare_shutdown ()
135
162
# TODO: cluster_name change
136
163
self .config_manager .render_env (
137
164
cassandra_limit_memory_mb = 1024 if self .charm .config .profile == "testing" else None
@@ -141,8 +168,30 @@ def _on_config_changed(self, _: ConfigChangedEvent) -> None:
141
168
logger .debug (f"Config haven't passed validation: { e } " )
142
169
return
143
170
144
- if self .state .unit .workload_state == UnitWorkloadState .ACTIVE :
145
- self .charm .on [str (self .bootstrap_manager .name )].acquire_lock .emit ()
171
+ self .charm .on [str (self .bootstrap_manager .name )].acquire_lock .emit ()
172
+
173
+ def _on_secret_changed (self , event : SecretChangedEvent ) -> None :
174
+ if not self .charm .unit .is_leader ():
175
+ return
176
+
177
+ if self .state .unit .workload_state == UnitWorkloadState .INSTALLING :
178
+ return
179
+
180
+ try :
181
+ if event .secret .id != self .charm .config .system_users :
182
+ return
183
+
184
+ if self .state .unit .workload_state != UnitWorkloadState .ACTIVE :
185
+ event .defer ()
186
+ return
187
+
188
+ if self .state .cluster .cassandra_password_secret != (
189
+ password := self ._acquire_cassandra_password ()
190
+ ):
191
+ self .database_manager .update_system_user_password ("cassandra" , password )
192
+ self .state .cluster .cassandra_password_secret = password
193
+ except ValidationError :
194
+ return
146
195
147
196
def _on_update_status (self , _ : UpdateStatusEvent ) -> None :
148
197
# TODO: add peer relation change hook for subordinates to update leader address too
0 commit comments