def validate_config_mapping(config_mapping): if MASTER_NAMESPACE not in config_mapping: msg = "A config mapping requires a %s namespace" raise ConfigError(msg % MASTER_NAMESPACE) master = valid_config(config_mapping.pop(MASTER_NAMESPACE)) nodes = get_nodes_from_master_namespace(master) yield MASTER_NAMESPACE, master for name, content in six.iteritems(config_mapping): context = ConfigContext(name, nodes, master.command_context, name) yield name, valid_named_config(content, config_context=context)
def validator(value, config_context): if config_context.partial: return valid_string(value, config_context) context = command_context.CommandContext( context_object, config_context.command_context) try: value % context return value except (KeyError, ValueError), e: error_msg = "Unknown context variable %s at %s: %s" raise ConfigError(error_msg % (e, config_context.path, value))
def _validate_dependencies(self, job, actions, base_action, current_action=None, stack=None): """Check for circular or misspelled dependencies.""" stack = stack or [] current_action = current_action or base_action stack.append(current_action.name) for dep in current_action.requires: if dep == base_action.name and len(stack) > 0: msg = 'Circular dependency in job.%s: %s' raise ConfigError(msg % (job['name'], ' -> '.join(stack))) if dep not in actions: raise ConfigError('Action jobs.%s.%s has a dependency "%s"' ' that is not in the same job!' % (job['name'], current_action.name, dep)) self._validate_dependencies(job, actions, base_action, actions[dep], stack) stack.pop()
def test_update_config_failure(self): autospec_method(self.controller.strip_header) striped_content = self.controller.strip_header.return_value name, config_hash = None, mock.Mock() self.manager.get_hash.return_value = config_hash self.manager.write_config.side_effect = ConfigError("It broke") error = self.controller.update_config( name, striped_content, config_hash, ) assert_equal(error, "It broke") self.manager.write_config.assert_called_with(name, striped_content) assert not self.mcp.reconfigure.call_count
def schedule_config_from_legacy_dict(schedule, config_context): """Support old style schedules as dicts.""" if 'interval' in schedule: config = ConfigGenericSchedule('interval', schedule['interval'], None) return valid_interval_scheduler(config, config_context) if 'start_time' in schedule or 'days' in schedule: start_time = schedule.get('start_time', '00:00:00') days = schedule.get('days', '') scheduler_config = '%s %s' % (start_time, days) config = ConfigGenericSchedule('daily', scheduler_config, None) return valid_daily_scheduler(config, config_context) path = config_context.path raise ConfigError("Unknown scheduler at %s: %s" % (path, schedule))
def test_update_config_failure(self): name, content, old_content, config_hash = None, mock.Mock(), mock.Mock( ), mock.Mock() self.manager.get_hash.return_value = config_hash self.manager.write_config.side_effect = [ConfigError("It broke"), None] self.controller.read_config = mock.Mock( return_value={'config': old_content}) error = self.controller.update_config( name, content, config_hash, ) assert error == "It broke" self.manager.write_config.call_args_list = [(name, content), (name, old_content)] assert self.mcp.reconfigure.call_count == 1
def validate(self, in_dict, config_context): if self.optional and in_dict is None: return None if in_dict is None: raise ConfigError("A %s is required." % self.type_name) shortcut_value = self.do_shortcut(in_dict) if shortcut_value: return shortcut_value config_context = self.build_context(in_dict, config_context) in_dict = self.cast(in_dict, config_context) self.validate_required_keys(in_dict) self.validate_extra_keys(in_dict) return self.build_config(in_dict, config_context)
def __setitem__(self, key, value): if key in self: raise ConfigError(self.fmt_string % key) super().__setitem__(key, value)
def post_validation(self, config, config_context): buffer_size = config.get('buffer_size') if buffer_size and buffer_size < 1: path = config_context.path raise ConfigError("%s buffer_size must be >= 1." % path)
def valid_cleanup_action_name(value, config_context): if value != CLEANUP_ACTION_NAME: msg = "Cleanup actions cannot have custom names %s.%s" raise ConfigError(msg % (config_context.path, value)) return CLEANUP_ACTION_NAME
def valid_trigger_downstreams(trigger_downstreams, config_context): if isinstance(trigger_downstreams, (type(None), bool, dict)): return trigger_downstreams raise ConfigError('must be None, bool or dict')
def valid_action_name(value, config_context): valid_identifier(value, config_context) if value == CLEANUP_ACTION_NAME: error_msg = "Invalid action name %s at %s" raise ConfigError(error_msg % (value, config_context.path)) return value
def post_validation(self, valid_input, config_context): if config_context.partial: return if valid_input['agent'] and 'SSH_AUTH_SOCK' not in os.environ: raise ConfigError("No SSH Agent available ($SSH_AUTH_SOCK)")
def valid_node_name(value, config_context): valid_identifier(value, config_context) if not config_context.partial and value not in config_context.nodes: msg = "Unknown node name %s at %s" raise ConfigError(msg % (value, config_context.path)) return value
def valid_day(day): if day not in CONVERT_DAYS_INT: raise ConfigError("Unknown day %s at %s" % (day, config_context.path)) return CONVERT_DAYS_INT[day]
def f(value, config_context): if not validator(value): raise ConfigError(error_fmt % (config_context.path, value)) return value
def __setitem__(self, key, value): if key in self: raise ConfigError(self.fmt_string % key) super(UniqueNameDict, self).__setitem__(key, value)
def build_enum_validator(enum): enum = set(enum) msg = 'Value at %%s is not in %s: %%s.' % str(enum) return build_type_validator(enum.__contains__, msg) def valid_time(value, config_context): valid_string(value, config_context) for format in ['%H:%M', '%H:%M:%S']: try: return datetime.datetime.strptime(value, format) except ValueError, exc: pass msg = 'Value at %s is not a valid time: %s' raise ConfigError(msg % (config_context.path, exc)) # Translations from possible configuration units to the argument to # datetime.timedelta TIME_INTERVAL_UNITS = dicts.invert_dict_list({ 'days': ['d', 'day', 'days'], 'hours': ['h', 'hr', 'hrs', 'hour', 'hours'], 'minutes': ['m', 'min', 'mins', 'minute', 'minutes'], 'seconds': ['s', 'sec', 'secs', 'second', 'seconds'] }) TIME_INTERVAL_RE = re.compile(r"^\s*(?P<value>\d+)\s*(?P<units>[a-zA-Z]+)\s*$") def valid_time_delta(value, config_context): error_msg = "Value at %s is not a valid time delta: %s"
def from_string(content): try: return yaml.load(content) except yaml.error.YAMLError, e: raise ConfigError("Invalid config format: %s" % str(e))