class ConcreteTimePeriod(BaseSchema): alias = fields.String(description="The alias of the time period", example="alias") active_time_ranges = fields.List( fields.Nested(ConcreteTimeRangeActive), description="The days for which time ranges were specified", example={ "day": "all", "time_ranges": [{ "start": "12:00", "end": "14:00" }] }, ) exceptions = fields.List( fields.Nested(ConcreteTimePeriodException), description="Specific day exclusions with their list of time ranges", example=[{ "date": "2020-01-01", "time_ranges": [{ "start": "14:00", "end": "18:00" }] }], ) exclude = fields.List( # type: ignore[assignment] fields.String(description="Name of excluding time period", example="holidays"), description= "The collection of time period aliases whose periods are excluded", )
class JobLogs(BaseSchema): result = fields.List( fields.String(), description="The list of result related logs", ) progress = fields.List( fields.String(), description="The list of progress related logs", )
class UserAttributes(BaseSchema): fullname = fields.String(required=True, description="The alias or full name of the user.") customer = gui_fields.customer_field( required=True, should_exist=True, ) disable_login = fields.Boolean( required=False, description="This field indicates if the user is allowed to login to the monitoring.", ) contact_options = fields.Nested( ConcreteUserContactOption, required=False, description="Contact settings for the user", ) idle_timeout = fields.Nested( UserIdleOption, required=False, description="Idle timeout for the user. Per default, the global configuration is used.", example={"option": "global"}, ) roles = fields.List( fields.String(), description="The list of assigned roles to the user", ) authorized_sites = fields.List( fields.String(), description="The names of the sites that this user is authorized to handle", required=False, ) contactgroups = fields.List( fields.String(), description="The contact groups that this user is a member of", required=False, ) pager_address = fields.String( required=False, description="", ) disable_notifications = fields.Nested( ConcreteDisabledNotifications, required=False, ) language = fields.String( required=False, description="The language used by the user in the user interface", ) enforce_password_change = fields.Boolean( required=False, description="This field indicates if the user is forced to change the password on the " "next login or access.", ) interface_options = fields.Nested( ConcreteUserInterfaceAttributes, required=False, )
class BIAggregationStateResponseSchema(Schema): aggregations = fields.Dict( description="The Aggregation state", example={}, ) missing_sites = fields.List( fields.String(), description="The missing sites", example=["beta", "heute"], ) missing_aggr = fields.List( fields.String(), description="the missing aggregations", example=["Host heute"] )
class TagConditionConditionSchemaBase(TagConditionSchemaBase): """Convert Rulesets to Checkmk structure and back Examples: >>> tcs = TagConditionConditionSchemaBase() >>> tcs.dump([{'hurz': {'$or': ['a', 'b', 'c']}}], many=True) [{'key': 'hurz', 'operator': 'one_of', 'value': ['a', 'b', 'c']}] >>> tcs.dump({'hurz': {'$or': ['a', 'b', 'c']}}) {'key': 'hurz', 'operator': 'one_of', 'value': ['a', 'b', 'c']} >>> tcs.dump({'hurz': {'$or': 'h'}}) Traceback (most recent call last): ... marshmallow.exceptions.ValidationError: Invalid type: 'h' """ cast_to_dict = True allowed_operators = ("one_of", "none_of") operator_type = "collection" # field defined in superclass operator = fields.String( description= "If the matched tag should be one of the given values, or not.", enum=list( allowed_operators), # Our serializer only wants to know lists. ) value = fields.List( fields.String(description="The value of a tag."), description="A list of values for the tag.", )
class Linkable(BaseSchema): links = fields.List( fields.Nested(LinkSchema), required=True, description="list of links to other resources.", example=None, )
class ApiError(BaseSchema): """This is the base class for all API errors.""" code = fields.Integer( description="The HTTP status code.", required=True, example=404, ) message = fields.String( description="Detailed information on what exactly went wrong.", required=True, example="The resource could not be found.", ) title = fields.String( description="A summary of the problem.", required=True, example="Not found", ) _fields = fields.Dict( data_key="fields", # mypy, due to attribute "fields" being used in marshmallow.Schema keys=fields.String(description="The field name"), values=fields.List(fields.String(description="The error messages")), description="Detailed error messages on all fields failing validation.", required=False, ) ext: fields.Field = fields.Dict( keys=fields.String(description="The key name"), values=fields.String(description="The value"), description="Additional information about the error.", required=False, )
class HostExtensions(BaseSchema): folder = gui_fields.FolderField( description="The folder, in which this host resides.", ) attributes = gui_fields.attributes_field( "host", "view", description="Attributes of this host.", example={"ipaddress": "192.168.0.123"}, ) effective_attributes = fields.Dict( description="All attributes of this host and all parent folders. Format may change!", allow_none=True, example={"tag_snmp_ds": None}, ) is_cluster = fields.Boolean( description="If this is a cluster host, i.e. a container for other hosts.", ) is_offline = fields.Boolean( description="Whether the host is offline", ) cluster_nodes = fields.List( gui_fields.HostField(), allow_none=True, load_default=None, description="In the case this is a cluster host, these are the cluster nodes.", )
class ObjectCollectionMember(ObjectMemberBase): memberType = fields.Constant("collection") value = fields.List(fields.Nested(LinkSchema())) name = fields.String(example="important_values") title = fields.String( description="A human readable title of this object. Can be used for " "user interfaces.", )
def openapi_field(self) -> gui_fields.Field: return fields.List( fields.String(validate=fields.ValidateAnyOfValidators([ fields.ValidateIPv4(), gui_fields.ValidateHostName(), ])), description="A list of IPv4 addresses.", )
class FolderCollection(DomainObjectCollection): domainType = fields.Constant( "folder_config", description="The domain type of the objects in the collection.", ) value = fields.List( fields.Nested(FolderSchema()), description="A list of folder objects.", )
class HostConfigCollection(DomainObjectCollection): domainType = fields.Constant( "host_config", description="The domain type of the objects in the collection.", ) value = fields.List( fields.Nested(HostConfigSchema()), description="A list of host objects.", )
class ObjectProperty(Linkable): id = fields.String(description="The unique name of this property, local to this domain type.") value = fields.List( fields.String(), description="The value of the property. In this case a list.", ) extensions = fields.Dict( description="Additional attributes alongside the property.", )
class UserCollection(DomainObjectCollection): domainType = fields.Constant( "user_config", description="The domain type of the objects in the collection.", ) value = fields.List( fields.Nested(UserObject), description="A list of user objects.", )
class ConcreteTimePeriodException(BaseSchema): date = fields.String( example="2020-01-01", format="date", description="The date of the time period exception." "8601 profile", ) time_ranges = fields.List( fields.Nested(ConcreteTimeRange), example="[{'start': '14:00', 'end': '18:00'}]", )
class FailedHosts(BaseSchema): succeeded_hosts = fields.Nested( response_schemas.HostConfigCollection(), description="The list of succeeded host objects", ) failed_hosts = fields.Dict( keys=fields.String(description="Name of the host"), values=fields.List(fields.String(description="The error messages")), description="Detailed error messages on hosts failing the action", )
class User(Linkable): userName = fields.String(description="A unique user name.") friendlyName = fields.String( required=True, description= "The user's name in a form suitable to be rendered in a UI.", ) email = fields.String( description="(optional) the user's email address, if known.") roles = fields.List( fields.String(), description= "List of unique role names that apply to this user (can be empty).", )
class ActionResultScalar(ActionResultBase): result = fields.Nested( Schema.from_dict( { "links": fields.List( fields.Nested(LinkSchema), required=True, ), "value": fields.String( required=True, example="Done.", ), }, name="ActionResultScalarValue", ), description="The scalar result of the action.", )
class ActionResultObject(ActionResultBase): result = fields.Nested( Schema.from_dict( { "links": fields.List( fields.Nested(LinkSchema), required=True, ), "value": fields.Dict( required=True, example={"duration": "5 seconds."}, ), }, name="ActionResultObjectValue", ), description="The result of the action. In this case, an object.", )
class PasswordExtension(BaseSchema): ident = fields.String( example="pass", description="The unique identifier for the password", ) title = fields.String( example="Kubernetes login", description="The title for the password", ) comment = fields.String( example="Kommentar", description="A comment for the password", ) documentation_url = fields.String( example="localhost", attribute="docu_url", description="The URL pointing to documentation or any other page.", ) password = fields.String( required=True, example="password", description="The password string", ) owned_by = fields.String( example="admin", description= "The owner of the password who is able to edit, delete and use existing passwords.", ) shared = fields.List( fields.String( example="all", description="The member the password is shared with", ), example=["all"], attribute="shared_with", description="The list of members the password is shared with", ) customer = gui_fields.customer_field( required=True, should_exist=True, )
class HostParameters(BaseSchema): """All the parameters for the hosts list. Examples: >>> p = HostParameters() >>> p.load({})['columns'] [Column(hosts.name: string)] >>> p.load({})['sites'] [] """ sites = fields.List( gui_fields.SiteField(), description="Restrict the query to this particular site.", load_default=[], ) query = gui_fields.query_field(Hosts, required=False) columns = gui_fields.column_field(Hosts, mandatory=[Hosts.name], example=["name"])
class BulkDiscovery(BaseSchema): hostnames = fields.List( EXISTING_HOST_NAME, required=True, example=["example", "sample"], description="A list of host names", ) mode = fields.String( required=False, description="""The mode of the discovery action. Can be one of: * `new` - Add unmonitored services and new host labels * `remove` - Remove vanished services * `fix_all` - Add unmonitored services and new host labels, remove vanished services * `refresh` - Refresh all services (tabula rasa), add new host labels * `only_host_labels` - Only discover new host labels """, enum=list(DISCOVERY_ACTION.keys()), example="refresh", load_default="new", ) do_full_scan = fields.Boolean( required=False, description="The option whether to perform a full scan or not.", example=False, load_default=True, ) bulk_size = fields.Integer( required=False, description="The number of hosts to be handled at once.", example=False, load_default=10, ) ignore_errors = fields.Boolean( required=False, description= "The option whether to ignore errors in single check plugins.", example=False, load_default=True, )
class ApiError(BaseSchema): code = fields.Integer( description="The HTTP status code.", required=True, example=404, ) message = fields.String( description="Detailed information on what exactly went wrong.", required=True, example="The resource could not be found.", ) title = fields.String( description="A summary of the problem.", required=True, example="Not found", ) _fields = fields.Dict( data_key="fields", # mypy keys=fields.String(description="The field name"), values=fields.List(fields.String(description="The error messages")), description="Detailed error messages on all fields failing validation.", required=False, )
class HostOrServiceConditionSchema(base.BaseSchema): """ Examples: >>> wor = HostOrServiceConditionSchema() # without regex >>> rv = wor.load({ ... 'match_on': ['foo'], ... 'operator': 'one_of', ... }) >>> rv ['foo'] >>> wor.dump(rv) {'match_on': ['foo'], 'operator': 'one_of'} >>> wr = HostOrServiceConditionSchema(use_regex="always") # with regex >>> rv = wr.load({ ... 'match_on': ['abc$', 'xyz$'], ... 'operator': 'one_of', ... }) >>> rv [{'$regex': 'abc$'}, {'$regex': 'xyz$'}] >>> wr.dump(rv) {'match_on': ['abc$', 'xyz$'], 'operator': 'one_of'} >>> wadr = HostOrServiceConditionSchema(use_regex="adaptive") # when prefixed with ~ >>> rv = wadr.load({ ... 'match_on': ['~(heute|gestern)$', 'heute', '~[v]orgestern$'], ... 'operator': 'one_of', ... }) >>> rv [{'$regex': '^(heute|gestern)$'}, 'heute', {'$regex': '^[v]orgestern$'}] >>> wadr.dump(rv) {'match_on': ['~(heute|gestern)$', 'heute', '~[v]orgestern$'], 'operator': 'one_of'} """ def __init__( self, *, only: typing.Optional[types.StrSequenceOrSet] = None, exclude: types.StrSequenceOrSet = (), many: bool = False, context: typing.Optional[typing.Dict] = None, load_only: types.StrSequenceOrSet = (), dump_only: types.StrSequenceOrSet = (), partial: typing.Union[bool, types.StrSequenceOrSet] = False, unknown: typing.Optional[str] = None, use_regex: typing.Literal["always", "never", "adaptive"] = "adaptive", ): self.use_regex = use_regex super().__init__( only=only, exclude=exclude, many=many, context=context, load_only=load_only, dump_only=dump_only, partial=partial, unknown=unknown, ) cast_to_dict = True match_on = fields.List( fields.String(), description="A list of string matching regular expressions.", ) operator = fields.String( enum=["one_of", "none_of"], description= ("How the hosts or services should be matched.\n" " * one_of - will match if any of the hosts or services is matched\n" " * none_of - will match if none of the hosts are matched. In other words: will match" " all hosts or services which are not specified.\n"), ) @pre_dump(pass_many=False) def convert_to_api( self, data: HostOrServiceConditions, many: bool = False, partial: bool = False, ) -> typing.Optional[ApiMatchExpression]: if not data: return None def _remove_regex_dict(_entry): if isinstance(_entry, dict) and "$regex" in _entry: regex = _entry["$regex"] if self.use_regex == "adaptive" and regex: if regex[0] == "^": return "~" + regex[1:] return "~" + regex return regex if isinstance(_entry, str): return _entry raise ValidationError(f"Unknown format: {_entry}") def _ensure_list(_entry) -> typing.List[str]: if isinstance(_entry, list): return _entry return [_entry] rv: ApiMatchExpression = { "match_on": [], "operator": "one_of", } if isinstance(data, dict): try: entries = _ensure_list(_unpack_value(data)) except ValueError as exc: raise ValidationError(str(exc)) from exc rv["operator"] = _unpack_operator(data) else: entries = _ensure_list(data) rv["match_on"] = [_remove_regex_dict(entry) for entry in entries] return rv @post_load(pass_many=False) def convert_to_checkmk( self, data: ApiMatchExpression, many: bool = False, partial: bool = False, ) -> HostOrServiceConditions: def _wrap_entry(_entry): if _entry[0] == "~": return {"$regex": f"^{_entry[1:]}"} return _entry match_on: HostOrServiceConditionsSimple if self.use_regex == "always": match_on = [{"$regex": entry} for entry in data["match_on"]] elif self.use_regex == "adaptive": match_on = [_wrap_entry(entry) for entry in data["match_on"]] elif isinstance(data["match_on"], list): match_on = typing.cast(HostOrServiceConditionsSimple, data["match_on"]) else: raise ValidationError(f"Unknown type: {data['match_on']!r}.") if data["operator"] == "one_of": # pylint: disable=no-else-return return match_on elif data["operator"] == "none_of": return {"$nor": match_on} else: raise ValidationError(f"Unknown match type: {data['operator']}")
def openapi_field(self) -> gui_fields.Field: return fields.List( fields.String(), description="Name of host attributes which are locked in the UI.", )
def openapi_field(self) -> gui_fields.Field: return fields.List( fields.String(validate=fields.ValidateIPv6()), description="A list of IPv6 addresses.", )
def openapi_field(self) -> gui_fields.Field: return fields.List( gui_fields.HostField(should_exist=True), description="A list of parents of this host.", )
class BIAggregationStateRequestSchema(Schema): filter_names = fields.List(fields.String(), description="Filter by names", example=["Host foo"]) filter_groups = fields.List( fields.String(), description="Filter by group", example=["My Group"] )
class ConcreteTimeRangeActive(BaseSchema): day = fields.String( description="The day for which the time ranges are specified", pattern=f"{'|'.join(weekday_ids())}", ) time_ranges = fields.List(fields.Nested(ConcreteTimeRange))
from cmk.gui.plugins.openapi.utils import problem from cmk import fields PERMISSIONS = permissions.Ignore( permissions.AnyPerm([ permissions.Perm("general.see_all"), permissions.Perm("bi.see_all"), permissions.Perm("mkeventd.seeall"), ])) PARAMETERS = [{ "sites": fields.List( gui_fields.SiteField(), description="Restrict the query to this particular site.", load_default=list, ), "query": gui_fields.query_field( Services, required=False, example='{"op": "=", "left": "host_name", "right": "example.com"}', ), "columns": gui_fields.column_field( Services, mandatory=[ Services.host_name, Services.description, ],