aria.ops.object
1from __future__ import annotations 2 3import copy 4from typing import Any 5from typing import List 6from typing import Optional 7from typing import Set 8 9from aria.ops.data import Metric 10from aria.ops.data import Property 11from aria.ops.event import Event 12 13# Copyright 2022 VMware, Inc. 14# SPDX-License-Identifier: Apache-2.0 15 16 17class Key: 18 """Object's Key class, used for identifying Objects 19 20 Objects are identified by the Adapter Kind, Object Kind, and one or more Identifiers. 21 22 Identifiers can be either the Object's 'name', or one or more 'Identifier' key-value pairs. 23 In order for an 'Identifier' to be used for identification, it must have 'is_part_of_uniqueness' set to True 24 (this is the default). 25 26 Two Objects with the same Key are not permitted in a :class:`Result`. 27 28 Objects must be created with the full key. Keys should not change after the Object has been created. 29 30 All Objects with the same Adapter Kind and Object Kind must have the same set of Identifiers that have 31 'is_part_of_uniqueness' set to True. 32 """ 33 34 def __init__( 35 self, 36 adapter_kind: str, 37 object_kind: str, 38 name: str, 39 identifiers: Optional[List[Identifier]] = None, 40 ) -> None: 41 """Initializes a Key, which uniquely identifies a vROps Object 42 43 :param adapter_kind: The Adapter Kind this Object is associated with. 44 :param object_kind: The Object Kind (e.g., class) of this Object. 45 :param name: A human-readable name for this Object. Should be unique if possible. 46 :param identifiers: A list of :class:`Identifier` that uniquely identify the Object. If none are present than 47 the name must be unique and is used for identification. All Objects with the same adapter kind and Object 48 kind must have the same set of identifiers. 49 """ 50 self.adapter_kind = adapter_kind 51 self.object_kind = object_kind 52 self.name = name 53 if identifiers is None: 54 identifiers = [] 55 self.identifiers = {identifier.key: identifier for identifier in identifiers} 56 57 def __repr__(self) -> str: 58 return f"{self.adapter_kind}:{self.object_kind}:{self.identifiers}" 59 60 def __key(self) -> tuple: 61 # Sort all identifiers by 'key' that are part of uniqueness 62 unique_identifiers = sorted( 63 filter(lambda id_: id_.is_part_of_uniqueness, self.identifiers.values()), 64 key=lambda id_: id_.key, 65 ) 66 if len(unique_identifiers) == 0: 67 # If there are no identifiers, or if all identifiers are not part of uniqueness, the name is used as 68 # uniquely identifying 69 return self.adapter_kind, self.object_kind, self.name 70 else: 71 # Otherwise, if there is at least one identifier that is part of uniqueness, name is not used for 72 # identification. Add each of the unique identifiers to the tuple, sorted by key 73 return (self.adapter_kind, self.object_kind) + tuple(unique_identifiers) 74 75 def __eq__(self, other: Any) -> bool: 76 if isinstance(other, Key): 77 # TODO: raise exception if the object types are the same but identifier keys don't match? 78 return self.__key() == other.__key() 79 else: 80 return False 81 82 def __hash__(self) -> int: 83 return hash(self.__key()) 84 85 def get_identifier( 86 self, key: str, default_value: Optional[str] = None 87 ) -> Optional[str]: 88 """Return the value for the given identifier key 89 90 :param key: The identifier key 91 :param default_value: An optional default value 92 :return: The value associated with the identifier. 93 If the value associated with the identifier is empty and 'default_value' is 94 provided, returns 'default_value'. 95 If the identifier does not exist, returns default_value if provided, else 'None'. 96 """ 97 if self.identifiers.get(key): 98 if self.identifiers[key].value or default_value is None: 99 return self.identifiers[key].value 100 return default_value 101 return default_value 102 103 def get_json(self) -> dict: 104 """Get a JSON representation of this Key 105 106 Returns a JSON representation of this Key in the format required by vROps. 107 108 :return: A JSON representation of this Key 109 """ 110 return { 111 "name": self.name, 112 "adapterKind": self.adapter_kind, 113 "objectKind": self.object_kind, 114 "identifiers": [ 115 identifier.get_json() for identifier in self.identifiers.values() 116 ], 117 } 118 119 120class IdentifierUniquenessException(Exception): 121 """Exception when two Objects of the same type have the same identifier but the `is_part_of_uniqueness` attribute 122 does not match. 123 """ 124 125 pass 126 127 128class Identifier: 129 """Represents a piece of data that identifies an Object.""" 130 131 def __init__( 132 self, key: str, value: str, is_part_of_uniqueness: bool = True 133 ) -> None: 134 """Creates an identifier which is used as part of an Object's identification in a :class:`Key` 135 136 Represents a piece of data that identifies an Object. If `is_part_of_uniqueness` is False, this data can 137 change over time without creating a new Object. This is primarily used for human-readable values that are useful 138 in identification purposes, but may change at times. 139 140 :param key: A key that determines which identifier the value corresponds to. 141 :param value: The value of the identifier. 142 :param is_part_of_uniqueness: Determines if this key/value pair is used in the identification process 143 """ 144 self.key = key 145 self.value = value 146 self.is_part_of_uniqueness = is_part_of_uniqueness 147 148 def __repr__(self) -> str: 149 u = "*" if self.is_part_of_uniqueness else "" 150 return f"{self.key}{u}:{self.value}" 151 152 def __key(self) -> tuple: 153 if self.is_part_of_uniqueness: 154 # 'True' is included as the second tuple because otherwise we could get a collision between a key that has 155 # a value of 'False' and a key that is not a part of uniqueness 156 return self.key, True, self.value 157 return self.key, False 158 159 def __eq__(self, other: Any) -> bool: 160 if isinstance(other, Identifier): 161 if ( 162 self.key == other.key 163 and self.is_part_of_uniqueness != other.is_part_of_uniqueness 164 ): 165 # TODO: is there a better way we can handle this case? 166 raise IdentifierUniquenessException( 167 f"Identifier '{self.key}' has an inconsistent uniqueness attribute" 168 ) 169 return self.__key() == other.__key() 170 return False 171 172 def __hash__(self) -> int: 173 return hash(self.__key()) 174 175 def get_json(self) -> dict: 176 """Get a JSON representation of this Identifier 177 178 Returns a JSON representation of this Identifier in the format required by vROps. 179 180 :return: A JSON representation of this Identifier 181 """ 182 return { 183 "key": self.key, 184 "value": self.value, 185 "isPartOfUniqueness": self.is_part_of_uniqueness, 186 } 187 188 189class Object: 190 """Represents an Object (resource) in vROps. 191 192 Contains :class:`Metric`, :class:`Property`, :class:`Event`, and relationships to other Objects. Each Object is 193 identified by a unique :class:`Key`. 194 """ 195 196 def __init__(self, key: Key) -> None: 197 """Create a new Object with a given Key. 198 199 The preferred way to create a new Object is to call the :class:`Result.object` method on the :class:`Result` 200 class, which ensures that for a given key only one Object exists. 201 202 :param key: The :class:`Key` that uniquely identifies this Object 203 """ 204 self._key: Key = key 205 self._metrics: List[Metric] = [] 206 self._properties: List[Property] = [] 207 self._events: Set[Event] = set() 208 self._parents: Set[Key] = set() 209 self._children: Set[Key] = set() 210 self._updated_children: bool = False 211 212 def get_key(self) -> Key: 213 """Get a copy of the Object's Key. 214 215 An object's Key cannot change after it has been created. 216 217 :return: A copy of the object's key 218 """ 219 return copy.deepcopy(self._key) 220 221 def adapter_type(self) -> str: 222 """Get the adapter type of this object 223 224 :return: The adapter type of this object 225 """ 226 return self._key.adapter_kind 227 228 def object_type(self) -> str: 229 """Get the type of this object 230 231 :return: The type of this object 232 """ 233 return self._key.object_kind 234 235 def get_identifier_value( 236 self, identifier_key: str, default_value: Optional[str] = None 237 ) -> Optional[str]: 238 """Retrieve the value of a given identifier 239 240 :param identifier_key: Key of the identifier 241 :param default_value: An optional default value 242 :return: The value associated with the identifier. 243 If the value associated with the identifier is empty and 'default_value' is 244 provided, returns 'default_value'. 245 If the identifier does not exist, returns default_value if provided, else 'None'. 246 """ 247 return self._key.get_identifier(identifier_key, default_value) 248 249 def add_metric(self, metric: Metric) -> None: 250 """Method that adds a single Metric data point to this Object 251 252 :param metric: A :class:`Metric` data point to add to this Object 253 :return: None 254 """ 255 self._metrics.append(metric) 256 257 def add_metrics(self, metrics: List[Metric]) -> None: 258 """Method that adds a list of Metric data points to this Object 259 260 :param metrics: A list of :class:`Metric` data points to add to this Object 261 :return: None 262 """ 263 for metric in metrics: 264 self.add_metric(metric) 265 266 def with_metric(self, *args: Any, **kwargs: Any) -> None: 267 """Method that handles creating a :class:`Metric` data point, and adding to this Object. 268 269 The signature matches :class:`Metric.__init__`. 270 :return: None 271 """ 272 self.add_metric(Metric(*args, **kwargs)) 273 274 def get_metric(self, key: str) -> List[Metric]: 275 """ 276 277 :param key: Metric key of the metric to return. 278 :return: All metrics matching the given key. 279 """ 280 return list(filter(lambda metric: metric.key == key, self._metrics)) 281 282 def get_metric_values(self, key: str) -> List[float]: 283 """ 284 285 :param key: Metric key of the metric to return. 286 :return: A list of the metric values in chronological order. 287 """ 288 # find matching metrics 289 metrics = self.get_metric(key) 290 291 # sort metrics by timestamp from oldest to newest 292 metrics.sort(key=lambda metric: metric.timestamp) # type: ignore 293 294 return [m.value for m in metrics] 295 296 def get_last_metric_value(self, key: str) -> Optional[float]: 297 """ 298 299 :param key: Metric key of the metric to return. 300 :return: The latest value of the metric or None if no metric exists with the given key. 301 """ 302 metrics = self.get_metric_values(key) 303 304 if not metrics: 305 return None 306 else: 307 return metrics[-1] 308 309 def add_property(self, property_: Property) -> None: 310 """Method that adds a single Property value to this Object 311 312 :param property_: A :class:`Property` value to add to this Object 313 :return: None 314 """ 315 self._properties.append(property_) 316 317 def add_properties(self, properties: List[Property]) -> None: 318 """Method that adds a list of Property values to this Object 319 320 :param properties: A list of :class:`Property` values to add to this Object 321 :return: None 322 """ 323 for property_ in properties: 324 self.add_property(property_) 325 326 def with_property(self, *args: Any, **kwargs: Any) -> None: 327 """Method that handles creating a :class:`Property` value, and adding to this Object. 328 329 The signature matches :class:`Property.__init__`. 330 :return: None 331 """ 332 self.add_property(Property(*args, **kwargs)) 333 334 def get_property(self, key: str) -> List[Property]: 335 """ 336 337 :param key: Property key of the property to return. 338 :return: All properties matching the given key 339 """ 340 return list(filter(lambda property_: property_.key == key, self._properties)) 341 342 def get_property_values(self, key: str) -> List[str]: 343 """ 344 345 :param key: Property key of the property to return. 346 :return: A list of the property values in chronological order. 347 """ 348 # find matching properties 349 properties = self.get_property(key) 350 351 # sort properties by timestamp from oldest to newest 352 properties.sort(key=lambda property_: property_.timestamp) # type: ignore 353 354 return [p.value for p in properties] 355 356 def get_last_property_value(self, key: str) -> Optional[str | float]: 357 """ 358 359 :param key: Property key of the property to return. 360 :return: The latest value of the property or None if no property exists with the given key. 361 """ 362 properties = self.get_property_values(key) 363 364 if not properties: 365 return None 366 else: 367 return properties[-1] 368 369 def add_event(self, event: Event) -> None: 370 """Method that adds a single Event to this Object 371 372 :param event: An :class:`Event` to add to this Object 373 :return: None 374 """ 375 self._events.add(event) 376 377 def add_events(self, events: List[Event]) -> None: 378 """Method that adds a list of Events to this Object 379 380 :param events: A list of :class:`Event` to add to this Object 381 :return: None 382 """ 383 for event in events: 384 self.add_event(event) 385 386 def with_event(self, *args: Any, **kwargs: Any) -> None: 387 """Method that handles creating an :class:`Event`, and adding to this Object. 388 389 The signature matches :class:`Event.__init__`. 390 :return: None 391 """ 392 self.add_event(Event(*args, **kwargs)) 393 394 def add_parent(self, parent: Object) -> None: 395 """Method that adds a parent Object to this Object. 396 397 This Object will also be added as a child to the parent. 398 399 Relationship cycles are not permitted. 400 401 :param parent: Parent :class:`Object` 402 :return: None 403 """ 404 self._parents.add(parent._key) 405 parent._children.add(self._key) 406 407 def add_parents(self, parents: List[Object]) -> None: 408 """Method that adds a list of parent Objects to this Object. 409 410 This Object will also be added as a child to each of the parents. 411 412 Relationship cycles are not permitted. 413 414 :param parents: A list of parent :class:`Object` 415 :return: None 416 """ 417 for parent in parents: 418 self.add_parent(parent) 419 420 def get_parents(self) -> Set[Key]: 421 """ 422 :return: A set of all object keys that are parents of this object 423 """ 424 return self._parents 425 426 def add_child(self, child: Object) -> None: 427 """Method that adds a child Object to this Object. 428 429 This Object will also be added as a parent to the child. 430 431 Relationship cycles are not permitted. 432 433 :param child: Child :class:`Object` 434 :return: None 435 """ 436 self._updated_children = True 437 self._children.add(child._key) 438 child._parents.add(self._key) 439 440 def add_children(self, children: List[Object]) -> None: 441 """Method that adds a list of child Objects to this Object. 442 443 This Object will also be added as a parent to each of the children. 444 445 Relationship cycles are not permitted. 446 447 :param children: A list of child :class:`Object` 448 :return: None 449 """ 450 # We want to set this even in the case where the list is empty 451 self._updated_children = True 452 for child in children: 453 self.add_child(child) 454 455 def get_children(self) -> Set[Key]: 456 """ 457 :return: A set of all object keys that are children of this object 458 """ 459 return self._children 460 461 def has_content(self) -> bool: 462 """ 463 :return: True if the object contains any metrics, properties or events; False otherwise. 464 """ 465 return bool(self._metrics) or bool(self._properties) or bool(self._events) 466 467 def get_json(self) -> dict: 468 """Get a JSON representation of this Object 469 470 Returns a JSON representation of this Object in the format required by vROps. 471 472 :return: A JSON representation of this Object 473 """ 474 return { 475 "key": self._key.get_json(), 476 "metrics": [metric.get_json() for metric in self._metrics], 477 "properties": [prop.get_json() for prop in self._properties], 478 "events": [event.get_json() for event in self._events], 479 }
18class Key: 19 """Object's Key class, used for identifying Objects 20 21 Objects are identified by the Adapter Kind, Object Kind, and one or more Identifiers. 22 23 Identifiers can be either the Object's 'name', or one or more 'Identifier' key-value pairs. 24 In order for an 'Identifier' to be used for identification, it must have 'is_part_of_uniqueness' set to True 25 (this is the default). 26 27 Two Objects with the same Key are not permitted in a :class:`Result`. 28 29 Objects must be created with the full key. Keys should not change after the Object has been created. 30 31 All Objects with the same Adapter Kind and Object Kind must have the same set of Identifiers that have 32 'is_part_of_uniqueness' set to True. 33 """ 34 35 def __init__( 36 self, 37 adapter_kind: str, 38 object_kind: str, 39 name: str, 40 identifiers: Optional[List[Identifier]] = None, 41 ) -> None: 42 """Initializes a Key, which uniquely identifies a vROps Object 43 44 :param adapter_kind: The Adapter Kind this Object is associated with. 45 :param object_kind: The Object Kind (e.g., class) of this Object. 46 :param name: A human-readable name for this Object. Should be unique if possible. 47 :param identifiers: A list of :class:`Identifier` that uniquely identify the Object. If none are present than 48 the name must be unique and is used for identification. All Objects with the same adapter kind and Object 49 kind must have the same set of identifiers. 50 """ 51 self.adapter_kind = adapter_kind 52 self.object_kind = object_kind 53 self.name = name 54 if identifiers is None: 55 identifiers = [] 56 self.identifiers = {identifier.key: identifier for identifier in identifiers} 57 58 def __repr__(self) -> str: 59 return f"{self.adapter_kind}:{self.object_kind}:{self.identifiers}" 60 61 def __key(self) -> tuple: 62 # Sort all identifiers by 'key' that are part of uniqueness 63 unique_identifiers = sorted( 64 filter(lambda id_: id_.is_part_of_uniqueness, self.identifiers.values()), 65 key=lambda id_: id_.key, 66 ) 67 if len(unique_identifiers) == 0: 68 # If there are no identifiers, or if all identifiers are not part of uniqueness, the name is used as 69 # uniquely identifying 70 return self.adapter_kind, self.object_kind, self.name 71 else: 72 # Otherwise, if there is at least one identifier that is part of uniqueness, name is not used for 73 # identification. Add each of the unique identifiers to the tuple, sorted by key 74 return (self.adapter_kind, self.object_kind) + tuple(unique_identifiers) 75 76 def __eq__(self, other: Any) -> bool: 77 if isinstance(other, Key): 78 # TODO: raise exception if the object types are the same but identifier keys don't match? 79 return self.__key() == other.__key() 80 else: 81 return False 82 83 def __hash__(self) -> int: 84 return hash(self.__key()) 85 86 def get_identifier( 87 self, key: str, default_value: Optional[str] = None 88 ) -> Optional[str]: 89 """Return the value for the given identifier key 90 91 :param key: The identifier key 92 :param default_value: An optional default value 93 :return: The value associated with the identifier. 94 If the value associated with the identifier is empty and 'default_value' is 95 provided, returns 'default_value'. 96 If the identifier does not exist, returns default_value if provided, else 'None'. 97 """ 98 if self.identifiers.get(key): 99 if self.identifiers[key].value or default_value is None: 100 return self.identifiers[key].value 101 return default_value 102 return default_value 103 104 def get_json(self) -> dict: 105 """Get a JSON representation of this Key 106 107 Returns a JSON representation of this Key in the format required by vROps. 108 109 :return: A JSON representation of this Key 110 """ 111 return { 112 "name": self.name, 113 "adapterKind": self.adapter_kind, 114 "objectKind": self.object_kind, 115 "identifiers": [ 116 identifier.get_json() for identifier in self.identifiers.values() 117 ], 118 }
Object's Key class, used for identifying Objects
Objects are identified by the Adapter Kind, Object Kind, and one or more Identifiers.
Identifiers can be either the Object's 'name', or one or more 'Identifier' key-value pairs. In order for an 'Identifier' to be used for identification, it must have 'is_part_of_uniqueness' set to True (this is the default).
Two Objects with the same Key are not permitted in a Result
.
Objects must be created with the full key. Keys should not change after the Object has been created.
All Objects with the same Adapter Kind and Object Kind must have the same set of Identifiers that have 'is_part_of_uniqueness' set to True.
35 def __init__( 36 self, 37 adapter_kind: str, 38 object_kind: str, 39 name: str, 40 identifiers: Optional[List[Identifier]] = None, 41 ) -> None: 42 """Initializes a Key, which uniquely identifies a vROps Object 43 44 :param adapter_kind: The Adapter Kind this Object is associated with. 45 :param object_kind: The Object Kind (e.g., class) of this Object. 46 :param name: A human-readable name for this Object. Should be unique if possible. 47 :param identifiers: A list of :class:`Identifier` that uniquely identify the Object. If none are present than 48 the name must be unique and is used for identification. All Objects with the same adapter kind and Object 49 kind must have the same set of identifiers. 50 """ 51 self.adapter_kind = adapter_kind 52 self.object_kind = object_kind 53 self.name = name 54 if identifiers is None: 55 identifiers = [] 56 self.identifiers = {identifier.key: identifier for identifier in identifiers}
Initializes a Key, which uniquely identifies a vROps Object
Parameters
- adapter_kind: The Adapter Kind this Object is associated with.
- object_kind: The Object Kind (e.g., class) of this Object.
- name: A human-readable name for this Object. Should be unique if possible.
- identifiers: A list of
Identifier
that uniquely identify the Object. If none are present than the name must be unique and is used for identification. All Objects with the same adapter kind and Object kind must have the same set of identifiers.
86 def get_identifier( 87 self, key: str, default_value: Optional[str] = None 88 ) -> Optional[str]: 89 """Return the value for the given identifier key 90 91 :param key: The identifier key 92 :param default_value: An optional default value 93 :return: The value associated with the identifier. 94 If the value associated with the identifier is empty and 'default_value' is 95 provided, returns 'default_value'. 96 If the identifier does not exist, returns default_value if provided, else 'None'. 97 """ 98 if self.identifiers.get(key): 99 if self.identifiers[key].value or default_value is None: 100 return self.identifiers[key].value 101 return default_value 102 return default_value
Return the value for the given identifier key
Parameters
- key: The identifier key
- default_value: An optional default value
Returns
The value associated with the identifier. If the value associated with the identifier is empty and 'default_value' is provided, returns 'default_value'. If the identifier does not exist, returns default_value if provided, else 'None'.
104 def get_json(self) -> dict: 105 """Get a JSON representation of this Key 106 107 Returns a JSON representation of this Key in the format required by vROps. 108 109 :return: A JSON representation of this Key 110 """ 111 return { 112 "name": self.name, 113 "adapterKind": self.adapter_kind, 114 "objectKind": self.object_kind, 115 "identifiers": [ 116 identifier.get_json() for identifier in self.identifiers.values() 117 ], 118 }
Get a JSON representation of this Key
Returns a JSON representation of this Key in the format required by vROps.
Returns
A JSON representation of this Key
121class IdentifierUniquenessException(Exception): 122 """Exception when two Objects of the same type have the same identifier but the `is_part_of_uniqueness` attribute 123 does not match. 124 """ 125 126 pass
Exception when two Objects of the same type have the same identifier but the is_part_of_uniqueness
attribute
does not match.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- add_note
129class Identifier: 130 """Represents a piece of data that identifies an Object.""" 131 132 def __init__( 133 self, key: str, value: str, is_part_of_uniqueness: bool = True 134 ) -> None: 135 """Creates an identifier which is used as part of an Object's identification in a :class:`Key` 136 137 Represents a piece of data that identifies an Object. If `is_part_of_uniqueness` is False, this data can 138 change over time without creating a new Object. This is primarily used for human-readable values that are useful 139 in identification purposes, but may change at times. 140 141 :param key: A key that determines which identifier the value corresponds to. 142 :param value: The value of the identifier. 143 :param is_part_of_uniqueness: Determines if this key/value pair is used in the identification process 144 """ 145 self.key = key 146 self.value = value 147 self.is_part_of_uniqueness = is_part_of_uniqueness 148 149 def __repr__(self) -> str: 150 u = "*" if self.is_part_of_uniqueness else "" 151 return f"{self.key}{u}:{self.value}" 152 153 def __key(self) -> tuple: 154 if self.is_part_of_uniqueness: 155 # 'True' is included as the second tuple because otherwise we could get a collision between a key that has 156 # a value of 'False' and a key that is not a part of uniqueness 157 return self.key, True, self.value 158 return self.key, False 159 160 def __eq__(self, other: Any) -> bool: 161 if isinstance(other, Identifier): 162 if ( 163 self.key == other.key 164 and self.is_part_of_uniqueness != other.is_part_of_uniqueness 165 ): 166 # TODO: is there a better way we can handle this case? 167 raise IdentifierUniquenessException( 168 f"Identifier '{self.key}' has an inconsistent uniqueness attribute" 169 ) 170 return self.__key() == other.__key() 171 return False 172 173 def __hash__(self) -> int: 174 return hash(self.__key()) 175 176 def get_json(self) -> dict: 177 """Get a JSON representation of this Identifier 178 179 Returns a JSON representation of this Identifier in the format required by vROps. 180 181 :return: A JSON representation of this Identifier 182 """ 183 return { 184 "key": self.key, 185 "value": self.value, 186 "isPartOfUniqueness": self.is_part_of_uniqueness, 187 }
Represents a piece of data that identifies an Object.
132 def __init__( 133 self, key: str, value: str, is_part_of_uniqueness: bool = True 134 ) -> None: 135 """Creates an identifier which is used as part of an Object's identification in a :class:`Key` 136 137 Represents a piece of data that identifies an Object. If `is_part_of_uniqueness` is False, this data can 138 change over time without creating a new Object. This is primarily used for human-readable values that are useful 139 in identification purposes, but may change at times. 140 141 :param key: A key that determines which identifier the value corresponds to. 142 :param value: The value of the identifier. 143 :param is_part_of_uniqueness: Determines if this key/value pair is used in the identification process 144 """ 145 self.key = key 146 self.value = value 147 self.is_part_of_uniqueness = is_part_of_uniqueness
Creates an identifier which is used as part of an Object's identification in a Key
Represents a piece of data that identifies an Object. If is_part_of_uniqueness
is False, this data can
change over time without creating a new Object. This is primarily used for human-readable values that are useful
in identification purposes, but may change at times.
Parameters
- key: A key that determines which identifier the value corresponds to.
- value: The value of the identifier.
- is_part_of_uniqueness: Determines if this key/value pair is used in the identification process
176 def get_json(self) -> dict: 177 """Get a JSON representation of this Identifier 178 179 Returns a JSON representation of this Identifier in the format required by vROps. 180 181 :return: A JSON representation of this Identifier 182 """ 183 return { 184 "key": self.key, 185 "value": self.value, 186 "isPartOfUniqueness": self.is_part_of_uniqueness, 187 }
Get a JSON representation of this Identifier
Returns a JSON representation of this Identifier in the format required by vROps.
Returns
A JSON representation of this Identifier
190class Object: 191 """Represents an Object (resource) in vROps. 192 193 Contains :class:`Metric`, :class:`Property`, :class:`Event`, and relationships to other Objects. Each Object is 194 identified by a unique :class:`Key`. 195 """ 196 197 def __init__(self, key: Key) -> None: 198 """Create a new Object with a given Key. 199 200 The preferred way to create a new Object is to call the :class:`Result.object` method on the :class:`Result` 201 class, which ensures that for a given key only one Object exists. 202 203 :param key: The :class:`Key` that uniquely identifies this Object 204 """ 205 self._key: Key = key 206 self._metrics: List[Metric] = [] 207 self._properties: List[Property] = [] 208 self._events: Set[Event] = set() 209 self._parents: Set[Key] = set() 210 self._children: Set[Key] = set() 211 self._updated_children: bool = False 212 213 def get_key(self) -> Key: 214 """Get a copy of the Object's Key. 215 216 An object's Key cannot change after it has been created. 217 218 :return: A copy of the object's key 219 """ 220 return copy.deepcopy(self._key) 221 222 def adapter_type(self) -> str: 223 """Get the adapter type of this object 224 225 :return: The adapter type of this object 226 """ 227 return self._key.adapter_kind 228 229 def object_type(self) -> str: 230 """Get the type of this object 231 232 :return: The type of this object 233 """ 234 return self._key.object_kind 235 236 def get_identifier_value( 237 self, identifier_key: str, default_value: Optional[str] = None 238 ) -> Optional[str]: 239 """Retrieve the value of a given identifier 240 241 :param identifier_key: Key of the identifier 242 :param default_value: An optional default value 243 :return: The value associated with the identifier. 244 If the value associated with the identifier is empty and 'default_value' is 245 provided, returns 'default_value'. 246 If the identifier does not exist, returns default_value if provided, else 'None'. 247 """ 248 return self._key.get_identifier(identifier_key, default_value) 249 250 def add_metric(self, metric: Metric) -> None: 251 """Method that adds a single Metric data point to this Object 252 253 :param metric: A :class:`Metric` data point to add to this Object 254 :return: None 255 """ 256 self._metrics.append(metric) 257 258 def add_metrics(self, metrics: List[Metric]) -> None: 259 """Method that adds a list of Metric data points to this Object 260 261 :param metrics: A list of :class:`Metric` data points to add to this Object 262 :return: None 263 """ 264 for metric in metrics: 265 self.add_metric(metric) 266 267 def with_metric(self, *args: Any, **kwargs: Any) -> None: 268 """Method that handles creating a :class:`Metric` data point, and adding to this Object. 269 270 The signature matches :class:`Metric.__init__`. 271 :return: None 272 """ 273 self.add_metric(Metric(*args, **kwargs)) 274 275 def get_metric(self, key: str) -> List[Metric]: 276 """ 277 278 :param key: Metric key of the metric to return. 279 :return: All metrics matching the given key. 280 """ 281 return list(filter(lambda metric: metric.key == key, self._metrics)) 282 283 def get_metric_values(self, key: str) -> List[float]: 284 """ 285 286 :param key: Metric key of the metric to return. 287 :return: A list of the metric values in chronological order. 288 """ 289 # find matching metrics 290 metrics = self.get_metric(key) 291 292 # sort metrics by timestamp from oldest to newest 293 metrics.sort(key=lambda metric: metric.timestamp) # type: ignore 294 295 return [m.value for m in metrics] 296 297 def get_last_metric_value(self, key: str) -> Optional[float]: 298 """ 299 300 :param key: Metric key of the metric to return. 301 :return: The latest value of the metric or None if no metric exists with the given key. 302 """ 303 metrics = self.get_metric_values(key) 304 305 if not metrics: 306 return None 307 else: 308 return metrics[-1] 309 310 def add_property(self, property_: Property) -> None: 311 """Method that adds a single Property value to this Object 312 313 :param property_: A :class:`Property` value to add to this Object 314 :return: None 315 """ 316 self._properties.append(property_) 317 318 def add_properties(self, properties: List[Property]) -> None: 319 """Method that adds a list of Property values to this Object 320 321 :param properties: A list of :class:`Property` values to add to this Object 322 :return: None 323 """ 324 for property_ in properties: 325 self.add_property(property_) 326 327 def with_property(self, *args: Any, **kwargs: Any) -> None: 328 """Method that handles creating a :class:`Property` value, and adding to this Object. 329 330 The signature matches :class:`Property.__init__`. 331 :return: None 332 """ 333 self.add_property(Property(*args, **kwargs)) 334 335 def get_property(self, key: str) -> List[Property]: 336 """ 337 338 :param key: Property key of the property to return. 339 :return: All properties matching the given key 340 """ 341 return list(filter(lambda property_: property_.key == key, self._properties)) 342 343 def get_property_values(self, key: str) -> List[str]: 344 """ 345 346 :param key: Property key of the property to return. 347 :return: A list of the property values in chronological order. 348 """ 349 # find matching properties 350 properties = self.get_property(key) 351 352 # sort properties by timestamp from oldest to newest 353 properties.sort(key=lambda property_: property_.timestamp) # type: ignore 354 355 return [p.value for p in properties] 356 357 def get_last_property_value(self, key: str) -> Optional[str | float]: 358 """ 359 360 :param key: Property key of the property to return. 361 :return: The latest value of the property or None if no property exists with the given key. 362 """ 363 properties = self.get_property_values(key) 364 365 if not properties: 366 return None 367 else: 368 return properties[-1] 369 370 def add_event(self, event: Event) -> None: 371 """Method that adds a single Event to this Object 372 373 :param event: An :class:`Event` to add to this Object 374 :return: None 375 """ 376 self._events.add(event) 377 378 def add_events(self, events: List[Event]) -> None: 379 """Method that adds a list of Events to this Object 380 381 :param events: A list of :class:`Event` to add to this Object 382 :return: None 383 """ 384 for event in events: 385 self.add_event(event) 386 387 def with_event(self, *args: Any, **kwargs: Any) -> None: 388 """Method that handles creating an :class:`Event`, and adding to this Object. 389 390 The signature matches :class:`Event.__init__`. 391 :return: None 392 """ 393 self.add_event(Event(*args, **kwargs)) 394 395 def add_parent(self, parent: Object) -> None: 396 """Method that adds a parent Object to this Object. 397 398 This Object will also be added as a child to the parent. 399 400 Relationship cycles are not permitted. 401 402 :param parent: Parent :class:`Object` 403 :return: None 404 """ 405 self._parents.add(parent._key) 406 parent._children.add(self._key) 407 408 def add_parents(self, parents: List[Object]) -> None: 409 """Method that adds a list of parent Objects to this Object. 410 411 This Object will also be added as a child to each of the parents. 412 413 Relationship cycles are not permitted. 414 415 :param parents: A list of parent :class:`Object` 416 :return: None 417 """ 418 for parent in parents: 419 self.add_parent(parent) 420 421 def get_parents(self) -> Set[Key]: 422 """ 423 :return: A set of all object keys that are parents of this object 424 """ 425 return self._parents 426 427 def add_child(self, child: Object) -> None: 428 """Method that adds a child Object to this Object. 429 430 This Object will also be added as a parent to the child. 431 432 Relationship cycles are not permitted. 433 434 :param child: Child :class:`Object` 435 :return: None 436 """ 437 self._updated_children = True 438 self._children.add(child._key) 439 child._parents.add(self._key) 440 441 def add_children(self, children: List[Object]) -> None: 442 """Method that adds a list of child Objects to this Object. 443 444 This Object will also be added as a parent to each of the children. 445 446 Relationship cycles are not permitted. 447 448 :param children: A list of child :class:`Object` 449 :return: None 450 """ 451 # We want to set this even in the case where the list is empty 452 self._updated_children = True 453 for child in children: 454 self.add_child(child) 455 456 def get_children(self) -> Set[Key]: 457 """ 458 :return: A set of all object keys that are children of this object 459 """ 460 return self._children 461 462 def has_content(self) -> bool: 463 """ 464 :return: True if the object contains any metrics, properties or events; False otherwise. 465 """ 466 return bool(self._metrics) or bool(self._properties) or bool(self._events) 467 468 def get_json(self) -> dict: 469 """Get a JSON representation of this Object 470 471 Returns a JSON representation of this Object in the format required by vROps. 472 473 :return: A JSON representation of this Object 474 """ 475 return { 476 "key": self._key.get_json(), 477 "metrics": [metric.get_json() for metric in self._metrics], 478 "properties": [prop.get_json() for prop in self._properties], 479 "events": [event.get_json() for event in self._events], 480 }
Represents an Object (resource) in vROps.
Contains Metric
, Property
, Event
, and relationships to other Objects. Each Object is
identified by a unique Key
.
197 def __init__(self, key: Key) -> None: 198 """Create a new Object with a given Key. 199 200 The preferred way to create a new Object is to call the :class:`Result.object` method on the :class:`Result` 201 class, which ensures that for a given key only one Object exists. 202 203 :param key: The :class:`Key` that uniquely identifies this Object 204 """ 205 self._key: Key = key 206 self._metrics: List[Metric] = [] 207 self._properties: List[Property] = [] 208 self._events: Set[Event] = set() 209 self._parents: Set[Key] = set() 210 self._children: Set[Key] = set() 211 self._updated_children: bool = False
Create a new Object with a given Key.
The preferred way to create a new Object is to call the Result.object
method on the Result
class, which ensures that for a given key only one Object exists.
Parameters
- key: The
Key
that uniquely identifies this Object
213 def get_key(self) -> Key: 214 """Get a copy of the Object's Key. 215 216 An object's Key cannot change after it has been created. 217 218 :return: A copy of the object's key 219 """ 220 return copy.deepcopy(self._key)
Get a copy of the Object's Key.
An object's Key cannot change after it has been created.
Returns
A copy of the object's key
222 def adapter_type(self) -> str: 223 """Get the adapter type of this object 224 225 :return: The adapter type of this object 226 """ 227 return self._key.adapter_kind
Get the adapter type of this object
Returns
The adapter type of this object
229 def object_type(self) -> str: 230 """Get the type of this object 231 232 :return: The type of this object 233 """ 234 return self._key.object_kind
Get the type of this object
Returns
The type of this object
236 def get_identifier_value( 237 self, identifier_key: str, default_value: Optional[str] = None 238 ) -> Optional[str]: 239 """Retrieve the value of a given identifier 240 241 :param identifier_key: Key of the identifier 242 :param default_value: An optional default value 243 :return: The value associated with the identifier. 244 If the value associated with the identifier is empty and 'default_value' is 245 provided, returns 'default_value'. 246 If the identifier does not exist, returns default_value if provided, else 'None'. 247 """ 248 return self._key.get_identifier(identifier_key, default_value)
Retrieve the value of a given identifier
Parameters
- identifier_key: Key of the identifier
- default_value: An optional default value
Returns
The value associated with the identifier. If the value associated with the identifier is empty and 'default_value' is provided, returns 'default_value'. If the identifier does not exist, returns default_value if provided, else 'None'.
250 def add_metric(self, metric: Metric) -> None: 251 """Method that adds a single Metric data point to this Object 252 253 :param metric: A :class:`Metric` data point to add to this Object 254 :return: None 255 """ 256 self._metrics.append(metric)
Method that adds a single Metric data point to this Object
Parameters
- metric: A
Metric
data point to add to this Object
Returns
None
258 def add_metrics(self, metrics: List[Metric]) -> None: 259 """Method that adds a list of Metric data points to this Object 260 261 :param metrics: A list of :class:`Metric` data points to add to this Object 262 :return: None 263 """ 264 for metric in metrics: 265 self.add_metric(metric)
Method that adds a list of Metric data points to this Object
Parameters
- metrics: A list of
Metric
data points to add to this Object
Returns
None
267 def with_metric(self, *args: Any, **kwargs: Any) -> None: 268 """Method that handles creating a :class:`Metric` data point, and adding to this Object. 269 270 The signature matches :class:`Metric.__init__`. 271 :return: None 272 """ 273 self.add_metric(Metric(*args, **kwargs))
Method that handles creating a Metric
data point, and adding to this Object.
The signature matches Metric.__init__
.
Returns
None
275 def get_metric(self, key: str) -> List[Metric]: 276 """ 277 278 :param key: Metric key of the metric to return. 279 :return: All metrics matching the given key. 280 """ 281 return list(filter(lambda metric: metric.key == key, self._metrics))
Parameters
- key: Metric key of the metric to return.
Returns
All metrics matching the given key.
283 def get_metric_values(self, key: str) -> List[float]: 284 """ 285 286 :param key: Metric key of the metric to return. 287 :return: A list of the metric values in chronological order. 288 """ 289 # find matching metrics 290 metrics = self.get_metric(key) 291 292 # sort metrics by timestamp from oldest to newest 293 metrics.sort(key=lambda metric: metric.timestamp) # type: ignore 294 295 return [m.value for m in metrics]
Parameters
- key: Metric key of the metric to return.
Returns
A list of the metric values in chronological order.
297 def get_last_metric_value(self, key: str) -> Optional[float]: 298 """ 299 300 :param key: Metric key of the metric to return. 301 :return: The latest value of the metric or None if no metric exists with the given key. 302 """ 303 metrics = self.get_metric_values(key) 304 305 if not metrics: 306 return None 307 else: 308 return metrics[-1]
Parameters
- key: Metric key of the metric to return.
Returns
The latest value of the metric or None if no metric exists with the given key.
310 def add_property(self, property_: Property) -> None: 311 """Method that adds a single Property value to this Object 312 313 :param property_: A :class:`Property` value to add to this Object 314 :return: None 315 """ 316 self._properties.append(property_)
Method that adds a single Property value to this Object
Parameters
- property_: A
Property
value to add to this Object
Returns
None
318 def add_properties(self, properties: List[Property]) -> None: 319 """Method that adds a list of Property values to this Object 320 321 :param properties: A list of :class:`Property` values to add to this Object 322 :return: None 323 """ 324 for property_ in properties: 325 self.add_property(property_)
Method that adds a list of Property values to this Object
Parameters
- properties: A list of
Property
values to add to this Object
Returns
None
327 def with_property(self, *args: Any, **kwargs: Any) -> None: 328 """Method that handles creating a :class:`Property` value, and adding to this Object. 329 330 The signature matches :class:`Property.__init__`. 331 :return: None 332 """ 333 self.add_property(Property(*args, **kwargs))
Method that handles creating a Property
value, and adding to this Object.
The signature matches Property.__init__
.
Returns
None
335 def get_property(self, key: str) -> List[Property]: 336 """ 337 338 :param key: Property key of the property to return. 339 :return: All properties matching the given key 340 """ 341 return list(filter(lambda property_: property_.key == key, self._properties))
Parameters
- key: Property key of the property to return.
Returns
All properties matching the given key
343 def get_property_values(self, key: str) -> List[str]: 344 """ 345 346 :param key: Property key of the property to return. 347 :return: A list of the property values in chronological order. 348 """ 349 # find matching properties 350 properties = self.get_property(key) 351 352 # sort properties by timestamp from oldest to newest 353 properties.sort(key=lambda property_: property_.timestamp) # type: ignore 354 355 return [p.value for p in properties]
Parameters
- key: Property key of the property to return.
Returns
A list of the property values in chronological order.
357 def get_last_property_value(self, key: str) -> Optional[str | float]: 358 """ 359 360 :param key: Property key of the property to return. 361 :return: The latest value of the property or None if no property exists with the given key. 362 """ 363 properties = self.get_property_values(key) 364 365 if not properties: 366 return None 367 else: 368 return properties[-1]
Parameters
- key: Property key of the property to return.
Returns
The latest value of the property or None if no property exists with the given key.
370 def add_event(self, event: Event) -> None: 371 """Method that adds a single Event to this Object 372 373 :param event: An :class:`Event` to add to this Object 374 :return: None 375 """ 376 self._events.add(event)
Method that adds a single Event to this Object
Parameters
- event: An
Event
to add to this Object
Returns
None
378 def add_events(self, events: List[Event]) -> None: 379 """Method that adds a list of Events to this Object 380 381 :param events: A list of :class:`Event` to add to this Object 382 :return: None 383 """ 384 for event in events: 385 self.add_event(event)
Method that adds a list of Events to this Object
Parameters
- events: A list of
Event
to add to this Object
Returns
None
387 def with_event(self, *args: Any, **kwargs: Any) -> None: 388 """Method that handles creating an :class:`Event`, and adding to this Object. 389 390 The signature matches :class:`Event.__init__`. 391 :return: None 392 """ 393 self.add_event(Event(*args, **kwargs))
Method that handles creating an Event
, and adding to this Object.
The signature matches Event.__init__
.
Returns
None
395 def add_parent(self, parent: Object) -> None: 396 """Method that adds a parent Object to this Object. 397 398 This Object will also be added as a child to the parent. 399 400 Relationship cycles are not permitted. 401 402 :param parent: Parent :class:`Object` 403 :return: None 404 """ 405 self._parents.add(parent._key) 406 parent._children.add(self._key)
Method that adds a parent Object to this Object.
This Object will also be added as a child to the parent.
Relationship cycles are not permitted.
Parameters
- parent: Parent
Object
Returns
None
408 def add_parents(self, parents: List[Object]) -> None: 409 """Method that adds a list of parent Objects to this Object. 410 411 This Object will also be added as a child to each of the parents. 412 413 Relationship cycles are not permitted. 414 415 :param parents: A list of parent :class:`Object` 416 :return: None 417 """ 418 for parent in parents: 419 self.add_parent(parent)
Method that adds a list of parent Objects to this Object.
This Object will also be added as a child to each of the parents.
Relationship cycles are not permitted.
Parameters
- parents: A list of parent
Object
Returns
None
421 def get_parents(self) -> Set[Key]: 422 """ 423 :return: A set of all object keys that are parents of this object 424 """ 425 return self._parents
Returns
A set of all object keys that are parents of this object
427 def add_child(self, child: Object) -> None: 428 """Method that adds a child Object to this Object. 429 430 This Object will also be added as a parent to the child. 431 432 Relationship cycles are not permitted. 433 434 :param child: Child :class:`Object` 435 :return: None 436 """ 437 self._updated_children = True 438 self._children.add(child._key) 439 child._parents.add(self._key)
Method that adds a child Object to this Object.
This Object will also be added as a parent to the child.
Relationship cycles are not permitted.
Parameters
- child: Child
Object
Returns
None
441 def add_children(self, children: List[Object]) -> None: 442 """Method that adds a list of child Objects to this Object. 443 444 This Object will also be added as a parent to each of the children. 445 446 Relationship cycles are not permitted. 447 448 :param children: A list of child :class:`Object` 449 :return: None 450 """ 451 # We want to set this even in the case where the list is empty 452 self._updated_children = True 453 for child in children: 454 self.add_child(child)
Method that adds a list of child Objects to this Object.
This Object will also be added as a parent to each of the children.
Relationship cycles are not permitted.
Parameters
- children: A list of child
Object
Returns
None
456 def get_children(self) -> Set[Key]: 457 """ 458 :return: A set of all object keys that are children of this object 459 """ 460 return self._children
Returns
A set of all object keys that are children of this object
462 def has_content(self) -> bool: 463 """ 464 :return: True if the object contains any metrics, properties or events; False otherwise. 465 """ 466 return bool(self._metrics) or bool(self._properties) or bool(self._events)
Returns
True if the object contains any metrics, properties or events; False otherwise.
468 def get_json(self) -> dict: 469 """Get a JSON representation of this Object 470 471 Returns a JSON representation of this Object in the format required by vROps. 472 473 :return: A JSON representation of this Object 474 """ 475 return { 476 "key": self._key.get_json(), 477 "metrics": [metric.get_json() for metric in self._metrics], 478 "properties": [prop.get_json() for prop in self._properties], 479 "events": [event.get_json() for event in self._events], 480 }
Get a JSON representation of this Object
Returns a JSON representation of this Object in the format required by vROps.
Returns
A JSON representation of this Object