def test_override_builder_cfg(self): put_req = api.PutRequestMessage( bucket='chromium/try', parameters_json=json.dumps( dict(swarming=dict( override_builder_cfg=dict(dimensions=['a:b']), ), ))) build_req = api.put_request_message_to_build_request(put_req) builder_cfg = project_config_pb2.Builder() build_req.override_builder_cfg(builder_cfg) self.assertEqual(list(builder_cfg.dimensions), ['a:b'])
def test(cfg_text, expected_builder_text): cfg = project_config_pb2.BuildbucketCfg() protobuf.text_format.Merge(cfg_text, cfg) builder = cfg.buckets[0].swarming.builders[0] swarmingcfg.flatten_builder( builder, cfg.buckets[0].swarming.builder_defaults, {m.name: m for m in cfg.builder_mixins}, ) expected = project_config_pb2.Builder() protobuf.text_format.Merge(expected_builder_text, expected) self.assertEqual(builder, expected)
def _override_builder_cfg_func(parameters): """Returns a function that overrides a Builder config. May return None. See creation.BuildRequest.override_builder_cfg. """ swarming_param = parameters.get(_PARAM_SWARMING) or {} overrides_dict = swarming_param.get('override_builder_cfg') if not overrides_dict: return None overrides = project_config_pb2.Builder() protoutil.merge_dict(overrides_dict, overrides) return lambda cfg: flatten_swarmingcfg.merge_builder(cfg, overrides)
def _prepare_builder_config(builder_cfg, swarming_param): """Returns final version of builder config to use for |build|. Expects arguments to be valid. """ # Builders are already flattened in the datastore. result = builder_cfg # Apply overrides in the swarming parameter. override_builder_cfg_data = swarming_param.get('override_builder_cfg', {}) if override_builder_cfg_data: override_builder_cfg = project_config_pb2.Builder() protoutil.merge_dict(override_builder_cfg_data, result) ctx = validation.Context.raise_on_error( exc_type=errors.InvalidInputError, prefix='swarming.override_buider_cfg parameter: ') swarmingcfg_module.merge_builder(result, override_builder_cfg) swarmingcfg_module.validate_builder_cfg(result, [], True, ctx) return result
def validate_build_parameters(builder_name, params): """Raises errors.InvalidInputError if build parameters are invalid.""" params = copy.deepcopy(params) def bad(fmt, *args): raise errors.InvalidInputError(fmt % args) params.pop(BUILDER_PARAMETER) # already validated def assert_object(name, value): if not isinstance(value, dict): bad('%s parameter must be an object' % name) properties = params.pop(PARAM_PROPERTIES, None) if properties is not None: assert_object('properties', properties) if properties.get('buildername', builder_name) != builder_name: bad('inconsistent builder name') swarming = params.pop(PARAM_SWARMING, None) if swarming is not None: assert_object('swarming', swarming) swarming = copy.deepcopy(swarming) canary_template = swarming.pop('canary_template', None) if canary_template not in (True, False, None): bad('swarming.canary_template parameter must true, false or null') override_builder_cfg_data = swarming.pop('override_builder_cfg', None) if override_builder_cfg_data is not None: assert_object('swarming.override_builder_cfg', override_builder_cfg_data) if 'build_numbers' in override_builder_cfg_data: bad('swarming.override_builder_cfg parameter ' 'cannot override build_numbers') override_builder_cfg = project_config_pb2.Builder() try: protoutil.merge_dict(override_builder_cfg_data, override_builder_cfg) except TypeError as ex: bad('swarming.override_builder_cfg parameter: %s', ex) if override_builder_cfg.name: bad('swarming.override_builder_cfg cannot override builder name' ) if override_builder_cfg.mixins: bad('swarming.override_builder_cfg cannot use mixins') ctx = validation.Context.raise_on_error( exc_type=errors.InvalidInputError, prefix='swarming.override_builder_cfg parameter: ') swarmingcfg_module.validate_builder_cfg(override_builder_cfg, [], False, ctx) if swarming: bad('unrecognized keys in swarming param: %r', swarming.keys()) changes = params.pop(PARAM_CHANGES, None) if changes is not None: if not isinstance(changes, list): bad('changes param must be an array') for c in changes: # pragma: no branch if not isinstance(c, dict): bad('changes param must contain only objects') repo_url = c.get('repo_url') if repo_url is not None and not isinstance(repo_url, basestring): bad('change repo_url must be a string') author = c.get('author') if not isinstance(author, dict): bad('change author must be an object') email = author.get('email') if not isinstance(email, basestring): bad('change author email must be a string') if not email: bad('change author email not specified')
def validate_known_build_parameters(params): """Raises errors.InvalidInputError if LUCI build parameters are invalid.""" params = copy.deepcopy(params) ctx = config_validation.Context.raise_on_error( exc_type=errors.InvalidInputError) def bad(fmt, *args): raise errors.InvalidInputError(fmt % args) def assert_object(name, value): if not isinstance(value, dict): bad('%s parameter must be an object' % name) changes = params.get(_PARAM_CHANGES) if changes is not None: if not isinstance(changes, list): bad('changes param must be an array') for c in changes: # pragma: no branch if not isinstance(c, dict): bad('changes param must contain only objects') repo_url = c.get('repo_url') if repo_url is not None and not isinstance(repo_url, basestring): bad('change repo_url must be a string') author = c.get('author') if not isinstance(author, dict): bad('change author must be an object') email = author.get('email') if not isinstance(email, basestring): bad('change author email must be a string') if not email: bad('change author email not specified') swarming = params.get(_PARAM_SWARMING) if swarming is not None: assert_object('swarming', swarming) swarming = copy.deepcopy(swarming) override_builder_cfg_data = swarming.pop('override_builder_cfg', None) if override_builder_cfg_data is not None: assert_object('swarming.override_builder_cfg', override_builder_cfg_data) if 'build_numbers' in override_builder_cfg_data: bad('swarming.override_builder_cfg parameter ' 'cannot override build_numbers') override_builder_cfg = project_config_pb2.Builder() try: protoutil.merge_dict(override_builder_cfg_data, override_builder_cfg) except TypeError as ex: bad('swarming.override_builder_cfg parameter: %s', ex) if override_builder_cfg.name: bad('swarming.override_builder_cfg cannot override builder name' ) if override_builder_cfg.mixins: bad('swarming.override_builder_cfg cannot use mixins') if any( d.startswith('pool:') for d in override_builder_cfg.dimensions): logging.warning('pool is being overridden: %s', override_builder_cfg.dimensions) if 'pool:' in override_builder_cfg.dimensions: bad('swarming.override_builder_cfg cannot remove pool dimension' ) with ctx.prefix('swarming.override_builder_cfg parameter: '): swarmingcfg.validate_builder_cfg(override_builder_cfg, [], False, ctx) if swarming: bad('unrecognized keys in swarming param: %r', swarming.keys()) properties = params.get('properties') if properties: for k, v in sorted(properties.iteritems()): with ctx.prefix('property %r:', k): swarmingcfg.validate_recipe_property(k, v, ctx)