Skip to content

Commit f333c40

Browse files
authored
Fixed returning of write-only properties in mock support (#2126)
Details: * Added a class attribute 'wo_properties' to any resource handler classes in zhmcclient.mock._urihandler.py with the list of write-only property names. * Used the wo_properties class attribute to eliminate write-only properties from being returned in the following cases: - "Get <resource> Properties" operation without "properties" query parm - "Get <resource> Properties" operation with "properties" query parm - "List" operations with "additional-properties" query parm Signed-off-by: Andreas Maier <maiera@de.ibm.com>
1 parent 7b4f037 commit f333c40

2 files changed

Lines changed: 90 additions & 44 deletions

File tree

changes/2122.fix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed the issue that the zhmcclient mock support returned write-only properties
2+
of resources in Get and List operations.

zhmcclient/mock/_urihandler.py

Lines changed: 88 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,43 @@ def prop_copy(prop):
465465
return copy.deepcopy(prop)
466466

467467

468+
def without_names(names, remove_names):
469+
"""
470+
Return a copy of the input names, with the specified names removed.
471+
472+
Parameters:
473+
names (iterable of str): Input names
474+
remove_names (iterable of str): Names to be removed
475+
"""
476+
ret_names = []
477+
for name in names:
478+
if name in remove_names:
479+
continue
480+
ret_names.append(name)
481+
return ret_names
482+
483+
484+
def get_additional_properties(query_parms, wo_properties=None):
485+
"""
486+
Return the names of any additional-properties specified in the query
487+
parameter, not including the specified write-only properties.
488+
489+
The 'additional-properties' query parameter is remmoved from the
490+
query_parms parameter, if present.
491+
492+
Parameters:
493+
query_parms (dict): Query parameters
494+
wo_properties (iterable of str): Write-only properties
495+
"""
496+
if 'additional-properties' in query_parms:
497+
add_props = query_parms.pop('additional-properties').split(',')
498+
if wo_properties:
499+
add_props = without_names(add_props, wo_properties)
500+
else:
501+
add_props = []
502+
return add_props
503+
504+
468505
class UriHandler:
469506
"""
470507
Handle HTTP methods against a set of known URIs and invoke respective
@@ -531,6 +568,10 @@ class GenericGetPropertiesHandler:
531568
Handler class for generic get of resource properties.
532569
"""
533570

571+
# Write-only properties.
572+
# Is overridden by derived classes.
573+
wo_properties = []
574+
534575
# List of supported query parameters for the 'Get Properties' operation
535576
# of the resource type using this class.
536577
# Must be overridden in the derived resource handler class, if it supports
@@ -554,22 +595,28 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
554595
new_exc.__cause__ = None
555596
raise new_exc # zhmcclient.mock.InvalidResourceError
556597

557-
subset_pnames = query_parms.get('properties', None)
558-
if subset_pnames:
559-
subset_pnames = subset_pnames.split(',')
560-
ret_props = {}
561-
for pname in subset_pnames:
562-
try:
563-
ret_props[pname] = resource.properties[pname]
564-
except KeyError:
565-
new_exc = BadRequestError(
566-
method, uri, reason=14,
567-
message=f"Invalid property {pname!r} in 'properties' "
568-
f"query parameter for resource with URI {uri!r}")
569-
new_exc.__cause__ = None
570-
raise new_exc # BadRequestError
571-
return ret_props
572-
return properties_copy(resource.properties)
598+
pnames = query_parms.get('properties', None)
599+
if pnames:
600+
pnames = pnames.split(',')
601+
else:
602+
pnames = resource.properties.keys()
603+
ret_props = {}
604+
for pname in pnames:
605+
if pname in cls.wo_properties:
606+
# Do not return write-only properties .
607+
# In case a write-only property is specified in the 'properties'
608+
# query parm, it should be ignored without raising an error.
609+
continue
610+
try:
611+
ret_props[pname] = resource.properties[pname]
612+
except KeyError:
613+
new_exc = BadRequestError(
614+
method, uri, reason=14,
615+
message=f"Invalid property {pname!r} in 'properties' "
616+
f"query parameter for resource with URI {uri!r}")
617+
new_exc.__cause__ = None
618+
raise new_exc # BadRequestError
619+
return ret_props
573620

574621

575622
class GenericUpdatePropertiesHandler:
@@ -896,10 +943,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
896943
uri, query_parms = parse_query_parms(method, uri)
897944
check_invalid_query_parms(
898945
method, uri, query_parms, cls.valid_query_parms_get)
899-
if 'additional-properties' in query_parms:
900-
add_props = query_parms.pop('additional-properties').split(',')
901-
else:
902-
add_props = []
946+
add_props = get_additional_properties(
947+
query_parms, PartitionHandler.wo_properties)
903948
filter_args = query_parms
904949

905950
result_partitions = []
@@ -951,10 +996,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
951996
uri, query_parms = parse_query_parms(method, uri)
952997
check_invalid_query_parms(
953998
method, uri, query_parms, cls.valid_query_parms_get)
954-
if 'additional-properties' in query_parms:
955-
add_props = query_parms.pop('additional-properties').split(',')
956-
else:
957-
add_props = []
999+
add_props = get_additional_properties(
1000+
query_parms, LparHandler.wo_properties)
9581001
filter_args = query_parms
9591002

9601003
result_lpars = []
@@ -1011,10 +1054,9 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
10111054
uri, query_parms = parse_query_parms(method, uri)
10121055
check_invalid_query_parms(
10131056
method, uri, query_parms, cls.valid_query_parms_get)
1014-
if 'additional-properties' in query_parms:
1015-
add_props = query_parms.pop('additional-properties').split(',')
1016-
else:
1017-
add_props = []
1057+
add_props = get_additional_properties(
1058+
query_parms, PartitionHandler.wo_properties)
1059+
10181060
filter_args = query_parms
10191061

10201062
result_adapters = []
@@ -1159,6 +1201,8 @@ class UserHandler(GenericGetPropertiesHandler):
11591201
Handler class for HTTP methods on single User resource.
11601202
"""
11611203

1204+
wo_properties = ["password"]
1205+
11621206
@staticmethod
11631207
def post(method, hmc, uri, uri_parms, body, logon_required,
11641208
wait_for_completion):
@@ -1788,6 +1832,8 @@ class LdapServerDefinitionHandler(GenericGetPropertiesHandler,
17881832
Handler class for HTTP methods on single LdapServerDefinition resource.
17891833
"""
17901834

1835+
wo_properties = ["bind-password"]
1836+
17911837
@staticmethod
17921838
def post(method, hmc, uri, uri_parms, body, logon_required,
17931839
wait_for_completion):
@@ -1959,6 +2005,8 @@ class SSOServerDefinitionHandler(GenericGetPropertiesHandler,
19592005
Handler class for HTTP methods on single SSOServerDefinition resource.
19602006
"""
19612007

2008+
wo_properties = ["client-secret"]
2009+
19622010
@staticmethod
19632011
def post(method, hmc, uri, uri_parms, body, logon_required,
19642012
wait_for_completion):
@@ -3483,10 +3531,7 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
34833531
uri, query_parms = parse_query_parms(method, uri)
34843532
check_invalid_query_parms(
34853533
method, uri, query_parms, cls.valid_query_parms_get)
3486-
if 'additional-properties' in query_parms:
3487-
add_props = query_parms.pop('additional-properties').split(',')
3488-
else:
3489-
add_props = []
3534+
add_props = get_additional_properties(query_parms)
34903535
filter_args = query_parms
34913536

34923537
cpc_oid = uri_parms[0]
@@ -3901,10 +3946,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
39013946
uri, query_parms = parse_query_parms(method, uri)
39023947
check_invalid_query_parms(
39033948
method, uri, query_parms, cls.valid_query_parms_get)
3904-
if 'additional-properties' in query_parms:
3905-
add_props = query_parms.pop('additional-properties').split(',')
3906-
else:
3907-
add_props = []
3949+
add_props = get_additional_properties(
3950+
query_parms, PartitionHandler.wo_properties)
39083951
filter_args = query_parms
39093952

39103953
cpc_oid = uri_parms[0]
@@ -4147,6 +4190,8 @@ class PartitionHandler(GenericGetPropertiesHandler,
41474190

41484191
valid_query_parms_get = ['properties']
41494192

4193+
wo_properties = ["boot-ftp-password", "ssc-master-pw"]
4194+
41504195
# TODO: Add check_valid_cpc_status() in Update Partition Properties
41514196
# TODO: Add check_partition_status(transitional) in Update Partition Props
41524197
# TODO: Add check whether properties are modifiable in Update Part. Props
@@ -4919,10 +4964,7 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
49194964
uri, query_parms = parse_query_parms(method, uri)
49204965
check_invalid_query_parms(
49214966
method, uri, query_parms, cls.valid_query_parms_get)
4922-
if 'additional-properties' in query_parms:
4923-
add_props = query_parms.pop('additional-properties').split(',')
4924-
else:
4925-
add_props = []
4967+
add_props = get_additional_properties(query_parms)
49264968
filter_args = query_parms
49274969

49284970
cpc_oid = uri_parms[0]
@@ -5926,6 +5968,8 @@ class LparHandler(GenericGetPropertiesHandler):
59265968

59275969
valid_query_parms_get = ['properties', 'cached-acceptable', 'group-uri']
59285970

5971+
wo_properties = ["ssc-master-pw"]
5972+
59295973
@staticmethod
59305974
def post(method, hmc, uri, uri_parms, body, logon_required,
59315975
wait_for_completion):
@@ -6588,10 +6632,8 @@ def get(cls, method, hmc, uri, uri_parms, logon_required):
65886632
uri, query_parms = parse_query_parms(method, uri)
65896633
check_invalid_query_parms(
65906634
method, uri, query_parms, cls.valid_query_parms_get)
6591-
if 'additional-properties' in query_parms:
6592-
add_props = query_parms.pop('additional-properties').split(',')
6593-
else:
6594-
add_props = []
6635+
add_props = get_additional_properties(
6636+
query_parms, ImageActProfileHandler.wo_properties)
65956637
filter_args = query_parms
65966638

65976639
cpc_oid = uri_parms[0]
@@ -6620,6 +6662,8 @@ class ImageActProfileHandler(GenericGetPropertiesHandler,
66206662

66216663
valid_query_parms_get = ['properties', 'cached-acceptable']
66226664

6665+
wo_properties = ["ssc-master-pw", "zaware-master-pw"]
6666+
66236667

66246668
class LoadActProfilesHandler:
66256669
"""

0 commit comments

Comments
 (0)