mirror of
https://github.com/openkmip/pykmip
synced 2025-12-21 10:43:15 +00:00
Add support for the CurrentAttribute structure
This change adds support for the CurrentAttribute structure added in KMIP 2.0. The CurrentAttribute structure is a basic container structure that contains a single attribute instance for use by attribute operations. A new unit test suite has been added to cover the new additions. Partially implements #547
This commit is contained in:
committed by
Peter Hamilton
parent
cd1079afd5
commit
616e683370
@@ -175,6 +175,187 @@ class Attribute(Struct):
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class CurrentAttribute(primitives.Struct):
|
||||
"""
|
||||
A structure containing a single attribute.
|
||||
|
||||
This is intended for use with KMIP 2.0+.
|
||||
|
||||
Attributes:
|
||||
attribute: An attribute instance.
|
||||
"""
|
||||
|
||||
def __init__(self, attribute=None):
|
||||
"""
|
||||
Construct a CurrentAttribute structure.
|
||||
|
||||
Args:
|
||||
attribute (struct): An attribute structure of varying type.
|
||||
Defaults to None. Required for read/write.
|
||||
"""
|
||||
super(CurrentAttribute, self).__init__(
|
||||
tag=enums.Tags.CURRENT_ATTRIBUTE
|
||||
)
|
||||
|
||||
self._factory = AttributeValueFactory()
|
||||
|
||||
self._attribute = None
|
||||
|
||||
self.attribute = attribute
|
||||
|
||||
@property
|
||||
def attribute(self):
|
||||
if self._attribute:
|
||||
return self._attribute
|
||||
return None
|
||||
|
||||
@attribute.setter
|
||||
def attribute(self, value):
|
||||
if value is None:
|
||||
self._attribute = None
|
||||
elif isinstance(value, primitives.Base):
|
||||
if enums.is_attribute(value.tag):
|
||||
self._attribute = value
|
||||
else:
|
||||
raise TypeError(
|
||||
"The attribute must be a supported attribute type."
|
||||
)
|
||||
else:
|
||||
raise TypeError(
|
||||
"The attribute must be a Base object, not a {}.".format(
|
||||
type(value)
|
||||
)
|
||||
)
|
||||
|
||||
def read(self, input_buffer, kmip_version=enums.KMIPVersion.KMIP_2_0):
|
||||
"""
|
||||
Read the data stream and decode the CurrentAttribute structure into
|
||||
its parts.
|
||||
|
||||
Args:
|
||||
input_buffer (stream): A data stream containing encoded object
|
||||
data, supporting a read method.
|
||||
kmip_version (enum): A KMIPVersion enumeration defining the KMIP
|
||||
version with which the object will be decoded. Optional,
|
||||
defaults to KMIP 2.0.
|
||||
|
||||
Raises:
|
||||
AttributeNotSupported: Raised when an invalid value is decoded as
|
||||
the attribute from the encoding.
|
||||
InvalidKmipEncoding: Raised if the attribute is missing from the
|
||||
encoding.
|
||||
VersionNotSupported: Raised when a KMIP version is provided that
|
||||
does not support the CurrentAttribute structure.
|
||||
"""
|
||||
if kmip_version < enums.KMIPVersion.KMIP_2_0:
|
||||
raise exceptions.VersionNotSupported(
|
||||
"KMIP {} does not support the CurrentAttribute object.".format(
|
||||
kmip_version.value
|
||||
)
|
||||
)
|
||||
|
||||
super(CurrentAttribute, self).read(
|
||||
input_buffer,
|
||||
kmip_version=kmip_version
|
||||
)
|
||||
local_buffer = BytearrayStream(input_buffer.read(self.length))
|
||||
|
||||
if len(local_buffer) < 3:
|
||||
raise exceptions.InvalidKmipEncoding(
|
||||
"The CurrentAttribute encoding is missing the attribute field."
|
||||
)
|
||||
tag = struct.unpack('!I', b'\x00' + local_buffer.peek(3))[0]
|
||||
if enums.is_enum_value(enums.Tags, tag):
|
||||
tag = enums.Tags(tag)
|
||||
if enums.is_attribute(tag, kmip_version=kmip_version):
|
||||
value = self._factory.create_attribute_value_by_enum(tag, None)
|
||||
value.read(local_buffer, kmip_version=kmip_version)
|
||||
self._attribute = value
|
||||
else:
|
||||
raise exceptions.AttributeNotSupported(
|
||||
"Attribute {} is not supported by KMIP {}.".format(
|
||||
tag.name,
|
||||
kmip_version.value
|
||||
)
|
||||
)
|
||||
else:
|
||||
raise exceptions.InvalidKmipEncoding(
|
||||
"The CurrentAttribute encoding is missing the attribute field."
|
||||
)
|
||||
|
||||
self.is_oversized(local_buffer)
|
||||
|
||||
def write(self, output_buffer, kmip_version=enums.KMIPVersion.KMIP_2_0):
|
||||
"""
|
||||
Write the CurrentAttribute structure encoding to the data stream.
|
||||
|
||||
Args:
|
||||
output_buffer (stream): A data stream in which to encode
|
||||
CurrentAttribute structure data, supporting a write method.
|
||||
kmip_version (enum): A KMIPVersion enumeration defining the KMIP
|
||||
version with which the object will be encoded. Optional,
|
||||
defaults to KMIP 2.0.
|
||||
|
||||
Raises:
|
||||
AttributeNotSupported: Raised if an unsupported attribute is
|
||||
found while encoding.
|
||||
InvalidField: Raised when the attribute is unspecified at write
|
||||
time.
|
||||
VersionNotSupported: Raised when a KMIP version is provided that
|
||||
does not support the CurrentAttribute object.
|
||||
"""
|
||||
if kmip_version < enums.KMIPVersion.KMIP_2_0:
|
||||
raise exceptions.VersionNotSupported(
|
||||
"KMIP {} does not support the CurrentAttribute object.".format(
|
||||
kmip_version.value
|
||||
)
|
||||
)
|
||||
|
||||
local_buffer = BytearrayStream()
|
||||
|
||||
if self._attribute:
|
||||
tag = self._attribute.tag
|
||||
if not enums.is_attribute(tag, kmip_version=kmip_version):
|
||||
raise exceptions.AttributeNotSupported(
|
||||
"Attribute {} is not supported by KMIP {}.".format(
|
||||
tag.name,
|
||||
kmip_version.value
|
||||
)
|
||||
)
|
||||
self._attribute.write(local_buffer, kmip_version=kmip_version)
|
||||
else:
|
||||
raise exceptions.InvalidField(
|
||||
"The CurrentAttribute object is missing the attribute field."
|
||||
)
|
||||
|
||||
self.length = local_buffer.length()
|
||||
super(CurrentAttribute, self).write(
|
||||
output_buffer,
|
||||
kmip_version=kmip_version
|
||||
)
|
||||
output_buffer.write(local_buffer.buffer)
|
||||
|
||||
def __repr__(self):
|
||||
return "CurrentAttribute(attribute={})".format(repr(self.attribute))
|
||||
|
||||
def __str__(self):
|
||||
value = '"attribute": {}'.format(repr(self.attribute))
|
||||
return '{' + value + '}'
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, CurrentAttribute):
|
||||
return NotImplemented
|
||||
elif self.attribute != other.attribute:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
if isinstance(other, CurrentAttribute):
|
||||
return not (self == other)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class AttributeReference(primitives.Struct):
|
||||
"""
|
||||
A structure containing reference information for an attribute.
|
||||
|
||||
Reference in New Issue
Block a user