class BinaryExprSchema(BaseSchema): """ >>> q = {'left': 'name', 'op': '=', 'right': 'foo'} >>> result = BinaryExprSchema().load(q) >>> assert result == q """ op = base.String(description="The operator.") left = base.String(description="The LiveStatus column name.", pattern=r"([a-z]+\.)?[_a-z]+", example="name") right = base.String(description="The value to compare the column to." ) # should be AnyOf(all openapi types)
class CustomFolderAttributes(ValueTypedDictSchema): value_type = ValueTypedDictSchema.field( base.String(description="Each tag is a mapping of string to string")) @post_load def _valid(self, data, **kwargs): return validate_custom_host_attributes(data)
class LogicalExprSchema(BaseSchema): """Expression combining multiple other query expressions.""" op = base.String(description="The operator.") # many=True does not work here for some reason. expr = base.List( base.Nested( lambda *a, **kw: ExprSchema(*a, **kw), # pylint: disable=unnecessary-lambda description="A list of query expressions to combine.", ))
class CustomFolderAttributes(ValueTypedDictSchema): value_type = ValueTypedDictSchema.field( base.String(description="Each tag is a mapping of string to string")) @post_load def _valid(self, data, **kwargs): try: validate_host_attributes(data, new=self.context["object_context"]) except MKUserError as exc: raise ValidationError(str(exc))
class NotExprSchema(BaseSchema): """Expression negating another query expression. Examples: >>> from cmk.utils.livestatus_helpers.tables import Hosts >>> input_expr = {'op': '=', 'left': 'hosts.name', 'right': 'foo'} >>> q = {'op': 'not', 'expr': input_expr} >>> result = NotExprSchema(context={'table': Hosts}).load(q) >>> assert result == q """ op = base.String(description="The operator. In this case `not`.") expr = base.Nested( lambda: ExprSchema(), # pylint: disable=unnecessary-lambda description="The query expression to negate.", )
def attributes_field( object_type: ObjectType, object_context: ObjectContext, description: Optional[str] = None, example: Optional[Any] = None, required: bool = False, load_default: Any = utils.missing, many: bool = False, names_only: bool = False, ) -> _fields.Field: """Build an Attribute Field Args: object_type: May be one of 'folder', 'host' or 'cluster'. object_context: May be 'create' or 'update'. Deletion is considered as 'update'. description: A descriptive text of this field. Required. example: An example for the OpenAPI documentation. Required. required: Whether the field must be sent by the client or is option. load_default: many: names_only: When set to True, the field will be a List of Strings which validate the tag names only. Returns: """ if description is None: # SPEC won't validate without description, though the error message is very obscure, so we # clarify this here by force. raise ValueError("description is necessary.") custom_schema = { "host": CustomHostAttributes, "cluster": CustomHostAttributes, "folder": CustomFolderAttributes, } if not names_only: return MultiNested( [ attr_openapi_schema(object_type, object_context), custom_schema[object_type], ], metadata={"context": { "object_context": object_context }}, merged=True, # to unify both models description=description, example=example, many=many, load_default=dict if load_default is utils.missing else utils.missing, required=required, ) attrs = { attr.name for attr in collect_attributes(object_type, object_context) } def validate(value): if value not in attrs: raise ValidationError(f"Unknown attribute: {value!r}") return base.List( base.String(validate=validate), description=description, example=example, load_default=load_default, required=required, )