Skip to content

Commit

Permalink
config[x] with type:secret returns a Secret.
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyandrewmeyer committed Apr 10, 2024
1 parent ddfb86b commit 476a05e
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
2 changes: 2 additions & 0 deletions ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
'CollectMetricsEvent',
'CollectStatusEvent',
'ConfigChangedEvent',
'ConfigMeta',
'ContainerBase',
'ContainerMeta',
'ContainerStorageMeta',
Expand Down Expand Up @@ -198,6 +199,7 @@
CollectMetricsEvent,
CollectStatusEvent,
ConfigChangedEvent,
ConfigMeta,
ContainerBase,
ContainerMeta,
ContainerStorageMeta,
Expand Down
15 changes: 12 additions & 3 deletions ops/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __init__(self, meta: 'ops.charm.CharmMeta', backend: '_ModelBackend',
relations: Dict[str, 'ops.RelationMeta'] = meta.relations
self._relations = RelationMapping(relations, self.unit, self._backend, self._cache,
broken_relation_id=broken_relation_id)
self._config = ConfigData(self._backend)
self._config = ConfigData(self._backend, meta.config)
resources: Iterable[str] = meta.resources
self._resources = Resources(list(resources), self._backend)
self._pod = Pod(self._backend)
Expand Down Expand Up @@ -1724,11 +1724,20 @@ class ConfigData(LazyMapping):
This class should not be instantiated directly. It should be accessed via :attr:`Model.config`.
"""

def __init__(self, backend: '_ModelBackend'):
def __init__(self, backend: '_ModelBackend',
config: Optional[Dict[str, 'ops.ConfigMeta']] = None):
self._backend = backend
self._config = config

def _load(self):
return self._backend.config_get()
data = self._backend.config_get()
if self._config:
# Convert any type:secret options to Secret objects.
# The simple types (bool, int, float, str) are correctly typed in the JSON.
for option in self._config.values():
if option.type == "secret" and option.name in data:
data[option.name] = Secret(self._backend, data[option.name])
return data


class StatusBase:
Expand Down
9 changes: 6 additions & 3 deletions ops/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
from ops import charm, framework, model, pebble, storage
from ops._private import yaml
from ops.charm import CharmBase, CharmMeta, RelationRole
from ops.model import Container, RelationNotFoundError, _ConfigOption, _NetworkDict
from ops.model import Container, RelationNotFoundError, Secret, _ConfigOption, _NetworkDict
from ops.pebble import ExecProcess

ReadableBuffer = Union[bytes, str, StringIO, BytesIO, BinaryIO]
Expand Down Expand Up @@ -1307,7 +1307,7 @@ def _emit_relation_changed(self, relation_id: int, app_or_unit: str):

def _update_config(
self,
key_values: Optional[Mapping[str, Union[str, int, float, bool]]] = None,
key_values: Optional[Mapping[str, Union[str, int, float, bool, Secret]]] = None,
unset: Iterable[str] = (),
) -> None:
"""Update the config as seen by the charm.
Expand All @@ -1330,6 +1330,9 @@ def _update_config(
for key, value in key_values.items():
if key in config._defaults:
if value is not None:
if self._meta.config[key].type == 'secret' and isinstance(value, str):
# Promote this to an actual Secret object.
value = Secret(self._backend, value)
config._config_set(key, value)
else:
raise ValueError(f"unknown config option: '{key}'")
Expand All @@ -1344,7 +1347,7 @@ def _update_config(

def update_config(
self,
key_values: Optional[Mapping[str, Union[str, int, float, bool]]] = None,
key_values: Optional[Mapping[str, Union[str, int, float, bool, Secret]]] = None,
unset: Iterable[str] = (),
) -> None:
"""Update the config as seen by the charm.
Expand Down
12 changes: 11 additions & 1 deletion test/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def setUp(self):
type: int
qux:
type: boolean
secretfoo:
type: secret
secretbar:
type: secret
''')
self.addCleanup(self.harness.cleanup)
self.relation_id_db0 = self.harness.add_relation('db0', 'db')
Expand Down Expand Up @@ -618,11 +622,17 @@ def test_relation_no_units(self):

def test_config(self):
self.harness._get_backend_calls(reset=True)
self.harness.update_config({'foo': 'foo', 'bar': 1, 'qux': True})
secretfoo_id = self.harness.add_user_secret({"password": "xxxxxxxx"})
secretbar_id = self.harness.add_user_secret({"certificate": "xxxxxxxx"})
secretbar = self.model.get_secret(id=secretbar_id)
self.harness.update_config({'foo': 'foo', 'bar': 1, 'qux': True,
'secretfoo': secretfoo_id, 'secretbar': secretbar})
self.assertEqual(self.model.config, {
'foo': 'foo',
'bar': 1,
'qux': True,
'secretfoo': self.model.get_secret(id=secretfoo_id),
'secretbar': secretbar,
})
with self.assertRaises(TypeError):
# Confirm that we cannot modify config values.
Expand Down

0 comments on commit 476a05e

Please sign in to comment.