Skip to content

Commit 9150013

Browse files
committed
share: Import utils
Nothing uses these but they will soon. This is mostly imported wholesale from manilaclient, with some changes to reduce duplication and align the base test class with similar base test classes used for other services. Change-Id: Id546910e6e9d0ab164b5260561a28779530194a7 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
1 parent ef5a02f commit 9150013

3 files changed

Lines changed: 1757 additions & 0 deletions

File tree

openstackclient/common/envvars.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from openstackclient.i18n import _
1616

1717

18+
# TODO(stephenfin): Move this to osc-lib
1819
def bool_from_str(value: bool | str, strict: bool = False) -> bool:
1920
true_strings = ('1', 't', 'true', 'on', 'y', 'yes')
2021
false_strings = ('0', 'f', 'false', 'off', 'n', 'no')

openstackclient/share/utils.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Copyright 2019 Red Hat, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
from collections.abc import Sequence
16+
import logging
17+
from typing import Any
18+
19+
from manilaclient.common import constants
20+
from osc_lib import exceptions
21+
22+
from openstackclient.common import envvars
23+
from openstackclient.i18n import _
24+
25+
LOG = logging.getLogger(__name__)
26+
27+
28+
def extract_key_value_options(
29+
pairs: dict[str, str] | None,
30+
) -> dict[str, str]:
31+
result_dict = {}
32+
duplicate_options = []
33+
pairs = pairs or {}
34+
35+
for attr, value in pairs.items():
36+
if attr not in result_dict:
37+
result_dict[attr] = value
38+
else:
39+
duplicate_options.append(attr)
40+
41+
if pairs and len(duplicate_options) > 0:
42+
duplicate_str = ', '.join(duplicate_options)
43+
msg = f"Following options were duplicated: {duplicate_str}"
44+
raise exceptions.CommandError(msg)
45+
46+
return result_dict
47+
48+
49+
def format_properties(properties: dict[str, str]) -> str:
50+
formatted_data = []
51+
52+
for item in properties:
53+
formatted_data.append(f"{item} : {properties[item]}")
54+
return "\n".join(formatted_data)
55+
56+
57+
def extract_properties(properties: list[str]) -> dict[str, str]:
58+
result_dict = {}
59+
for item in properties:
60+
try:
61+
(key, value) = item.split('=', 1)
62+
if key in result_dict:
63+
raise exceptions.CommandError(
64+
f"Argument '{key}' is specified twice."
65+
)
66+
else:
67+
result_dict[key] = value
68+
except ValueError:
69+
raise exceptions.CommandError(
70+
"Parsing error, expected format 'key=value' for " + item
71+
)
72+
return result_dict
73+
74+
75+
def extract_extra_specs(
76+
extra_specs: dict[str, Any],
77+
specs_to_add: list[str],
78+
bool_specs: Sequence[str] = constants.BOOL_SPECS,
79+
) -> dict[str, Any]:
80+
try:
81+
for item in specs_to_add:
82+
(key, value) = item.split('=', 1)
83+
if key in extra_specs:
84+
msg = f"Argument '{key}' value specified twice."
85+
raise exceptions.CommandError(msg)
86+
elif key in bool_specs:
87+
if envvars.bool_from_str(value):
88+
extra_specs[key] = value.capitalize()
89+
else:
90+
msg = (
91+
f"Argument '{key}' is of boolean "
92+
f"type and has invalid value: {value!s}"
93+
)
94+
raise exceptions.CommandError(msg)
95+
else:
96+
extra_specs[key] = value
97+
except ValueError:
98+
msg = _("Wrong format: specs should be key=value pairs.")
99+
raise exceptions.CommandError(msg)
100+
return extra_specs
101+
102+
103+
def extract_group_specs(
104+
extra_specs: dict[str, Any], specs_to_add: list[str]
105+
) -> dict[str, Any]:
106+
return extract_extra_specs(
107+
extra_specs, specs_to_add, constants.GROUP_BOOL_SPECS
108+
)
109+
110+
111+
def format_column_headers(columns: list[str]) -> list[str]:
112+
column_headers = []
113+
for column in columns:
114+
column_headers.append(
115+
column.replace('_', ' ').title().replace('Id', 'ID')
116+
)
117+
return column_headers
118+
119+
120+
def format_share_group_type(
121+
share_group_type: Any, formatter: str = 'table'
122+
) -> dict[str, Any]:
123+
printable_share_group_type = share_group_type._info
124+
125+
is_public = printable_share_group_type.pop('is_public')
126+
127+
printable_share_group_type['visibility'] = (
128+
'public' if is_public else 'private'
129+
)
130+
131+
if formatter == 'table':
132+
printable_share_group_type['group_specs'] = format_properties(
133+
share_group_type.group_specs
134+
)
135+
printable_share_group_type['share_types'] = "\n".join(
136+
printable_share_group_type['share_types']
137+
)
138+
139+
return printable_share_group_type

0 commit comments

Comments
 (0)