@@ -320,7 +320,7 @@ def _on_topic_requested(self, event: TopicRequestedEvent):
320
320
321
321
# Increment this PATCH version before using `charmcraft publish-lib` or reset
322
322
# to 0 if you are raising the major API version
323
- LIBPATCH = 22
323
+ LIBPATCH = 24
324
324
325
325
PYDEPS = ["ops>=2.0.0" ]
326
326
@@ -526,7 +526,16 @@ def get_content(self) -> Dict[str, str]:
526
526
"""Getting cached secret content."""
527
527
if not self ._secret_content :
528
528
if self .meta :
529
- self ._secret_content = self .meta .get_content ()
529
+ try :
530
+ self ._secret_content = self .meta .get_content (refresh = True )
531
+ except (ValueError , ModelError ) as err :
532
+ # https://bugs.launchpad.net/juju/+bug/2042596
533
+ # Only triggered when 'refresh' is set
534
+ msg = "ERROR either URI or label should be used for getting an owned secret but not both"
535
+ if isinstance (err , ModelError ) and msg not in str (err ):
536
+ raise
537
+ # Due to: ValueError: Secret owner cannot use refresh=True
538
+ self ._secret_content = self .meta .get_content ()
530
539
return self ._secret_content
531
540
532
541
def set_content (self , content : Dict [str , str ]) -> None :
@@ -807,6 +816,9 @@ def _fetch_relation_data_without_secrets(
807
816
This is used typically when the Provides side wants to read the Requires side's data,
808
817
or when the Requires side may want to read its own data.
809
818
"""
819
+ if app not in relation .data or not relation .data [app ]:
820
+ return {}
821
+
810
822
if fields :
811
823
return {k : relation .data [app ][k ] for k in fields if k in relation .data [app ]}
812
824
else :
@@ -830,6 +842,9 @@ def _fetch_relation_data_with_secrets(
830
842
normal_fields = []
831
843
832
844
if not fields :
845
+ if app not in relation .data or not relation .data [app ]:
846
+ return {}
847
+
833
848
all_fields = list (relation .data [app ].keys ())
834
849
normal_fields = [field for field in all_fields if not self ._is_secret_field (field )]
835
850
@@ -853,8 +868,11 @@ def _fetch_relation_data_with_secrets(
853
868
854
869
def _update_relation_data_without_secrets (
855
870
self , app : Application , relation : Relation , data : Dict [str , str ]
856
- ):
871
+ ) -> None :
857
872
"""Updating databag contents when no secrets are involved."""
873
+ if app not in relation .data or relation .data [app ] is None :
874
+ return
875
+
858
876
if any (self ._is_secret_field (key ) for key in data .keys ()):
859
877
raise SecretsIllegalUpdateError ("Can't update secret {key}." )
860
878
@@ -865,8 +883,19 @@ def _delete_relation_data_without_secrets(
865
883
self , app : Application , relation : Relation , fields : List [str ]
866
884
) -> None :
867
885
"""Remove databag fields 'fields' from Relation."""
886
+ if app not in relation .data or not relation .data [app ]:
887
+ return
888
+
868
889
for field in fields :
869
- relation .data [app ].pop (field )
890
+ try :
891
+ relation .data [app ].pop (field )
892
+ except KeyError :
893
+ logger .debug (
894
+ "Non-existing field was attempted to be removed from the databag %s, %s" ,
895
+ str (relation .id ),
896
+ str (field ),
897
+ )
898
+ pass
870
899
871
900
# Public interface methods
872
901
# Handling Relation Fields seamlessly, regardless if in databag or a Juju Secret
@@ -880,9 +909,6 @@ def get_relation(self, relation_name, relation_id) -> Relation:
880
909
"Relation %s %s couldn't be retrieved" , relation_name , relation_id
881
910
)
882
911
883
- if not relation .app :
884
- raise DataInterfacesError ("Relation's application missing" )
885
-
886
912
return relation
887
913
888
914
def fetch_relation_data (
@@ -1068,7 +1094,7 @@ def _delete_relation_secret(
1068
1094
secret = self ._get_relation_secret (relation .id , group )
1069
1095
1070
1096
if not secret :
1071
- logging .error ("Can't update secret for relation %s" , str (relation .id ))
1097
+ logging .error ("Can't delete secret for relation %s" , str (relation .id ))
1072
1098
return False
1073
1099
1074
1100
old_content = secret .get_content ()
@@ -1089,7 +1115,10 @@ def _delete_relation_secret(
1089
1115
# Remove secret from the relation if it's fully gone
1090
1116
if not new_content :
1091
1117
field = self ._generate_secret_field_name (group )
1092
- relation .data [self .local_app ].pop (field )
1118
+ try :
1119
+ relation .data [self .local_app ].pop (field )
1120
+ except KeyError :
1121
+ pass
1093
1122
1094
1123
# Return the content that was removed
1095
1124
return True
@@ -1807,7 +1836,8 @@ def _assign_relation_alias(self, relation_id: int) -> None:
1807
1836
1808
1837
# We need to set relation alias also on the application level so,
1809
1838
# it will be accessible in show-unit juju command, executed for a consumer application unit
1810
- self .update_relation_data (relation_id , {"alias" : available_aliases [0 ]})
1839
+ if self .local_unit .is_leader ():
1840
+ self .update_relation_data (relation_id , {"alias" : available_aliases [0 ]})
1811
1841
1812
1842
def _emit_aliased_event (self , event : RelationChangedEvent , event_name : str ) -> None :
1813
1843
"""Emit an aliased event to a particular relation if it has an alias.
@@ -1894,6 +1924,9 @@ def _on_relation_created_event(self, event: RelationCreatedEvent) -> None:
1894
1924
1895
1925
# Sets both database and extra user roles in the relation
1896
1926
# if the roles are provided. Otherwise, sets only the database.
1927
+ if not self .local_unit .is_leader ():
1928
+ return
1929
+
1897
1930
if self .extra_user_roles :
1898
1931
self .update_relation_data (
1899
1932
event .relation .id ,
@@ -2153,6 +2186,9 @@ def _on_relation_created_event(self, event: RelationCreatedEvent) -> None:
2153
2186
"""Event emitted when the Kafka relation is created."""
2154
2187
super ()._on_relation_created_event (event )
2155
2188
2189
+ if not self .local_unit .is_leader ():
2190
+ return
2191
+
2156
2192
# Sets topic, extra user roles, and "consumer-group-prefix" in the relation
2157
2193
relation_data = {
2158
2194
f : getattr (self , f .replace ("-" , "_" ), "" )
@@ -2325,6 +2361,9 @@ def _on_relation_created_event(self, event: RelationCreatedEvent) -> None:
2325
2361
"""Event emitted when the OpenSearch relation is created."""
2326
2362
super ()._on_relation_created_event (event )
2327
2363
2364
+ if not self .local_unit .is_leader ():
2365
+ return
2366
+
2328
2367
# Sets both index and extra user roles in the relation if the roles are provided.
2329
2368
# Otherwise, sets only the index.
2330
2369
data = {"index" : self .index }
0 commit comments