Steps to reproduce
This charm demonstrates the issue:
#!/usr/bin/env python3
import logging
import ops
from charms.data_platform_libs.v0.data_secrets import SecretCache, generate_secret_label, SecretAlreadyExistsError
logger = logging.getLogger(__name__)
class MysqlOperator348BugCharm(ops.CharmBase):
def __init__(self, *args):
super().__init__(*args)
self.secrets = SecretCache(self)
self.framework.observe(self.on.install, self._on_install)
def _on_install(self, event: ops.InstallEvent):
secret1 = {"name1": "abcdefgh"}
label1 = generate_secret_label(self, "app")
self.secrets.add(label1, secret1, "app")
secret2 = {"name2": "password"}
label2 = generate_secret_label(self, "app")
logger.info(f"label1: {label1}, label2: {label2}, secrets: {self.secrets._secrets}")
try:
self.secrets.add(label2, secret2, "app")
except SecretAlreadyExistsError as e:
logger.error("Failed to add second secret: %s", e)
else:
logger.info(f"label1: {label1}, label2: {label2}, secrets: {self.secrets._secrets}")
if __name__ == "__main__": # pragma: nocover
ops.main(MysqlOperator348BugCharm) # type: ignore
Note that you need to have the main version of the data_platform_libs, not one from a charmcraft fetch.
Expected behavior
With the above charm, the first INFO logging line should look something like:
label1: something, label2: something-else, secrets: {'something': <...>}
And there should be a second one like:
label1: something, label2: something-else, secrets: {'something': <...>, 'something-else': <...>}
Actual behavior
With the above charm, the logging output is:
unit-secret-bug-0: 09:54:30 INFO unit.secret-bug/0.juju-log label1: secret-bug.app, label2: secret-bug.app, secrets: {'secret-bug.app': <charms.data_platform_libs.v0.data_secrets.CachedSecret object at 0x7f5da6ed24a0>}
unit-secret-bug-0: 09:54:30 ERROR unit.secret-bug/0.juju-log Failed to add second secret: Secret secret-bug.app already exists
The issue is that the generate_secret_label method in data_secrets.py takes the charm and the scope as arguments, and uses the charm's app name and the scope to form the label. The app name is obviously the same across the app, and the scope is either app or unit. This means that if you try to get a label for an app secret, you'll always get exactly the same string. This effectively means that the SecretCache system as used by mysql.py will only store a single app secret, because it believes that any secret is already in the cache after one is.
Versions
Operating system: Ubuntu 23.10
Juju CLI: 3.1.6-genericlinux-amd64
(Note that the code never gets to Juju in the problematic area).
Juju agent: 3.1.5
Charm revision: N/A
LXD: N/A
Log output
Juju debug log:
Copied above.
Additional context
This was introduced in #348. You can also see failing unit tests if you bump your ops requirement to 2.6.0 or higher (I haven't looked at exactly what changes there, but presumably some of the code starts exercising more of the secret support in ops).
Steps to reproduce
This charm demonstrates the issue:
Note that you need to have the
mainversion of thedata_platform_libs, not one from acharmcraft fetch.Expected behavior
With the above charm, the first INFO logging line should look something like:
label1: something, label2: something-else, secrets: {'something': <...>}And there should be a second one like:
label1: something, label2: something-else, secrets: {'something': <...>, 'something-else': <...>}Actual behavior
With the above charm, the logging output is:
The issue is that the
generate_secret_labelmethod indata_secrets.pytakes the charm and the scope as arguments, and uses the charm's app name and the scope to form the label. The app name is obviously the same across the app, and the scope is eitherapporunit. This means that if you try to get a label for an app secret, you'll always get exactly the same string. This effectively means that theSecretCachesystem as used bymysql.pywill only store a single app secret, because it believes that any secret is already in the cache after one is.Versions
Operating system: Ubuntu 23.10
Juju CLI: 3.1.6-genericlinux-amd64
(Note that the code never gets to Juju in the problematic area).
Juju agent: 3.1.5
Charm revision: N/A
LXD: N/A
Log output
Juju debug log:
Copied above.
Additional context
This was introduced in #348. You can also see failing unit tests if you bump your
opsrequirement to 2.6.0 or higher (I haven't looked at exactly what changes there, but presumably some of the code starts exercising more of the secret support in ops).