Added Placement parser.
authorPete Vander Giessen <petevg@gmail.com>
Mon, 28 Nov 2016 21:36:50 +0000 (16:36 -0500)
committerPete Vander Giessen <petevg@gmail.com>
Tue, 29 Nov 2016 14:58:49 +0000 (09:58 -0500)
Interim workaround for https://bugs.launchpad.net/juju/+bug/1645480,
where the websocket API will not accept the placement string that the
planner generates.

.gitignore
juju/application.py
juju/placement.py [new file with mode: 0644]
tests/unit/test_placement.py [new file with mode: 0644]

index 9bde928..f8abe96 100644 (file)
@@ -1,8 +1,10 @@
 *.sw[mnop]
 .venv/
 *.pyc
+*.py~
 docs/_build/
 __pycache__/
 .tox/
 *.egg-info/
 .cache/
+.\#*
index 4a98622..df309b3 100644 (file)
@@ -3,6 +3,7 @@ import logging
 
 from . import model
 from .client import client
+from .placement import parse as parse_placement
 
 log = logging.getLogger(__name__)
 
@@ -83,7 +84,7 @@ class Application(model.ModelEntity):
 
         result = await app_facade.AddUnits(
             application=self.name,
-            placement=to,
+            placement=[parse_placement(to)],
             num_units=count,
         )
 
diff --git a/juju/placement.py b/juju/placement.py
new file mode 100644 (file)
index 0000000..62cd570
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# This module allows us to parse a machine placement directive into a
+# Placement object suitable for passing through the websocket API.
+#
+# Once https://bugs.launchpad.net/juju/+bug/1645480 is addressed, this
+# module should be deprecated.
+#
+
+MACHINE_SCOPE = "#"
+
+from .client import client
+
+def parse(directive):
+    """
+    Given a string in the format `scope:directive`, or simply `scope`
+    or `directive`, return a Placement object suitable for passing
+    back over the websocket API.
+
+    """
+    if directive == "":
+        # Handle null case
+        return None
+
+    if type(directive) in [dict, client.Placement]:
+        # We've been handed something that we can simply hand back to
+        # the api. (Forwards compatibility)
+        return directive
+
+    if ":" in directive:
+        # Planner has given us a scope and directive in string form
+        scope, directive = directive.split(":")
+        return client.Placement(scope=scope, directive=directive)
+
+    if directive.isdigit():
+        # Planner has given us a machine id (we rely on juju core to
+        # verify its validity.)
+        return client.Placement(scope=MACHINE_SCOPE, directive=directive)
+
+    # Planner has probably given us a container type. Leave it up to
+    # juju core to verify that it is valid.
+    return client.Placement(scope=directive)
diff --git a/tests/unit/test_placement.py b/tests/unit/test_placement.py
new file mode 100644 (file)
index 0000000..793266d
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Test our placement helper
+#
+
+import unittest
+
+from juju import placement
+from juju.client import client
+
+class TestPlacement(unittest.TestCase):
+
+    def test_parse_both_specified(self):
+        res = placement.parse("foo:bar")
+        self.assertEqual(res.scope, "foo")
+        self.assertEqual(res.directive, "bar")
+
+    def test_parse_machine(self):
+        res = placement.parse("22")
+        self.assertEqual(res.scope, "#")
+        self.assertEqual(res.directive, "22")