def test_collect_all_errors_from_specifications(self): assert_report_item_list_equal( validate.ValidatorAll([ validate.NamesIn(["x", "y"]), validate.MutuallyExclusive(["x", "y"]), validate.ValuePositiveInteger("x"), validate.ValueIn("y", ["a", "b"]), ]).validate({ "x": "abcd", "y": "defg", "z": "hijk", }), [ fixture.error( report_codes.INVALID_OPTIONS, option_names=["z"], option_type=None, allowed=["x", "y"], allowed_patterns=[], ), fixture.error(report_codes.MUTUALLY_EXCLUSIVE_OPTIONS, option_names=["x", "y"], option_type=None), fixture.error( report_codes.INVALID_OPTION_VALUE, option_value="abcd", option_name="x", allowed_values="a positive integer", cannot_be_empty=False, forbidden_characters=None, ), fixture.error( report_codes.INVALID_OPTION_VALUE, option_value="defg", option_name="y", allowed_values=["a", "b"], cannot_be_empty=False, forbidden_characters=None, ), ])
def test_empty_report_on_valid_option(self): assert_report_item_list_equal( validate.ValuePositiveInteger("key").validate({"key": "10"}), [])
def _validate_generic_container_options_update(container_el, options, force_options): validators_optional_options = [ validate.ValueNonnegativeInteger("masters"), validate.ValueNonnegativeInteger("promoted-max"), validate.ValuePositiveInteger("replicas"), validate.ValuePositiveInteger("replicas-per-host"), ] for val in validators_optional_options: val.empty_string_valid = True validators = [ validate.NamesIn( # allow to remove options even if they are not allowed GENERIC_CONTAINER_OPTIONS | _options_to_remove(options), option_type="container", **validate.set_warning(report_codes.FORCE_OPTIONS, force_options), ), # image is a mandatory attribute and cannot be removed validate.ValueNotEmpty("image", "image name"), ] + validators_optional_options # CIB does not allow both to be set. Deleting both is not a problem, # though. Deleting one while setting another also works and is further # checked bellow. if not (options.get("masters", "") == "" or options.get("promoted-max", "") == ""): validators.append( validate.MutuallyExclusive( ["masters", "promoted-max"], option_type="container", )) deprecation_reports = [] if options.get("masters"): # If the user wants to delete the masters option, do not report it is # deprecated. They may be removing it because they just found out it is # deprecated. deprecation_reports.append( ReportItem.warning( reports.messages.DeprecatedOption( "masters", ["promoted-max"], "container", ))) # Do not allow to set masters if promoted-max is set unless promoted-max is # going to be removed now. Do the same check also the other way around. CIB # only allows one of them to be set. if (options.get("masters") and container_el.get("promoted-max") and options.get("promoted-max") != ""): deprecation_reports.append( ReportItem.error( reports.messages.PrerequisiteOptionMustNotBeSet( "masters", "promoted-max", "container", "container"))) if (options.get("promoted-max") and container_el.get("masters") and options.get("masters") != ""): deprecation_reports.append( ReportItem.error( reports.messages.PrerequisiteOptionMustNotBeSet( "promoted-max", "masters", "container", "container"))) return (validate.ValidatorAll(validators).validate(options) + deprecation_reports)
def _validate_date_inrange_expr( expr: DateInRangeExpr, ) -> reports.ReportItemList: # TODO This is taken from the CIB schema. There is an ongoing # discussion that the schema doesn't match Pacemaker Explained. Based # on the result of the discussion, this might need to be updated. duration_parts = { "hours", "monthdays", "weekdays", "yearsdays", "months", "weeks", "years", "weekyears", "moon", } start_date, end_date = None, None report_list = [] if expr.date_start is not None: try: start_date = dateutil_parser.isoparse(expr.date_start) except ValueError: report_list.append( reports.item.ReportItem.error( message=reports.messages.InvalidOptionValue( "date", expr.date_start, "ISO 8601 date"), )) if expr.date_end is not None: try: end_date = dateutil_parser.isoparse(expr.date_end) except ValueError: report_list.append( reports.item.ReportItem.error( message=reports.messages.InvalidOptionValue( "date", expr.date_end, "ISO 8601 date"), )) if (start_date is not None and end_date is not None and start_date >= end_date): report_list.append( reports.item.ReportItem.error( message=reports.messages. RuleExpressionSinceGreaterThanUntil( expr.date_start, # If end_date is not None, then expr.date_end is not # None, but mypy does not see it. cast(str, expr.date_end), ), )) if expr.duration_parts: duplicate_keys = { key for key, count in Counter( [pair[0] for pair in expr.duration_parts]).items() if count > 1 } validator_list: List[validate.ValidatorInterface] = [ validate.ValuePositiveInteger(name) for name in sorted(duration_parts) ] validator_list.append( validate.NamesIn(duration_parts, option_type="duration")) report_list += validate.ValidatorAll(validator_list).validate( dict(expr.duration_parts)) if duplicate_keys: report_list.append( reports.item.ReportItem.error( message=reports. messages.RuleExpressionOptionsDuplication( sorted(duplicate_keys)), )) return report_list