Repository: juju/python-libjuju

Issue:
Unable to set allocate-public-ip constraint
### Summary

When using `model.deploy()` to deploy an application, including the `allocate-public-ip=true` constraint fails with the following error:

```
Traceback (most recent call last):
  File "test_integration.py", line 60, in test_deploy_cluster
    app = await ops_test.model.deploy(
  File "/.tox_env/lib/python3.8/site-packages/juju/model.py", line 1662, in deploy
    return await self._deploy(
  File "/.tox_env/lib/python3.8/site-packages/juju/model.py", line 1897, in _deploy
    app = client.ApplicationDeploy(
  File "/.tox_env/lib/python3.8/site-packages/juju/client/_definitions.py", line 1806, in __init__
    constraints_ = Value.from_json(constraints) if constraints else None
  File "/.tox_env/lib/python3.8/site-packages/juju/client/facade.py", line 640, in from_json
    return cls(**d)
  File "/.tox_env/lib/python3.8/site-packages/juju/client/_definitions.py", line 27110, in __init__
    raise Exception("Expected allocate_public_ip_ to be a bool, received: {}".format(type(allocate_public_ip_)))
Exception: Expected allocate_public_ip_ to be a bool, received: <class 'str'>
```

I believe the issue occurs due to https://github.com/juju/python-libjuju/blob/master/juju/constraints.py#L75-L85 not doing any handling for boolean values.

### Proposed Fix

Extend `normalize_value` with something along the lines of:

```python
if value in ['true', 'True']:
    return True
if value in ['false', 'False']:
    return False
```

I doubt this is going to break any other constraints.

Discussion:

Patch:
diff --git a/juju/constraints.py b/juju/constraints.py
index 42d26c2..3191f28 100644
--- a/juju/constraints.py
+++ b/juju/constraints.py
@@ -82,6 +82,11 @@ def normalize_value(value):
     if value.isdigit():
         return int(value)
 
+    if value.lower() == 'true':
+        return True
+    if value.lower() == 'false':
+        return False
+
     return value
 
 


Test patch:
diff --git a/tests/unit/test_constraints.py b/tests/unit/test_constraints.py
index 4d5e26c..f76f516 100644
--- a/tests/unit/test_constraints.py
+++ b/tests/unit/test_constraints.py
@@ -33,6 +33,10 @@ class TestConstraints(unittest.TestCase):
         self.assertEqual(_("10M"), 10)
         self.assertEqual(_("10"), 10)
         self.assertEqual(_("foo,bar"), "foo,bar")
+        self.assertEqual(_("false"), False)
+        self.assertEqual(_("true"), True)
+        self.assertEqual(_("FALSE"), False)
+        self.assertEqual(_("TRUE"), True)
 
     def test_normalize_list_val(self):
         _ = constraints.normalize_list_value