Merge tag '2.3.1' into debian/wallaby
python-octaviaclient 2.3.1 release
meta:version: 2.3.1
meta:diff-start: -
meta:series: wallaby
meta:release-type: release
meta:pypi: yes
meta:first: no
meta:release:Author: Gregory Thiemonge <gthiemon@redhat.com>
meta:release:Commit: Gregory Thiemonge <gthiemon@redhat.com>
meta:release:Change-Id: Icb8280040a88e6d2f98669295bc97de7aa056e08
meta:release:Code-Review+2: Thierry Carrez <thierry@openstack.org>
meta:release:Code-Review+2: Elod Illes <elod.illes@est.tech>
meta:release:Workflow+1: Elod Illes <elod.illes@est.tech>
Michal Arbet
2 years ago
1 | 1 | host=review.opendev.org |
2 | 2 | port=29418 |
3 | 3 | project=openstack/python-octaviaclient.git |
4 | defaultbranch=stable/wallaby |
10 | 10 | # under the License. |
11 | 11 | # |
12 | 12 | |
13 | LOADBALANCER_RESOURCES = 'loadbalancers' | |
14 | LISTENER_RESOURCES = 'listeners' | |
15 | POOL_RESOURCES = 'pools' | |
16 | MEMBER_RESOURCES = 'members' | |
17 | HEALTH_MONITOR_RESOURCES = 'healthmonitors' | |
18 | L7POLICY_RESOURCES = 'l7policies' | |
19 | L7RULE_RESOURCES = 'rules' | |
20 | QUOTA_RESOURCES = 'quotas' | |
21 | AMPHORA_RESOURCES = 'amphorae' | |
22 | PROVIDER_RESOURCES = 'providers' | |
23 | PROVIDER_FLAVOR_CAPABILITY_RESOURCES = 'flavor_capabilities' | |
24 | PROVIDER_AVAILABILITY_ZONE_CAPABILITY_RESOURCES = ( | |
25 | 'availability_zone_capabilities') | |
26 | FLAVOR_RESOURCES = 'flavors' | |
27 | FLAVORPROFILE_RESOURCES = 'flavorprofiles' | |
28 | AVAILABILITYZONE_RESOURCES = 'availability_zones' | |
29 | AVAILABILITYZONEPROFILE_RESOURCES = 'availability_zone_profiles' | |
30 | ||
13 | 31 | BASE_LBAAS_ENDPOINT = '/lbaas' |
14 | 32 | BASE_OCTAVIA_ENDPOINT = '/octavia' |
15 | 33 | |
16 | BASE_LOADBALANCER_URL = BASE_LBAAS_ENDPOINT + '/loadbalancers' | |
34 | BASE_LOADBALANCER_URL = BASE_LBAAS_ENDPOINT + '/' + LOADBALANCER_RESOURCES | |
17 | 35 | BASE_SINGLE_LB_URL = BASE_LOADBALANCER_URL + '/{uuid}' |
18 | 36 | BASE_LB_STATS_URL = BASE_SINGLE_LB_URL + '/stats' |
19 | 37 | BASE_LOADBALANCER_STATUS_URL = BASE_SINGLE_LB_URL + '/status' |
20 | 38 | BASE_LOADBALANCER_FAILOVER_URL = BASE_SINGLE_LB_URL + '/failover' |
21 | 39 | |
22 | BASE_LISTENER_URL = BASE_LBAAS_ENDPOINT + '/listeners' | |
40 | BASE_LISTENER_URL = BASE_LBAAS_ENDPOINT + '/' + LISTENER_RESOURCES | |
23 | 41 | BASE_SINGLE_LISTENER_URL = BASE_LISTENER_URL + '/{uuid}' |
24 | 42 | BASE_LISTENER_STATS_URL = BASE_SINGLE_LISTENER_URL + '/stats' |
25 | 43 | |
26 | BASE_POOL_URL = BASE_LBAAS_ENDPOINT + '/pools' | |
44 | BASE_POOL_URL = BASE_LBAAS_ENDPOINT + '/' + POOL_RESOURCES | |
27 | 45 | BASE_SINGLE_POOL_URL = BASE_POOL_URL + '/{pool_id}' |
28 | 46 | |
29 | BASE_MEMBER_URL = BASE_SINGLE_POOL_URL + '/members' | |
47 | BASE_MEMBER_URL = BASE_SINGLE_POOL_URL + '/' + MEMBER_RESOURCES | |
30 | 48 | BASE_SINGLE_MEMBER_URL = BASE_MEMBER_URL + '/{member_id}' |
31 | 49 | |
32 | BASE_HEALTH_MONITOR_URL = BASE_LBAAS_ENDPOINT + '/healthmonitors' | |
50 | BASE_HEALTH_MONITOR_URL = BASE_LBAAS_ENDPOINT + '/' + HEALTH_MONITOR_RESOURCES | |
33 | 51 | BASE_SINGLE_HEALTH_MONITOR_URL = BASE_HEALTH_MONITOR_URL + '/{uuid}' |
34 | 52 | |
35 | BASE_L7POLICY_URL = BASE_LBAAS_ENDPOINT + '/l7policies' | |
53 | BASE_L7POLICY_URL = BASE_LBAAS_ENDPOINT + '/' + L7POLICY_RESOURCES | |
36 | 54 | BASE_SINGLE_L7POLICY_URL = BASE_L7POLICY_URL + '/{policy_uuid}' |
37 | BASE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/rules' | |
38 | BASE_SINGLE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/rules/{rule_uuid}' | |
55 | BASE_L7RULE_URL = BASE_SINGLE_L7POLICY_URL + '/' + L7RULE_RESOURCES | |
56 | BASE_SINGLE_L7RULE_URL = BASE_L7RULE_URL + '/{rule_uuid}' | |
39 | 57 | |
40 | BASE_QUOTA_URL = BASE_LBAAS_ENDPOINT + '/quotas' | |
58 | BASE_QUOTA_URL = BASE_LBAAS_ENDPOINT + '/' + QUOTA_RESOURCES | |
41 | 59 | BASE_SINGLE_QUOTA_URL = BASE_QUOTA_URL + '/{uuid}' |
42 | 60 | BASE_QUOTA_DEFAULT_URL = BASE_QUOTA_URL + '/defaults' |
43 | 61 | |
44 | BASE_AMPHORA_URL = BASE_OCTAVIA_ENDPOINT + "/amphorae" | |
62 | BASE_AMPHORA_URL = BASE_OCTAVIA_ENDPOINT + "/" + AMPHORA_RESOURCES | |
45 | 63 | BASE_SINGLE_AMPHORA_URL = BASE_AMPHORA_URL + "/{uuid}" |
46 | 64 | BASE_AMPHORA_CONFIGURE_URL = BASE_SINGLE_AMPHORA_URL + '/config' |
47 | 65 | BASE_AMPHORA_FAILOVER_URL = BASE_SINGLE_AMPHORA_URL + '/failover' |
48 | 66 | BASE_AMPHORA_STATS_URL = BASE_SINGLE_AMPHORA_URL + '/stats' |
49 | 67 | |
50 | BASE_PROVIDER_URL = BASE_LBAAS_ENDPOINT + "/providers" | |
68 | BASE_PROVIDER_URL = BASE_LBAAS_ENDPOINT + "/" + PROVIDER_RESOURCES | |
51 | 69 | BASE_PROVIDER_FLAVOR_CAPABILITY_URL = ( |
52 | BASE_LBAAS_ENDPOINT + "/providers/{provider}/flavor_capabilities") | |
70 | BASE_PROVIDER_URL + "/{provider}/" + PROVIDER_FLAVOR_CAPABILITY_RESOURCES) | |
53 | 71 | BASE_PROVIDER_AVAILABILITY_ZONE_CAPABILITY_URL = ( |
54 | BASE_LBAAS_ENDPOINT + "/providers/{provider}" | |
55 | "/availability_zone_capabilities" | |
72 | BASE_PROVIDER_URL + "/{provider}/" + | |
73 | PROVIDER_AVAILABILITY_ZONE_CAPABILITY_RESOURCES | |
56 | 74 | ) |
57 | 75 | |
58 | BASE_FLAVOR_URL = BASE_LBAAS_ENDPOINT + "/flavors" | |
76 | BASE_FLAVOR_URL = BASE_LBAAS_ENDPOINT + "/" + FLAVOR_RESOURCES | |
59 | 77 | BASE_SINGLE_FLAVOR_URL = BASE_FLAVOR_URL + "/{uuid}" |
60 | BASE_FLAVORPROFILE_URL = BASE_LBAAS_ENDPOINT + "/flavorprofiles" | |
78 | BASE_FLAVORPROFILE_URL = BASE_LBAAS_ENDPOINT + "/" + FLAVORPROFILE_RESOURCES | |
61 | 79 | BASE_SINGLE_FLAVORPROFILE_URL = BASE_FLAVORPROFILE_URL + "/{uuid}" |
62 | 80 | |
63 | 81 | BASE_AVAILABILITYZONE_URL = BASE_LBAAS_ENDPOINT + "/availabilityzones" |
11 | 11 | # |
12 | 12 | """Octavia API Library""" |
13 | 13 | import functools |
14 | import urllib.parse as urlparse | |
14 | 15 | |
15 | 16 | from osc_lib.api import api |
16 | 17 | from osc_lib import exceptions as osc_exc |
65 | 66 | |
66 | 67 | _endpoint_suffix = '/v2.0' |
67 | 68 | |
69 | # Make sure we are always requesting JSON responses | |
70 | JSON_HEADER = {'Accept': 'application/json'} | |
71 | ||
68 | 72 | def __init__(self, endpoint=None, **kwargs): |
69 | 73 | super().__init__(endpoint=endpoint, **kwargs) |
70 | 74 | self.endpoint = self.endpoint.rstrip('/') |
71 | 75 | self._build_url() |
72 | 76 | |
73 | # Make sure we are always requesting JSON responses | |
74 | JSON_HEADER = {'Accept': 'application/json'} | |
75 | self._create = functools.partial(self.create, headers=JSON_HEADER) | |
76 | self._delete = functools.partial(self.delete, headers=JSON_HEADER) | |
77 | self._find = functools.partial(self.find, headers=JSON_HEADER) | |
78 | self._list = functools.partial(self.list, headers=JSON_HEADER) | |
77 | self._create = functools.partial(self.create, headers=self.JSON_HEADER) | |
78 | self._delete = functools.partial(self.delete, headers=self.JSON_HEADER) | |
79 | self._find = functools.partial(self.find, headers=self.JSON_HEADER) | |
80 | ||
81 | def _list(self, path, **params): | |
82 | get_all = params.pop('get_all', False) | |
83 | if not get_all: | |
84 | return self.list(path, **params, headers=self.JSON_HEADER) | |
85 | ||
86 | # Enable pagination for 'resources' | |
87 | resource_key = params.pop('resources') | |
88 | res = [] | |
89 | while True: | |
90 | response = self.list(path, **params, headers=self.JSON_HEADER) | |
91 | res.extend(response[resource_key]) | |
92 | ||
93 | links = response.get("{}_links".format(resource_key), []) | |
94 | for link in links: | |
95 | if link.get('rel') == 'next': | |
96 | query_str = urlparse.urlparse(link['href']).query | |
97 | params = urlparse.parse_qs(query_str) | |
98 | break | |
99 | else: | |
100 | break | |
101 | return {resource_key: res} | |
79 | 102 | |
80 | 103 | def _build_url(self): |
81 | 104 | if not self.endpoint.endswith(self._endpoint_suffix): |
91 | 114 | List of load balancers |
92 | 115 | """ |
93 | 116 | url = const.BASE_LOADBALANCER_URL |
94 | response = self._list(url, **params) | |
117 | response = self._list(url, get_all=True, | |
118 | resources=const.LOADBALANCER_RESOURCES, | |
119 | **params) | |
95 | 120 | |
96 | 121 | return response |
97 | 122 | |
206 | 231 | List of listeners |
207 | 232 | """ |
208 | 233 | url = const.BASE_LISTENER_URL |
209 | response = self._list(url, **kwargs) | |
234 | response = self._list(url, get_all=True, | |
235 | resources=const.LISTENER_RESOURCES, | |
236 | **kwargs) | |
210 | 237 | |
211 | 238 | return response |
212 | 239 | |
291 | 318 | List of pools |
292 | 319 | """ |
293 | 320 | url = const.BASE_POOL_URL |
294 | response = self._list(url, **kwargs) | |
321 | response = self._list(url, get_all=True, | |
322 | resources=const.POOL_RESOURCES, | |
323 | **kwargs) | |
295 | 324 | |
296 | 325 | return response |
297 | 326 | |
364 | 393 | Response list members |
365 | 394 | """ |
366 | 395 | url = const.BASE_MEMBER_URL.format(pool_id=pool_id) |
367 | response = self._list(url, **kwargs) | |
396 | response = self._list(url, get_all=True, | |
397 | resources=const.MEMBER_RESOURCES, | |
398 | **kwargs) | |
368 | 399 | |
369 | 400 | return response |
370 | 401 | |
448 | 479 | List of l7policies |
449 | 480 | """ |
450 | 481 | url = const.BASE_L7POLICY_URL |
451 | response = self._list(url, **kwargs) | |
482 | response = self._list(url, get_all=True, | |
483 | resources=const.L7POLICY_RESOURCES, | |
484 | **kwargs) | |
452 | 485 | |
453 | 486 | return response |
454 | 487 | |
519 | 552 | List of l7rules |
520 | 553 | """ |
521 | 554 | url = const.BASE_L7RULE_URL.format(policy_uuid=l7policy_id) |
522 | response = self._list(url, **kwargs) | |
555 | response = self._list(url, get_all=True, | |
556 | resources=const.L7RULE_RESOURCES, | |
557 | **kwargs) | |
523 | 558 | |
524 | 559 | return response |
525 | 560 | |
601 | 636 | A dict containing a list of health monitors |
602 | 637 | """ |
603 | 638 | url = const.BASE_HEALTH_MONITOR_URL |
604 | response = self._list(url, **kwargs) | |
639 | response = self._list(url, get_all=True, | |
640 | resources=const.HEALTH_MONITOR_RESOURCES, | |
641 | **kwargs) | |
605 | 642 | |
606 | 643 | return response |
607 | 644 | |
675 | 712 | A ``dict`` representing a list of quotas for the project |
676 | 713 | """ |
677 | 714 | url = const.BASE_QUOTA_URL |
678 | response = self._list(url, **params) | |
715 | response = self._list(url, get_all=True, | |
716 | resources=const.QUOTA_RESOURCES, | |
717 | **params) | |
679 | 718 | |
680 | 719 | return response |
681 | 720 | |
758 | 797 | A ``dict`` containing a list of amphorae |
759 | 798 | """ |
760 | 799 | url = const.BASE_AMPHORA_URL |
761 | response = self._list(path=url, **kwargs) | |
800 | response = self._list(path=url, get_all=True, | |
801 | resources=const.AMPHORA_RESOURCES, | |
802 | **kwargs) | |
762 | 803 | |
763 | 804 | return response |
764 | 805 | |
826 | 867 | A ``dict`` containing a list of provider |
827 | 868 | """ |
828 | 869 | url = const.BASE_PROVIDER_URL |
829 | response = self._list(path=url) | |
870 | response = self._list(path=url, get_all=True, | |
871 | resources=const.PROVIDER_RESOURCES) | |
830 | 872 | |
831 | 873 | return response |
832 | 874 | |
841 | 883 | """ |
842 | 884 | url = const.BASE_PROVIDER_FLAVOR_CAPABILITY_URL.format( |
843 | 885 | provider=provider) |
844 | response = self._list(url) | |
886 | resources = const.PROVIDER_FLAVOR_CAPABILITY_RESOURCES | |
887 | response = self._list(url, get_all=True, | |
888 | resources=resources) | |
845 | 889 | |
846 | 890 | return response |
847 | 891 | |
856 | 900 | """ |
857 | 901 | url = const.BASE_PROVIDER_AVAILABILITY_ZONE_CAPABILITY_URL.format( |
858 | 902 | provider=provider) |
859 | response = self._list(url) | |
903 | resources = const.PROVIDER_AVAILABILITY_ZONE_CAPABILITY_RESOURCES | |
904 | response = self._list(url, get_all=True, | |
905 | resources=resources) | |
860 | 906 | |
861 | 907 | return response |
862 | 908 | |
870 | 916 | A ``dict`` containing a list of flavor |
871 | 917 | """ |
872 | 918 | url = const.BASE_FLAVOR_URL |
873 | response = self._list(path=url, **kwargs) | |
919 | response = self._list(path=url, get_all=True, | |
920 | resources=const.FLAVOR_RESOURCES, **kwargs) | |
874 | 921 | |
875 | 922 | return response |
876 | 923 | |
955 | 1002 | List of flavor profile |
956 | 1003 | """ |
957 | 1004 | url = const.BASE_FLAVORPROFILE_URL |
958 | response = self._list(url, **kwargs) | |
1005 | response = self._list(url, get_all=True, | |
1006 | resources=const.FLAVORPROFILE_RESOURCES, | |
1007 | **kwargs) | |
959 | 1008 | |
960 | 1009 | return response |
961 | 1010 | |
1013 | 1062 | A ``dict`` containing a list of availabilityzone |
1014 | 1063 | """ |
1015 | 1064 | url = const.BASE_AVAILABILITYZONE_URL |
1016 | response = self._list(path=url, **kwargs) | |
1065 | response = self._list(path=url, get_all=True, | |
1066 | resources=const.AVAILABILITYZONE_RESOURCES, | |
1067 | **kwargs) | |
1017 | 1068 | |
1018 | 1069 | return response |
1019 | 1070 | |
1102 | 1153 | List of availabilityzone profile |
1103 | 1154 | """ |
1104 | 1155 | url = const.BASE_AVAILABILITYZONEPROFILE_URL |
1105 | response = self._list(url, **kwargs) | |
1156 | resources = const.AVAILABILITYZONEPROFILE_RESOURCES | |
1157 | response = self._list(url, get_all=True, | |
1158 | resources=resources, | |
1159 | **kwargs) | |
1106 | 1160 | |
1107 | 1161 | return response |
1108 | 1162 |
15 | 15 | from openstackclient.identity import common as identity_common |
16 | 16 | from osc_lib import exceptions as osc_exc |
17 | 17 | from osc_lib import utils |
18 | from oslo_utils import uuidutils | |
18 | 19 | |
19 | 20 | from octaviaclient.api import exceptions |
20 | 21 | from octaviaclient.osc.v2 import constants |
61 | 62 | return res |
62 | 63 | |
63 | 64 | |
65 | def _find_resource(list_funct, resource_name, root_tag, name, parent=None): | |
66 | """Search for a resource by name and ID. | |
67 | ||
68 | This function will search for a resource by both the name and ID, | |
69 | returning the resource once it finds a match. If no match is found, | |
70 | an exception will be raised. | |
71 | ||
72 | :param list_funct: The resource list method to call during searches. | |
73 | :param resource_name: The name of the resource type we are searching for. | |
74 | :param root_tag: The root tag of the resource returned from the API. | |
75 | :param name: The value we are searching for, a resource name or ID. | |
76 | :param parent: The parent resource ID, when required. | |
77 | :return: The resource found for the name or ID. | |
78 | :raises osc_exc.CommandError: If more than one match or none are found. | |
79 | """ | |
80 | if parent: | |
81 | parent_args = [parent] | |
82 | else: | |
83 | parent_args = [] | |
84 | # Optimize the API call order if we got a UUID-like name or not | |
85 | if uuidutils.is_uuid_like(name): | |
86 | # Try by ID first | |
87 | resource = list_funct(*parent_args, id=name)[root_tag] | |
88 | if len(resource) == 1: | |
89 | return resource[0] | |
90 | ||
91 | # Try by name next | |
92 | resource = list_funct(*parent_args, name=name)[root_tag] | |
93 | if len(resource) == 1: | |
94 | return resource[0] | |
95 | if len(resource) > 1: | |
96 | msg = ("{0} {1} found with name or ID of {2}. Please try " | |
97 | "again with UUID".format(len(resource), resource_name, | |
98 | name)) | |
99 | raise osc_exc.CommandError(msg) | |
100 | else: | |
101 | # Try by name first | |
102 | resource = list_funct(*parent_args, name=name)[root_tag] | |
103 | if len(resource) == 1: | |
104 | return resource[0] | |
105 | if len(resource) > 1: | |
106 | msg = ("{0} {1} found with name or ID of {2}. Please try " | |
107 | "again with UUID".format(len(resource), resource_name, | |
108 | name)) | |
109 | raise osc_exc.CommandError(msg) | |
110 | ||
111 | # Try by ID next | |
112 | resource = list_funct(*parent_args, id=name)[root_tag] | |
113 | if len(resource) == 1: | |
114 | return resource[0] | |
115 | ||
116 | # We didn't find what we were looking for, raise a consistent error. | |
117 | msg = "Unable to locate {0} in {1}".format(name, resource_name) | |
118 | raise osc_exc.CommandError(msg) | |
119 | ||
120 | ||
64 | 121 | def get_resource_id(resource, resource_name, name): |
65 | 122 | """Converts a resource name into a UUID for consumption for the API |
66 | 123 | |
93 | 150 | ).id |
94 | 151 | return project_id |
95 | 152 | return 'non-uuid' |
153 | ||
96 | 154 | if resource_name == 'members': |
97 | names = [re for re in resource(name['pool_id'])['members'] | |
98 | if re.get('id') == name['member_id'] or | |
99 | re.get('name') == name['member_id']] | |
100 | name = name['member_id'] | |
101 | if len(names) > 1: | |
102 | msg = ("{0} {1} found with name or ID of {2}. Please try " | |
103 | "again with UUID".format(len(names), resource_name, | |
104 | name)) | |
105 | raise osc_exc.CommandError(msg) | |
106 | return names[0].get('id') | |
155 | member = _find_resource(resource, resource_name, 'members', | |
156 | name['member_id'], parent=name['pool_id']) | |
157 | return member.get('id') | |
158 | ||
107 | 159 | if resource_name == 'l7rules': |
108 | names = [re for re in resource(name['l7policy_id'])['rules'] | |
109 | if re.get('id') == name['l7rule_id']] | |
110 | name = name['l7rule_id'] | |
111 | return names[0].get('id') | |
112 | names = [re for re in resource()[resource_name] | |
113 | if re.get('name') == name or re.get('id') == name] | |
114 | if len(names) > 1: | |
115 | msg = ("{0} {1} found with name or ID of {2}. Please try " | |
116 | "again with UUID".format(len(names), resource_name, | |
117 | name)) | |
118 | raise osc_exc.CommandError(msg) | |
119 | return names[0].get(primary_key) | |
160 | l7rule = _find_resource(resource, resource_name, 'rules', | |
161 | name['l7rule_id'], | |
162 | parent=name['l7policy_id']) | |
163 | return l7rule.get('id') | |
164 | ||
165 | resource = _find_resource(resource, resource_name, resource_name, name) | |
166 | return resource.get(primary_key) | |
120 | 167 | |
121 | 168 | except IndexError as e: |
122 | 169 | msg = "Unable to locate {0} in {1}".format(name, resource_name) |
67 | 67 | {'name': 'mem2'}] |
68 | 68 | } |
69 | 69 | |
70 | LIST_L7PO_RESP = [ | |
71 | {'name': 'l71'}, | |
72 | {'name': 'l72'}, | |
73 | ] | |
70 | LIST_L7PO_RESP = { | |
71 | 'l7policies': | |
72 | [{'name': 'l71'}, | |
73 | {'name': 'l72'}] | |
74 | } | |
74 | 75 | |
75 | 76 | LIST_L7RU_RESP = { |
76 | 77 | 'rules': |
93 | 93 | verifylist = [ |
94 | 94 | ('availabilityzone', 'unknown_availabilityzone') |
95 | 95 | ] |
96 | self.api_mock.availabilityzone_list.return_value = { | |
97 | 'availability_zones': []} | |
96 | 98 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
97 | 99 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
98 | 100 | parsed_args) |
98 | 98 | verifylist = [ |
99 | 99 | ('availabilityzoneprofile', 'unknown_availabilityzoneprofile') |
100 | 100 | ] |
101 | self.api_mock.availabilityzoneprofile_list.return_value = { | |
102 | 'availability_zone_profiles': []} | |
101 | 103 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
102 | 104 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
103 | 105 | parsed_args) |
91 | 91 | verifylist = [ |
92 | 92 | ('flavor', 'unknown_flavor') |
93 | 93 | ] |
94 | self.api_mock.flavor_list.return_value = {'flavors': []} | |
94 | 95 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
95 | 96 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
96 | 97 | parsed_args) |
93 | 93 | verifylist = [ |
94 | 94 | ('flavorprofile', 'unknown_flavorprofile') |
95 | 95 | ] |
96 | self.api_mock.flavorprofile_list.return_value = { | |
97 | 'flavorprofiles': []} | |
96 | 98 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
97 | 99 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
98 | 100 | parsed_args) |
156 | 156 | verifylist = [ |
157 | 157 | ('health_monitor', 'unknown_hm') |
158 | 158 | ] |
159 | self.api_mock.health_monitor_list.return_value = { | |
160 | 'healthmonitors': []} | |
159 | 161 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
160 | 162 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
161 | 163 | parsed_args) |
172 | 172 | verifylist = [ |
173 | 173 | ('l7policy', 'unknown_policy') |
174 | 174 | ] |
175 | self.api_mock.l7policy_list.return_value = {'l7policies': []} | |
175 | 176 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
176 | 177 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
177 | 178 | parsed_args) |
161 | 161 | verifylist = [ |
162 | 162 | ('listener', 'unknown_lb') |
163 | 163 | ] |
164 | self.api_mock.listener_list.return_value = {'listeners': []} | |
164 | 165 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
165 | 166 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
166 | 167 | parsed_args) |
304 | 304 | verifylist = [ |
305 | 305 | ('loadbalancer', 'unknown_lb') |
306 | 306 | ] |
307 | self.api_mock.load_balancer_list.return_value = { | |
308 | 'loadbalancers': []} | |
307 | 309 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
308 | 310 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
309 | 311 | parsed_args) |
154 | 154 | verifylist = [ |
155 | 155 | ('pool', 'unknown_pool') |
156 | 156 | ] |
157 | self.api_mock.pool_list.return_value = {'pools': []} | |
157 | 158 | parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
158 | 159 | self.assertRaises(exceptions.CommandError, self.cmd.take_action, |
159 | 160 | parsed_args) |
+5
-0
0 | --- | |
1 | fixes: | |
2 | - | | |
3 | Improved the client performance when using a name instead of the | |
4 | resource ID. |
0 | --- | |
1 | fixes: | |
2 | - | | |
3 | Fixed some issues when the number of Octavia resources exceeded the | |
4 | 'pagination_max_limit' parameter in Octavia API. The list calls now support | |
5 | pagination. |
14 | 14 | VIRTUAL_ENV={envdir} |
15 | 15 | PYTHONWARNINGS=default::DeprecationWarning |
16 | 16 | deps = |
17 | -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} | |
17 | -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby} | |
18 | 18 | -r{toxinidir}/test-requirements.txt |
19 | 19 | commands = |
20 | 20 | find . -type f -name "*.pyc" -delete |
54 | 54 | |
55 | 55 | [testenv:docs] |
56 | 56 | deps = |
57 | -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} | |
57 | -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby} | |
58 | 58 | -r{toxinidir}/doc/requirements.txt |
59 | 59 | commands = |
60 | 60 | rm -rf doc/build/html |
72 | 72 | |
73 | 73 | [testenv:releasenotes] |
74 | 74 | deps = |
75 | -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} | |
75 | -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby} | |
76 | 76 | -r{toxinidir}/doc/requirements.txt |
77 | 77 | commands = |
78 | 78 | rm -rf releasenotes/build |