Adds support for getting/setting config on a model (#152)
authorAdam Stokes <battlemidget@users.noreply.github.com>
Tue, 27 Jun 2017 20:08:41 +0000 (16:08 -0400)
committerCory Johns <johnsca@gmail.com>
Tue, 27 Jun 2017 20:08:41 +0000 (16:08 -0400)
* Adds support for getting/setting config on a model

Signed-off-by: Adam Stokes <battlemidget@users.noreply.github.com>
* Fix docstring parameter

Signed-off-by: Adam Stokes <battlemidget@users.noreply.github.com>
* Support ConfigValue type for interacting with model config

juju/client/overrides.py
juju/model.py
tests/integration/test_model.py

index 6ad47e9..f439adb 100644 (file)
@@ -10,6 +10,7 @@ __all__ = [
     'Delta',
     'Number',
     'Binary',
+    'ConfigValue',
 ]
 
 __patches__ = [
@@ -265,3 +266,10 @@ class Binary(_definitions.Binary):
 
     def to_json(self):
         return self.serialize()
+
+
+class ConfigValue(_definitions.ConfigValue):
+    def __repr__(self):
+        return '<{} source={} value={}>'.format(type(self).__name__,
+                                                repr(self.source),
+                                                repr(self.value))
index 7b86ba3..bd8709a 100644 (file)
@@ -22,6 +22,7 @@ import theblues.errors
 from . import tag, utils
 from .client import client
 from .client import connection
+from .client.client import ConfigValue
 from .constraints import parse as parse_constraints, normalize_key
 from .delta import get_entity_delta
 from .delta import get_entity_class
@@ -1255,11 +1256,20 @@ class Model(object):
         """
         raise NotImplementedError()
 
-    def get_config(self):
+    async def get_config(self):
         """Return the configuration settings for this model.
 
+        :returns: A ``dict`` mapping keys to `ConfigValue` instances,
+            which have `source` and `value` attributes.
         """
-        raise NotImplementedError()
+        config_facade = client.ModelConfigFacade.from_connection(
+            self.connection
+        )
+        result = await config_facade.ModelGet()
+        config = result.config
+        for key, value in config.items():
+            config[key] = ConfigValue.from_json(value)
+        return config
 
     def get_constraints(self):
         """Return the machine constraints for this model.
@@ -1440,13 +1450,19 @@ class Model(object):
         """
         raise NotImplementedError()
 
-    def set_config(self, **config):
+    async def set_config(self, config):
         """Set configuration keys on this model.
 
-        :param \*\*config: Config key/values
-
+        :param dict config: Mapping of config keys to either string values or
+            `ConfigValue` instances, as returned by `get_config`.
         """
-        raise NotImplementedError()
+        config_facade = client.ModelConfigFacade.from_connection(
+            self.connection
+        )
+        for key, value in config.items():
+            if isinstance(value, ConfigValue):
+                config[key] = value.value
+        await config_facade.ModelSet(config)
 
     def set_constraints(self, constraints):
         """Set machine constraints on this model.
index 37f51c0..8506786 100644 (file)
@@ -5,10 +5,12 @@ import pytest
 
 from .. import base
 from juju.model import Model
+from juju.client.client import ConfigValue
 
 MB = 1
 GB = 1024
-SSH_KEY = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsYMJGNGG74HAJha3n2CFmWYsOOaORnJK6VqNy86pj0MIpvRXBzFzVy09uPQ66GOQhTEoJHEqE77VMui7+62AcMXT+GG7cFHcnU8XVQsGM6UirCcNyWNysfiEMoAdZScJf/GvoY87tMEszhZIUV37z8PUBx6twIqMdr31W1J0IaPa+sV6FEDadeLaNTvancDcHK1zuKsL39jzAg7+LYjKJfEfrsQP+lj/EQcjtKqlhVS5kzsJVfx8ZEd0xhW5G7N6bCdKNalS8mKCMaBXJpijNQ82AiyqCIDCRrre2To0/i7pTjRiL0U9f9mV3S4NJaQaokR050w/ZLySFf6F7joJT mathijs@Qrama-Mathijs'
+SSH_KEY = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsYMJGNGG74HAJha3n2CFmWYsOOaORnJK6VqNy86pj0MIpvRXBzFzVy09uPQ66GOQhTEoJHEqE77VMui7+62AcMXT+GG7cFHcnU8XVQsGM6UirCcNyWNysfiEMoAdZScJf/GvoY87tMEszhZIUV37z8PUBx6twIqMdr31W1J0IaPa+sV6FEDadeLaNTvancDcHK1zuKsL39jzAg7+LYjKJfEfrsQP+lj/EQcjtKqlhVS5kzsJVfx8ZEd0xhW5G7N6bCdKNalS8mKCMaBXJpijNQ82AiyqCIDCRrre2To0/i7pTjRiL0U9f9mV3S4NJaQaokR050w/ZLySFf6F7joJT mathijs@Qrama-Mathijs'  # noqa
+
 
 @base.bootstrapped
 @pytest.mark.asyncio
@@ -221,6 +223,19 @@ async def test_watcher_reconnect(event_loop):
         assert model.connection.is_open
 
 
+@base.bootstrapped
+@pytest.mark.asyncio
+async def test_config(event_loop):
+    async with base.CleanModel() as model:
+        await model.set_config({
+            'extra-info': 'booyah',
+            'test-mode': ConfigValue(value=True),
+        })
+        result = await model.get_config()
+        assert 'extra-info' in result
+        assert result['extra-info'].source == 'model'
+        assert result['extra-info'].value == 'booyah'
+
 # @base.bootstrapped
 # @pytest.mark.asyncio
 # async def test_grant(event_loop)