2
0
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:
Peter Hamilton
2019-10-31 17:50:58 -04:00
committed by Peter Hamilton
parent cd1079afd5
commit 616e683370
2 changed files with 580 additions and 0 deletions

View File

@@ -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.