97529e46ad5accd7dc5d6d45e3d7e01d9347e639
[osm/N2VC.git] / juju / constraints.py
1 #
2 # Module that parses constraints
3 #
4 # The current version of juju core expects the client to take
5 # constraints given in the form "mem=10G foo=bar" and parse them into
6 # json that looks like {"mem": 10240, "foo": "bar"}. This module helps us
7 # accomplish that task.
8 #
9 # We do not attempt to duplicate the checking done in
10 # client/_client.py:Value here. That class will verify that the
11 # constraints keys are valid, and that we can successfully dump the
12 # constraints dict to json.
13 #
14 # Once https://bugs.launchpad.net/juju/+bug/1645402 is addressed, this
15 # module should be deprecated.
16 #
17
18 import re
19
20 # Matches on a string specifying memory size
21 MEM = re.compile('^[1-9][0-9]*[MGTP]$')
22
23 # Multiplication factors to get Megabytes
24 FACTORS = {
25 "M": 1,
26 "G": 1024,
27 "T": 1024 * 1024,
28 "P": 1024 * 1024 * 1024
29 }
30
31 SNAKE1 = re.compile(r'(.)([A-Z][a-z]+)')
32 SNAKE2 = re.compile('([a-z0-9])([A-Z])')
33
34 def parse(constraints):
35 """
36 Constraints must be expressed as a string containing only spaces
37 and key value pairs joined by an '='.
38
39 """
40 if constraints is None:
41 return None
42
43 if constraints == "":
44 return None
45
46 if type(constraints) is dict:
47 # Fowards compatibilty: already parsed
48 return constraints
49
50 constraints = {
51 normalize_key(k): normalize_value(v) for k, v in [
52 s.split("=") for s in constraints.split(" ")]}
53
54 return constraints
55
56
57 def normalize_key(key):
58 key = key.strip()
59
60 key = key.replace("-", "_") # Our _client lib wants "_" in place of "-"
61
62 # Convert camelCase to snake_case
63 key = SNAKE1.sub(r'\1_\2', key)
64 key = SNAKE2.sub(r'\1_\2', key).lower()
65
66 return key
67
68
69 def normalize_value(value):
70 value = value.strip()
71
72 if MEM.match(value):
73 # Translate aliases to Megabytes. e.g. 1G = 10240
74 return int(value[:-1]) * FACTORS[value[-1:]]
75
76 if "," in value:
77 # Handle csv strings.
78 values = value.split(",")
79 values = [normalize_value(v) for v in values]
80 return values
81
82 if value.isdigit():
83 return int(value)
84
85 return value