Skip to content

Commit e6e204c

Browse files
author
smothiki
committed
feat(workflow): add support for floating point cpus and milli cpu units
1 parent 934d84f commit e6e204c

4 files changed

Lines changed: 17 additions & 19 deletions

File tree

client/cmd/limits.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package cmd
33
import (
44
"fmt"
55
"regexp"
6-
"strconv"
76

87
"github.com/deis/pkg/prettyprint"
98

@@ -43,7 +42,7 @@ func LimitsList(appID string) error {
4342
cpuMap := make(map[string]string)
4443

4544
for key, value := range config.CPU {
46-
cpuMap[key] = strconv.Itoa(int(value.(float64)))
45+
cpuMap[key] = value.(string)
4746
}
4847

4948
fmt.Print(prettyprint.PrettyTabs(cpuMap, 5))
@@ -145,7 +144,7 @@ func parseLimits(limits []string) map[string]interface{} {
145144
}
146145

147146
func parseLimit(limit string) (string, string, error) {
148-
regex := regexp.MustCompile("^([A-z]+)=([0-9]+[bkmgBKMG]{1,2}|[0-9]{1,4})$")
147+
regex := regexp.MustCompile("^([A-z]+)=([0-9]+[bkmgBKMG]{1,2}|[0-9.]{1,5}|[0-9.]{1,5}[m]{0,1})$")
149148

150149
if !regex.MatchString(limit) {
151150
return "", "", fmt.Errorf(`%s doesn't fit format type=#unit or type=#

rootfs/api/serializers.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
PROCTYPE_MATCH = re.compile(r'^(?P<type>[a-z]+)')
1515
MEMLIMIT_MATCH = re.compile(r'^(?P<mem>[0-9]+(MB|KB|GB|[BKMG]))$', re.IGNORECASE)
16-
CPUSHARE_MATCH = re.compile(r'^(?P<cpu>[0-9]+)$')
16+
CPUSHARE_MATCH = re.compile(r'^(?P<cpu>[0-9.]+[m]{0,1})$')
1717
TAGKEY_MATCH = re.compile(r'^[a-z]+$')
1818
TAGVAL_MATCH = re.compile(r'^\w+$')
1919
CONFIGKEY_MATCH = re.compile(r'^[a-z_]+[a-z0-9_]*$', re.IGNORECASE)
@@ -133,7 +133,7 @@ class ConfigSerializer(serializers.ModelSerializer):
133133
owner = serializers.ReadOnlyField(source='owner.username')
134134
values = JSONFieldSerializer(required=False, binary=True)
135135
memory = JSONFieldSerializer(required=False, binary=True)
136-
cpu = JSONFieldSerializer(required=False, binary=True, type='int')
136+
cpu = JSONFieldSerializer(required=False, binary=True)
137137
tags = JSONFieldSerializer(required=False, binary=True)
138138
created = serializers.DateTimeField(read_only=True)
139139
updated = serializers.DateTimeField(read_only=True)
@@ -175,16 +175,16 @@ def validate_cpu(self, data):
175175

176176
shares = re.match(CPUSHARE_MATCH, str(value))
177177
if not shares:
178-
raise serializers.ValidationError("CPU shares must be an integer")
178+
raise serializers.ValidationError("CPU shares must be a numeric value")
179179

180180
for share in shares.groupdict().values():
181181
try:
182-
i = int(share)
182+
if share[-1] == "m":
183+
float(share[:-1])
184+
else:
185+
float(share)
183186
except ValueError:
184-
raise serializers.ValidationError("CPU shares must be an integer")
185-
186-
if i > 1024 or i < 0:
187-
raise serializers.ValidationError("CPU shares must be between 0 and 1024")
187+
raise serializers.ValidationError("CPU units must be a numeric value")
188188

189189
return data
190190

rootfs/api/tests/test_config.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def test_response_data_types_converted(self):
162162
'app': 'test',
163163
'values': {'PORT': '5000'},
164164
'memory': {},
165-
'cpu': {'web': 1024},
165+
'cpu': {'web': "1024"},
166166
'tags': {}
167167
}
168168
self.assertDictContainsSubset(expected, response.data)
@@ -171,7 +171,7 @@ def test_response_data_types_converted(self):
171171
response = self.client.post(url, json.dumps(body), content_type='application/json',
172172
HTTP_AUTHORIZATION='token {}'.format(self.token))
173173
self.assertEqual(response.status_code, 400)
174-
self.assertIn('CPU shares must be an integer', response.data['cpu'])
174+
self.assertIn('CPU shares must be a numeric value', response.data['cpu'])
175175

176176
@mock.patch('requests.post', mock_status_ok)
177177
def test_config_set_same_key(self):
@@ -409,7 +409,7 @@ def test_limit_cpu(self):
409409
self.assertIn('cpu', response.data)
410410
cpu = response.data['cpu']
411411
self.assertIn('web', cpu)
412-
self.assertEqual(cpu['web'], 1024)
412+
self.assertEqual(cpu['web'], '1024')
413413
# set an additional value
414414
body = {'cpu': json.dumps({'worker': '512'})}
415415
response = self.client.post(url, json.dumps(body), content_type='application/json',
@@ -419,19 +419,19 @@ def test_limit_cpu(self):
419419
self.assertNotEqual(limit1['uuid'], limit2['uuid'])
420420
cpu = response.data['cpu']
421421
self.assertIn('worker', cpu)
422-
self.assertEqual(cpu['worker'], 512)
422+
self.assertEqual(cpu['worker'], '512')
423423
self.assertIn('web', cpu)
424-
self.assertEqual(cpu['web'], 1024)
424+
self.assertEqual(cpu['web'], '1024')
425425
# read the limit again
426426
response = self.client.get(url, HTTP_AUTHORIZATION='token {}'.format(self.token))
427427
self.assertEqual(response.status_code, 200)
428428
limit3 = response.data
429429
self.assertEqual(limit2, limit3)
430430
cpu = response.data['cpu']
431431
self.assertIn('worker', cpu)
432-
self.assertEqual(cpu['worker'], 512)
432+
self.assertEqual(cpu['worker'], '512')
433433
self.assertIn('web', cpu)
434-
self.assertEqual(cpu['web'], 1024)
434+
self.assertEqual(cpu['web'], '1024')
435435
# unset a value
436436
body = {'memory': json.dumps({'worker': None})}
437437
response = self.client.post(url, json.dumps(body), content_type='application/json',

rootfs/scheduler/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,6 @@ def _create_rc(self, name, image, command, **kwargs):
639639
containers[0]["resources"]["limits"]["memory"] = mem
640640

641641
if cpu:
642-
cpu = float(cpu)/1024
643642
containers[0]["resources"]["limits"]["cpu"] = cpu
644643

645644
# add in healtchecks

0 commit comments

Comments
 (0)