def test_value_comparison_with_type(self): dto = CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "attribute": "foo", "operation": "gt", "type": "version", "value": "1.2.3", }, None, None, [], "foo gt version 1.2.3", ), ], "foo gt version 1.2.3", ) output = dedent( """\ Rule: (id:my-id) Expression: foo gt version 1.2.3 (id:my-id-expr) """ ) self.assert_lines(dto, output)
def fixture_dto(nvtype, in_effect): return CibNvsetDto( f"id-{in_effect}", nvtype, {"score": "150"}, CibRuleExpressionDto( f"id-{in_effect}-rule", CibRuleExpressionType.RULE, in_effect, {"boolean-op": "or"}, None, None, [ CibRuleExpressionDto( f"id-{in_effect}-rule-op", CibRuleExpressionType.OP_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"name": "monitor"}, None, None, [], "op monitor", ), ], "op monitor", ), [CibNvpairDto(f"id-{in_effect}-pair1", "name1", "value1")], )
def test_inrange_end(self): dto = CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"operation": "in_range", "end": "2014-07-26"}, None, None, [], "date in_range to 2014-07-26", ), ], "date in_range to 2014-07-26", ) output = dedent( """\ Rule: (id:rule) Expression: date in_range to 2014-07-26 (id:rule-expr) """ ) self.assert_lines(dto, output)
def test_defined(self): xml = etree.fromstring(""" <rule id="my-id"> <expression id="my-id-expr" attribute="pingd" operation="defined" /> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "attribute": "pingd", "operation": "defined" }, None, None, [], "defined pingd", ), ], "defined pingd", ), )
def test_interval(self): xml = etree.fromstring(""" <rule id="my-id"> <op_expression id="my-id-op" name="start" interval="2min" /> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-op", CibRuleExpressionType.OP_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "name": "start", "interval": "2min" }, None, None, [], "op start interval=2min", ), ], "op start interval=2min", ), )
def test_datespec(self): dto = CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"operation": "date_spec"}, CibRuleDateCommonDto( "rule-expr-datespec", {"hours": "1-14", "monthdays": "20-30", "months": "1"}, ), None, [], "date-spec hours=1-14 monthdays=20-30 months=1", ), ], "date-spec hours=1-14 monthdays=20-30 months=1", ) output = dedent( """\ Rule: (id:rule) Expression: (id:rule-expr) Date Spec: hours=1-14 monthdays=20-30 months=1 (id:rule-expr-datespec) """ ) self.assert_lines(dto, output)
def fixture_dto(expired): return CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, expired, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "attribute": "pingd", "operation": "defined" }, None, None, [], "defined pingd", ), ], "defined pingd", )
def test_interval(self): dto = CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-op", CibRuleExpressionType.OP_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"name": "start", "interval": "2min"}, None, None, [], "op start interval=2min", ), ], "op start interval=2min", ) output = dedent( """\ Rule: (id:my-id) Expression: op start interval=2min (id:my-id-op) """ ) self.assert_lines(dto, output)
def test_value_comparison(self): dto = CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "attribute": "my-attr", "operation": "eq", "value": "my value", }, None, None, [], "my-attr eq 'my value'", ), ], "my-attr eq 'my value'", ) output = dedent( """\ Rule: (id:my-id) Expression: my-attr eq 'my value' (id:my-id-expr) """ ) self.assert_lines(dto, output)
def test_inrange_end(self): xml = etree.fromstring(""" <rule id="rule"> <date_expression id="rule-expr" operation="in_range" end="2014-07-26" /> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "operation": "in_range", "end": "2014-07-26" }, None, None, [], "date in_range to 2014-07-26", ), ], "date in_range to 2014-07-26", ), )
def test_inrange_start_duration(self): dto = CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "operation": "in_range", "start": "2014-06-26", }, None, CibRuleDateCommonDto("rule-expr-duration", {"years": "1"}), [], "date in_range 2014-06-26 to duration years=1", ), ], "date in_range 2014-06-26 to duration years=1", ) output = dedent( """\ Rule: (id:rule) Expression: date in_range 2014-06-26 to duration (id:rule-expr) Duration: years=1 (id:rule-expr-duration) """ ) self.assert_lines(dto, output)
def test_success(self): dto = CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.RSC_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"class": "ocf", "provider": "pacemaker", "type": "Dummy"}, None, None, [], "resource ocf:pacemaker:Dummy", ), ], "resource ocf:pacemaker:Dummy", ) output = dedent( """\ Rule: (id:my-id) Expression: resource ocf:pacemaker:Dummy (id:my-id-expr) """ ) self.assert_lines(dto, output)
def test_minimal(self): xml = etree.fromstring(""" <rule id="my-id"> <op_expression id="my-id-op" name="start" /> </rule> """) self.assertEqual( rule_element_to_dto(xml), CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, False, {}, None, None, [ CibRuleExpressionDto( "my-id-op", CibRuleExpressionType.OP_EXPRESSION, False, {"name": "start"}, None, None, [], "op start", ), ], "op start", ), )
def fixture_expired_dto(expired): return CibNvsetDto( "my-id", CibNvsetType.META, {}, CibRuleExpressionDto( "my-id-rule", CibRuleExpressionType.RULE, expired, {"boolean-op": "and"}, None, None, [ CibRuleExpressionDto( "my-id-rule-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"operation": "defined", "attribute": "attr1",}, None, None, [], "defined attr1", ), ], "defined attr1", ), [CibNvpairDto("my-id-pair1", "name1", "value1")], )
def test_lt(self): xml = etree.fromstring(""" <rule id="rule"> <date_expression id="rule-expr" operation="lt" end="2014-06-26" /> </rule> """) self.assertEqual( rule_element_to_dto(xml), CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, False, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, False, { "operation": "lt", "end": "2014-06-26" }, None, None, [], "date lt 2014-06-26", ), ], "date lt 2014-06-26", ), )
def test_minimal(self): dto = CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, False, {}, None, None, [ CibRuleExpressionDto( "my-id-op", CibRuleExpressionType.OP_EXPRESSION, False, {"name": "start"}, None, None, [], "op start", ), ], "op start", ) output = dedent("""\ Rule: (id:my-id) Expression: op start (id:my-id-op) """) self.assert_lines(dto, output)
def test_inrange(self): dto = CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, False, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, False, { "operation": "in_range", "start": "2014-06-26", "end": "2014-07-26", }, None, None, [], "date in_range 2014-06-26 to 2014-07-26", ), ], "date in_range 2014-06-26 to 2014-07-26", ) output = dedent("""\ Rule: (id:rule) Expression: date in_range 2014-06-26 to 2014-07-26 (id:rule-expr) """) self.assert_lines(dto, output)
def test_simple(self): dto = CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"operation": "gt", "start": "2014-06-26"}, None, None, [], "date gt 2014-06-26", ), ], "date gt 2014-06-26", ) output = dedent( """\ Rule: (id:rule) Expression: date gt 2014-06-26 (id:rule-expr) """ ) self.assert_lines(dto, output)
def test_defined(self): dto = CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"attribute": "pingd", "operation": "defined"}, None, None, [], "defined pingd", ), ], "defined pingd", ) output = dedent( """\ Rule: (id:my-id) Expression: defined pingd (id:my-id-expr) """ ) self.assert_lines(dto, output)
def test_expired(self): for tag, nvtype in self.tag_type: with self.subTest(tag=tag, nvset_type=nvtype): xml = etree.fromstring( f""" <{tag} id="my-id" score="150"> <rule id="my-id-rule" boolean-op="and"> <rsc_expression id="my-id-rule-rsc-ocf-pacemaker-Dummy" class="ocf" provider="pacemaker" type="Dummy" /> </rule> <nvpair id="my-id-pair1" name="name1" value="value1" /> </{tag}> """ ) self.assertEqual( nvpair_multi.nvset_element_to_dto( xml, get_in_effect_eval( {"my-id-rule": CibRuleInEffectStatus.EXPIRED} ), ), CibNvsetDto( "my-id", nvtype, {"score": "150"}, CibRuleExpressionDto( "my-id-rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.EXPIRED, {"boolean-op": "and"}, None, None, [ CibRuleExpressionDto( "my-id-rule-rsc-ocf-pacemaker-Dummy", CibRuleExpressionType.RSC_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "class": "ocf", "provider": "pacemaker", "type": "Dummy", }, None, None, [], "resource ocf:pacemaker:Dummy", ), ], "resource ocf:pacemaker:Dummy", ), [CibNvpairDto("my-id-pair1", "name1", "value1")], ), )
def test_success(self): test_data = [ # ((class, provider, type), output) ((None, None, None), "::"), (("ocf", None, None), "ocf::"), ((None, "pacemaker", None), ":pacemaker:"), ((None, None, "Dummy"), "::Dummy"), (("ocf", "pacemaker", None), "ocf:pacemaker:"), (("ocf", None, "Dummy"), "ocf::Dummy"), ((None, "pacemaker", "Dummy"), ":pacemaker:Dummy"), (("ocf", "pacemaker", "Dummy"), "ocf:pacemaker:Dummy"), ] for in_data, out_data in test_data: with self.subTest(in_data=in_data): attrs = {} if in_data[0] is not None: attrs["class"] = in_data[0] if in_data[1] is not None: attrs["provider"] = in_data[1] if in_data[2] is not None: attrs["type"] = in_data[2] attrs_str = " ".join( [f"{name}='{value}'" for name, value in attrs.items()]) xml = etree.fromstring(f""" <rule id="my-id"> <rsc_expression id="my-id-expr" {attrs_str}/> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.RSC_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, attrs, None, None, [], f"resource {out_data}", ), ], f"resource {out_data}", ), )
def _rule_to_dto(rule_el: Element) -> CibRuleExpressionDto: children_dto_list = [ _tag_to_export[child.tag](child) # The xpath method has a complicated return value, but we know our xpath # expression only returns elements. for child in cast(Element, cast(_Element, rule_el).xpath(_xpath_for_export)) ] # "and" is a documented pacemaker default # https://clusterlabs.org/pacemaker/doc/en-US/Pacemaker/2.0/html-single/Pacemaker_Explained/index.html#_rule_properties boolean_op = rule_el.get("boolean-op", "and") string_parts = [] for child_dto in children_dto_list: if child_dto.type == CibRuleExpressionType.RULE: string_parts.append(f"({child_dto.as_string})") else: string_parts.append(child_dto.as_string) return CibRuleExpressionDto( rule_el.get("id", ""), _tag_to_type[rule_el.tag], False, # TODO implement is_expired export_attributes(rule_el, with_id=False), None, None, children_dto_list, f" {boolean_op} ".join(string_parts), )
def test_full(self): for tag, nvtype in self.tag_type: with self.subTest(tag=tag, nvset_type=nvtype): xml = etree.fromstring(f""" <{tag} id="my-id" score="150"> <rule id="my-id-rule" boolean-op="or"> <op_expression id="my-id-rule-op" name="monitor" /> </rule> <nvpair id="my-id-pair1" name="name1" value="value1" /> <nvpair id="my-id-pair2" name="name2" value="value2" /> </{tag}> """) self.assertEqual( nvpair_multi.nvset_element_to_dto(xml), CibNvsetDto( "my-id", nvtype, {"score": "150"}, CibRuleExpressionDto( "my-id-rule", CibRuleExpressionType.RULE, False, {"boolean-op": "or"}, None, None, [ CibRuleExpressionDto( "my-id-rule-op", CibRuleExpressionType.OP_EXPRESSION, False, {"name": "monitor"}, None, None, [], "op monitor", ), ], "op monitor", ), [ CibNvpairDto("my-id-pair1", "name1", "value1"), CibNvpairDto("my-id-pair2", "name2", "value2"), ], ), )
def test_full(self): for nvtype, label in type_to_label: with self.subTest(nvset_type=nvtype, label=label): dto = CibNvsetDto( "my-id", nvtype, {"score": "150"}, CibRuleExpressionDto( "my-id-rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {"boolean-op": "or"}, None, None, [ CibRuleExpressionDto( "my-id-rule-op", CibRuleExpressionType.OP_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"name": "monitor"}, None, None, [], "op monitor", ), ], "op monitor", ), [ CibNvpairDto("my-id-pair1", "name1", "value1"), CibNvpairDto("my-id-pair2", "name 2", "value 2"), CibNvpairDto("my-id-pair3", "name=3", "value=3"), ], ) output = dedent(f"""\ {label}: my-id score=150 "name 2"="value 2" name1=value1 "name=3"="value=3" Rule: boolean-op=or (id:my-id-rule) Expression: op monitor (id:my-id-rule-op) """) self.assert_lines(dto, output)
def _common_expr_to_dto(self, expr_el: _Element) -> CibRuleExpressionDto: return CibRuleExpressionDto( str(expr_el.get("id", "")), self._tag_to_type[str(expr_el.tag)], CibRuleInEffectStatus.UNKNOWN, export_attributes(expr_el, with_id=False), None, None, [], self._str_eval.get_str(expr_el), )
def test_datespec(self): xml = etree.fromstring(""" <rule id="rule"> <date_expression id="rule-expr" operation="date_spec"> <date_spec id="rule-expr-datespec" hours="1-14" monthdays="20-30" months="1" /> </date_expression> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, {"operation": "date_spec"}, CibRuleDateCommonDto( "rule-expr-datespec", { "hours": "1-14", "monthdays": "20-30", "months": "1", }, ), None, [], "date-spec hours=1-14 monthdays=20-30 months=1", ), ], "date-spec hours=1-14 monthdays=20-30 months=1", ), )
def _common_expr_to_dto(expr_el: Element, as_string: str) -> CibRuleExpressionDto: return CibRuleExpressionDto( expr_el.get("id", ""), _tag_to_type[expr_el.tag], False, export_attributes(expr_el, with_id=False), None, None, [], as_string, )
def test_inrange_start_duration(self): xml = etree.fromstring(""" <rule id="rule"> <date_expression id="rule-expr" operation="in_range" start="2014-06-26" > <duration id="rule-expr-duration" years="1"/> </date_expression> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "rule", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "rule-expr", CibRuleExpressionType.DATE_EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "operation": "in_range", "start": "2014-06-26", }, None, CibRuleDateCommonDto( "rule-expr-duration", {"years": "1"}, ), [], "date in_range 2014-06-26 to duration years=1", ), ], "date in_range 2014-06-26 to duration years=1", ), )
def _date_expr_to_dto(self, expr_el: _Element) -> CibRuleExpressionDto: date_spec = expr_el.find("./date_spec") duration = expr_el.find("./duration") return CibRuleExpressionDto( str(expr_el.get("id", "")), self._tag_to_type[str(expr_el.tag)], CibRuleInEffectStatus.UNKNOWN, export_attributes(expr_el, with_id=False), None if date_spec is None else self._date_common_to_dto(date_spec), None if duration is None else self._date_common_to_dto(duration), [], self._str_eval.get_str(expr_el), )
def test_value_comparison_with_type(self): xml = etree.fromstring(""" <rule id="my-id"> <expression id="my-id-expr" attribute="foo" operation="gt" type="version" value="1.2.3" /> </rule> """) self.assertEqual( rule_element_to_dto(get_in_effect_eval(), xml), CibRuleExpressionDto( "my-id", CibRuleExpressionType.RULE, CibRuleInEffectStatus.UNKNOWN, {}, None, None, [ CibRuleExpressionDto( "my-id-expr", CibRuleExpressionType.EXPRESSION, CibRuleInEffectStatus.UNKNOWN, { "attribute": "foo", "operation": "gt", "type": "version", "value": "1.2.3", }, None, None, [], "foo gt version 1.2.3", ), ], "foo gt version 1.2.3", ), )