| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import json |
| 5 import re | 6 import re |
| 6 | 7 |
| 7 from proto import project_config_pb2 | 8 from proto import project_config_pb2 |
| 8 | 9 |
| 9 | 10 |
| 10 DIMENSION_KEY_RGX = re.compile(r'^[a-zA-Z\_\-]+$') | 11 DIMENSION_KEY_RGX = re.compile(r'^[a-zA-Z\_\-]+$') |
| 11 | 12 |
| 12 | 13 |
| 13 def validate_tag(tag, ctx): | 14 def validate_tag(tag, ctx): |
| 14 # a valid swarming tag is a string that contains ":" | 15 # a valid swarming tag is a string that contains ":" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 38 'key "%s" does not match pattern "%s"', | 39 'key "%s" does not match pattern "%s"', |
| 39 key, DIMENSION_KEY_RGX.pattern) | 40 key, DIMENSION_KEY_RGX.pattern) |
| 40 if key in known_keys: | 41 if key in known_keys: |
| 41 ctx.error('duplicate key %s', key) | 42 ctx.error('duplicate key %s', key) |
| 42 else: | 43 else: |
| 43 known_keys.add(key) | 44 known_keys.add(key) |
| 44 if not value: | 45 if not value: |
| 45 ctx.error('no value') | 46 ctx.error('no value') |
| 46 | 47 |
| 47 | 48 |
| 48 | |
| 49 def validate_recipe_cfg(recipe, common_recipe, ctx): | 49 def validate_recipe_cfg(recipe, common_recipe, ctx): |
| 50 common_recipe = common_recipe or project_config_pb2.Swarming.Recipe() | 50 common_recipe = common_recipe or project_config_pb2.Swarming.Recipe() |
| 51 if not (recipe.name or common_recipe.name): | 51 if not (recipe.name or common_recipe.name): |
| 52 ctx.error('name unspecified') | 52 ctx.error('name unspecified') |
| 53 if not (recipe.repository or common_recipe.repository): | 53 if not (recipe.repository or common_recipe.repository): |
| 54 ctx.error('repository unspecified') | 54 ctx.error('repository unspecified') |
| 55 validate_recipe_properties(recipe.properties, ctx) | 55 validate_recipe_properties(recipe.properties, recipe.properties_j, ctx) |
| 56 | 56 |
| 57 | 57 |
| 58 def validate_recipe_properties(properties, ctx): | 58 def validate_recipe_properties(properties, properties_j, ctx): |
| 59 keys = set() |
| 60 |
| 61 def validate_key(key): |
| 62 if not key: |
| 63 ctx.error('key not specified') |
| 64 elif key =='buildername': |
| 65 ctx.error( |
| 66 'do not specify buildername property; ' |
| 67 'it is added by swarmbucket automatically') |
| 68 if key in keys: |
| 69 ctx.error('duplicate property "%s"', key) |
| 70 |
| 59 for i, p in enumerate(properties): | 71 for i, p in enumerate(properties): |
| 60 with ctx.prefix('property #%d: ', i + 1): | 72 with ctx.prefix('properties #%d: ', i + 1): |
| 61 if ':' not in p: | 73 if ':' not in p: |
| 62 ctx.error('does not have colon') | 74 ctx.error('does not have colon') |
| 63 else: | 75 else: |
| 64 key, _ = p.split(':', 1) | 76 key, _ = p.split(':', 1) |
| 65 if not key: | 77 validate_key(key) |
| 66 ctx.error('key not specified') | 78 keys.add(key) |
| 67 elif key =='buildername': | 79 |
| 68 ctx.error( | 80 for i, p in enumerate(properties_j): |
| 69 'do not specify buildername property; ' | 81 with ctx.prefix('properties_j #%d: ', i + 1): |
| 70 'it is added by swarmbucket automatically') | 82 if ':' not in p: |
| 83 ctx.error('does not have colon') |
| 84 else: |
| 85 key, value = p.split(':', 1) |
| 86 validate_key(key) |
| 87 keys.add(key) |
| 88 try: |
| 89 json.loads(value) |
| 90 except ValueError as ex: |
| 91 ctx.error(ex) |
| 92 |
| 71 | 93 |
| 72 def validate_builder_cfg( | 94 def validate_builder_cfg( |
| 73 builder, ctx, bucket_has_pool_dim=False, common_recipe=None): | 95 builder, ctx, bucket_has_pool_dim=False, common_recipe=None): |
| 74 if not builder.name: | 96 if not builder.name: |
| 75 ctx.error('name unspecified') | 97 ctx.error('name unspecified') |
| 76 | 98 |
| 77 for i, t in enumerate(builder.swarming_tags): | 99 for i, t in enumerate(builder.swarming_tags): |
| 78 with ctx.prefix('tag #%d: ', i + 1): | 100 with ctx.prefix('tag #%d: ', i + 1): |
| 79 validate_tag(t, ctx) | 101 validate_tag(t, ctx) |
| 80 | 102 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 100 for i, t in enumerate(swarming.common_swarming_tags): | 122 for i, t in enumerate(swarming.common_swarming_tags): |
| 101 with ctx.prefix('common tag #%d: ', i + 1): | 123 with ctx.prefix('common tag #%d: ', i + 1): |
| 102 validate_tag(t, ctx) | 124 validate_tag(t, ctx) |
| 103 | 125 |
| 104 validate_dimensions('common dimension', swarming.common_dimensions, ctx) | 126 validate_dimensions('common dimension', swarming.common_dimensions, ctx) |
| 105 has_pool_dim = has_pool_dimension(swarming.common_dimensions) | 127 has_pool_dim = has_pool_dimension(swarming.common_dimensions) |
| 106 common_recipe = None | 128 common_recipe = None |
| 107 if swarming.HasField('common_recipe'): | 129 if swarming.HasField('common_recipe'): |
| 108 common_recipe = swarming.common_recipe | 130 common_recipe = swarming.common_recipe |
| 109 with ctx.prefix('common_recipe: '): | 131 with ctx.prefix('common_recipe: '): |
| 110 validate_recipe_properties(swarming.common_recipe.properties, ctx) | 132 validate_recipe_properties( |
| 133 swarming.common_recipe.properties, |
| 134 swarming.common_recipe.properties_j, ctx) |
| 111 | 135 |
| 112 for i, b in enumerate(swarming.builders): | 136 for i, b in enumerate(swarming.builders): |
| 113 with ctx.prefix('builder %s: ' % (b.name or '#%s' % (i + 1))): | 137 with ctx.prefix('builder %s: ' % (b.name or '#%s' % (i + 1))): |
| 114 validate_builder_cfg( | 138 validate_builder_cfg( |
| 115 b, ctx, bucket_has_pool_dim=has_pool_dim, | 139 b, ctx, bucket_has_pool_dim=has_pool_dim, |
| 116 common_recipe=common_recipe) | 140 common_recipe=common_recipe) |
| 117 | 141 |
| 118 def has_pool_dimension(dimensions): | 142 def has_pool_dimension(dimensions): |
| 119 return any(d.startswith('pool:') for d in dimensions) | 143 return any(d.startswith('pool:') for d in dimensions) |
| OLD | NEW |