998862d02508499dd28d0f20983e1f5858498213
[osm/N2VC.git] / modules / libjuju / 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 # https://github.com/juju/juju/blob/master/constraints/constraints.go#L666
25 FACTORS = {
26 "M": 1,
27 "G": 1024,
28 "T": 1024 * 1024,
29 "P": 1024 * 1024 * 1024
30 }
31
32 SNAKE1 = re.compile(r'(.)([A-Z][a-z]+)')
33 SNAKE2 = re.compile('([a-z0-9])([A-Z])')
34
35
36 def parse(constraints):
37 """
38 Constraints must be expressed as a string containing only spaces
39 and key value pairs joined by an '='.
40
41 """
42 if not constraints:
43 return None
44
45 if type(constraints) is dict:
46 # Fowards compatibilty: already parsed
47 return constraints
48
49 constraints = {
50 normalize_key(k): normalize_value(v) for k, v in [
51 s.split("=") for s in constraints.split(" ")]}
52
53 return constraints
54
55
56 def normalize_key(key):
57 key = key.strip()
58
59 key = key.replace("-", "_") # Our _client lib wants "_" in place of "-"
60
61 # Convert camelCase to snake_case
62 key = SNAKE1.sub(r'\1_\2', key)
63 key = SNAKE2.sub(r'\1_\2', key).lower()
64
65 return key
66
67
68 def normalize_value(value):
69 value = value.strip()
70
71 if MEM.match(value):
72 # Translate aliases to Megabytes. e.g. 1G = 10240
73 return int(value[:-1]) * FACTORS[value[-1:]]
74
75 if "," in value:
76 # Handle csv strings.
77 values = value.split(",")
78 values = [normalize_value(v) for v in values]
79 return values
80
81 if value.isdigit():
82 return int(value)
83
84 return value