Add "--wait" functionality

Change-Id: Ia8e451d7f806fac7d36b2860f256eb34f9f7400e
This commit is contained in:
Adam Harwell 2019-10-29 16:59:12 -07:00
parent cd6482966a
commit ae244fcf25
22 changed files with 1441 additions and 75 deletions

View File

@ -0,0 +1,26 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
class OctaviaClientException(Exception):
"""The base exception class for all exceptions this library raises."""
def __init__(self, code, message=None, request_id=None):
self.code = code
self.message = message or self.__class__.message
self.request_id = request_id
def __str__(self):
return "%s (HTTP %s) (Request-ID: %s)" % (self.message,
self.code,
self.request_id)

View File

@ -18,6 +18,7 @@ from osc_lib.api import api
from osc_lib import exceptions as osc_exc
from octaviaclient.api import constants as const
from octaviaclient.api import exceptions
def correct_return_codes(func):
@ -45,7 +46,7 @@ def correct_return_codes(func):
else:
raise
raise OctaviaClientException(
raise exceptions.OctaviaClientException(
code=code,
message=message,
request_id=request_id)
@ -934,17 +935,3 @@ class OctaviaAPI(api.BaseAPI):
response = self._delete(url)
return response
class OctaviaClientException(Exception):
"""The base exception class for all exceptions this library raises."""
def __init__(self, code, message=None, request_id=None):
self.code = code
self.message = message or self.__class__.message
self.request_id = request_id
def __str__(self):
return "%s (HTTP %s) (Request-ID: %s)" % (self.message,
self.code,
self.request_id)

View File

@ -128,15 +128,32 @@ class ConfigureAmphora(command.Command):
metavar='<amphora-id>',
help='UUID of the amphora to configure.',
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
attrs = v2_utils.get_amphora_attrs(self.app.client_manager,
parsed_args)
amp_id = attrs.pop('amphora_id')
self.app.client_manager.load_balancer.amphora_configure(
amphora_id=attrs.pop('amphora_id'))
amphora_id=amp_id)
if parsed_args.wait:
amphora = self.app.client_manager.load_balancer.amphora_show(
amp_id)
lb_id = amphora.get('loadbalancer_id')
# TODO(rm_work): No status change if the amp isn't linked to an LB?
if lb_id:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=lb_id
)
class FailoverAmphora(command.Command):
@ -150,12 +167,33 @@ class FailoverAmphora(command.Command):
metavar='<amphora-id>',
help='UUID of the amphora.',
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
attrs = v2_utils.get_amphora_attrs(self.app.client_manager,
parsed_args)
amp_id = attrs.pop('amphora_id')
amphora = self.app.client_manager.load_balancer.amphora_show(amp_id)
self.app.client_manager.load_balancer.amphora_failover(
amphora_id=attrs.pop('amphora_id'))
amphora_id=amp_id)
if parsed_args.wait:
lb_id = amphora.get('loadbalancer_id')
if lb_id:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=lb_id
)
else:
v2_utils.wait_for_delete(
status_f=(self.app.client_manager.load_balancer.
amphora_show),
res_id=amp_id
)

View File

@ -313,3 +313,5 @@ FLAVORPROFILE_COLUMNS = (
'name',
'provider_name',
)
PROVISIONING_STATUS = 'provisioning_status'

View File

@ -132,6 +132,11 @@ class CreateHealthMonitor(command.ShowOne):
default=None,
help="Disable health monitor."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -143,6 +148,20 @@ class CreateHealthMonitor(command.ShowOne):
data = self.app.client_manager.load_balancer.health_monitor_create(
json=body)
if parsed_args.wait:
pool = self.app.client_manager.load_balancer.pool_show(
data['healthmonitor']['pools'][0]['id'])
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=pool['loadbalancers'][0]['id']
)
data = {
'healthmonitor': (
self.app.client_manager.load_balancer.health_monitor_show(
data['healthmonitor']['id']))
}
formatters = {'pools': v2_utils.format_list}
return (rows,
@ -162,6 +181,11 @@ class DeleteHealthMonitor(command.Command):
metavar='<health_monitor>',
help="Health monitor to delete (name or ID)."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -174,6 +198,13 @@ class DeleteHealthMonitor(command.Command):
self.app.client_manager.load_balancer.health_monitor_delete(
health_monitor_id=health_monitor_id)
if parsed_args.wait:
v2_utils.wait_for_delete(
status_f=(self.app.client_manager.load_balancer.
health_monitor_show),
res_id=health_monitor_id
)
class ListHealthMonitor(lister.Lister):
"""List health monitors"""
@ -316,6 +347,11 @@ class SetHealthMonitor(command.Command):
default=None,
help="Disable health monitor."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -330,6 +366,13 @@ class SetHealthMonitor(command.Command):
self.app.client_manager.load_balancer.health_monitor_set(
hm_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
health_monitor_show),
res_id=hm_id
)
class UnsetHealthMonitor(command.Command):
"""Clear health monitor settings"""
@ -378,6 +421,11 @@ class UnsetHealthMonitor(command.Command):
action='store_true',
help="Clear the health monitor URL path."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
@ -393,3 +441,10 @@ class UnsetHealthMonitor(command.Command):
self.app.client_manager.load_balancer.health_monitor_set(
hm_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
health_monitor_show),
res_id=hm_id
)

View File

@ -104,6 +104,11 @@ class CreateL7Policy(command.ShowOne):
default=None,
help="Disable l7policy."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -117,6 +122,20 @@ class CreateL7Policy(command.ShowOne):
data = self.app.client_manager.load_balancer.l7policy_create(
json=body)
if parsed_args.wait:
listener = self.app.client_manager.load_balancer.listener_show(
data['l7policy']['listener_id'])
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=listener['loadbalancers'][0]['id']
)
data = {
'l7policy': (
self.app.client_manager.load_balancer.l7policy_show(
data['l7policy']['id']))
}
formatters = {'rules': v2_utils.format_list}
return (rows, (utils.get_dict_properties(
@ -134,6 +153,11 @@ class DeleteL7Policy(command.Command):
metavar="<policy>",
help="l7policy to delete (name or ID)."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -146,6 +170,13 @@ class DeleteL7Policy(command.Command):
self.app.client_manager.load_balancer.l7policy_delete(
l7policy_id=l7policy_id)
if parsed_args.wait:
v2_utils.wait_for_delete(
status_f=(self.app.client_manager.load_balancer.
l7policy_show),
res_id=l7policy_id
)
class ListL7Policy(lister.Lister):
"""List l7policies"""
@ -278,6 +309,11 @@ class SetL7Policy(command.Command):
default=None,
help="Disable l7policy."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -293,6 +329,13 @@ class SetL7Policy(command.Command):
self.app.client_manager.load_balancer.l7policy_set(
l7policy_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
l7policy_show),
res_id=l7policy_id
)
class UnsetL7Policy(command.Command):
"""Clear l7policy settings"""
@ -320,6 +363,11 @@ class UnsetL7Policy(command.Command):
action='store_true',
help="Clear the l7policy redirect HTTP code."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
@ -335,3 +383,10 @@ class UnsetL7Policy(command.Command):
self.app.client_manager.load_balancer.l7policy_set(
policy_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
l7policy_show),
res_id=policy_id
)

View File

@ -16,6 +16,8 @@
"""L7rule action implementation"""
import functools
from cliff import lister
from osc_lib.command import command
from osc_lib import utils
@ -85,6 +87,11 @@ class CreateL7Rule(command.ShowOne):
default=None,
help="Disable l7rule."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -101,6 +108,22 @@ class CreateL7Rule(command.ShowOne):
json=body
)
if parsed_args.wait:
l7policy = self.app.client_manager.load_balancer.l7policy_show(
l7policy_id)
listener = self.app.client_manager.load_balancer.listener_show(
l7policy['listener_id'])
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=listener['loadbalancers'][0]['id']
)
data = {
'rule': (
self.app.client_manager.load_balancer.l7rule_show(
l7policy_id, data['rule']['id']))
}
return (rows, (utils.get_dict_properties(
data['rule'], rows, formatters={})))
@ -121,6 +144,11 @@ class DeleteL7Rule(command.Command):
metavar="<rule_id>",
help="l7rule to delete."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -132,6 +160,16 @@ class DeleteL7Rule(command.Command):
l7policy_id=attrs['l7policy_id']
)
if parsed_args.wait:
l7rule_show = functools.partial(
self.app.client_manager.load_balancer.l7rule_show,
attrs['l7policy_id']
)
v2_utils.wait_for_delete(
status_f=l7rule_show,
res_id=attrs['l7rule_id']
)
class ListL7Rule(lister.Lister):
"""List l7rules for l7policy"""
@ -251,6 +289,11 @@ class SetL7Rule(command.Command):
default=None,
help="Disable l7rule."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -269,6 +312,16 @@ class SetL7Rule(command.Command):
json=body
)
if parsed_args.wait:
l7rule_show = functools.partial(
self.app.client_manager.load_balancer.l7rule_show,
l7policy_id
)
v2_utils.wait_for_active(
status_f=l7rule_show,
res_id=l7rule_id
)
class UnsetL7Rule(command.Command):
"""Clear l7rule settings"""
@ -296,6 +349,11 @@ class UnsetL7Rule(command.Command):
action='store_true',
help="Clear the l7rule key."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
@ -311,3 +369,13 @@ class UnsetL7Rule(command.Command):
self.app.client_manager.load_balancer.l7rule_set(
l7policy_id=policy_id, l7rule_id=parsed_args.l7rule_id, json=body)
if parsed_args.wait:
l7rule_show = functools.partial(
self.app.client_manager.load_balancer.l7rule_show,
policy_id
)
v2_utils.wait_for_active(
status_f=l7rule_show,
res_id=parsed_args.l7rule_id
)

View File

@ -166,6 +166,11 @@ class CreateListener(command.ShowOne):
help="CIDR to allow access to the listener (can be set multiple "
"times)."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -176,6 +181,19 @@ class CreateListener(command.ShowOne):
body = {"listener": attrs}
data = self.app.client_manager.load_balancer.listener_create(
json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=data['listener']['loadbalancers'][0]['id']
)
data = {
'listener': (
self.app.client_manager.load_balancer.listener_show(
data['listener']['id']))
}
formatters = {'loadbalancers': v2_utils.format_list,
'pools': v2_utils.format_list,
'l7policies': v2_utils.format_list,
@ -199,6 +217,11 @@ class DeleteListener(command.Command):
metavar="<listener>",
help="Listener to delete (name or ID)"
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -211,6 +234,12 @@ class DeleteListener(command.Command):
self.app.client_manager.load_balancer.listener_delete(
listener_id=listener_id)
if parsed_args.wait:
v2_utils.wait_for_delete(
status_f=self.app.client_manager.load_balancer.listener_show,
res_id=listener_id
)
class ListListener(lister.Lister):
"""List listeners"""
@ -421,6 +450,11 @@ class SetListener(command.Command):
help="CIDR to allow access to the listener (can be set multiple "
"times)."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -435,6 +469,12 @@ class SetListener(command.Command):
self.app.client_manager.load_balancer.listener_set(
listener_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=self.app.client_manager.load_balancer.listener_show,
res_id=listener_id
)
class UnsetListener(command.Command):
"""Clear listener settings"""
@ -525,6 +565,11 @@ class UnsetListener(command.Command):
action='store_true',
help="Clear all allowed CIDRs from the listener."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
@ -541,6 +586,12 @@ class UnsetListener(command.Command):
self.app.client_manager.load_balancer.listener_set(
listener_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=self.app.client_manager.load_balancer.listener_show,
res_id=listener_id
)
class ShowListenerStats(command.ShowOne):
"""Shows the current statistics for a listener."""

View File

@ -118,6 +118,11 @@ class CreateLoadBalancer(command.ShowOne):
metavar='<flavor>',
help="The name or ID of the flavor for the load balancer."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -131,6 +136,18 @@ class CreateLoadBalancer(command.ShowOne):
data = self.app.client_manager.load_balancer.load_balancer_create(
json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=data['loadbalancer']['id']
)
data = {
'loadbalancer': (
self.app.client_manager.load_balancer.load_balancer_show(
data['loadbalancer']['id']))
}
formatters = {
'listeners': v2_utils.format_list,
'pools': v2_utils.format_list,
@ -160,6 +177,11 @@ class DeleteLoadBalancer(command.Command):
help="Cascade the delete to all child elements of the load "
"balancer."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -171,6 +193,13 @@ class DeleteLoadBalancer(command.Command):
self.app.client_manager.load_balancer.load_balancer_delete(
lb_id=lb_id, **attrs)
if parsed_args.wait:
v2_utils.wait_for_delete(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=lb_id
)
class FailoverLoadBalancer(command.Command):
"""Trigger load balancer failover"""
@ -183,14 +212,27 @@ class FailoverLoadBalancer(command.Command):
metavar='<load_balancer>',
help="Name or UUID of the load balancer."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
attrs = v2_utils.get_loadbalancer_attrs(self.app.client_manager,
parsed_args)
lb_id = attrs.pop('loadbalancer_id')
self.app.client_manager.load_balancer.load_balancer_failover(
lb_id=attrs.pop('loadbalancer_id'))
lb_id=lb_id)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=lb_id
)
class ListLoadBalancer(lister.Lister):
@ -362,6 +404,11 @@ class SetLoadBalancer(command.Command):
default=None,
help="Disable load balancer."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -374,6 +421,13 @@ class SetLoadBalancer(command.Command):
self.app.client_manager.load_balancer.load_balancer_set(
lb_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=lb_id
)
class UnsetLoadBalancer(command.Command):
"""Clear load balancer settings"""
@ -401,6 +455,11 @@ class UnsetLoadBalancer(command.Command):
action='store_true',
help="Clear the load balancer QoS policy.",
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -418,6 +477,13 @@ class UnsetLoadBalancer(command.Command):
self.app.client_manager.load_balancer.load_balancer_set(
lb_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=lb_id
)
class ShowLoadBalancerStats(command.ShowOne):
"""Shows the current statistics for a load balancer"""

View File

@ -15,6 +15,7 @@
"""Member action implementation"""
import functools
from cliff import lister
from osc_lib.command import command
@ -172,6 +173,11 @@ class CreateMember(command.ShowOne):
default=None,
help="Disable member"
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -186,6 +192,19 @@ class CreateMember(command.ShowOne):
json=body
)
if parsed_args.wait:
pool = self.app.client_manager.load_balancer.pool_show(pool_id)
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=pool['loadbalancers'][0]['id']
)
data = {
'member': (
self.app.client_manager.load_balancer.member_show(
pool_id, data['member']['id']))
}
return (rows,
(utils.get_dict_properties(
data['member'], rows, formatters={})))
@ -258,6 +277,11 @@ class SetMember(command.Command):
action='store_true',
default=None,
help="Set the admin_state_up to False")
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -273,6 +297,16 @@ class SetMember(command.Command):
json=post_data
)
if parsed_args.wait:
member_show = functools.partial(
self.app.client_manager.load_balancer.member_show,
pool_id
)
v2_utils.wait_for_active(
status_f=member_show,
res_id=member_id
)
class DeleteMember(command.Command):
"""Delete a member from a pool """
@ -291,6 +325,11 @@ class DeleteMember(command.Command):
metavar='<member>',
help="Name or ID of the member to be deleted."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -304,6 +343,16 @@ class DeleteMember(command.Command):
member_id=id
)
if parsed_args.wait:
member_show = functools.partial(
self.app.client_manager.load_balancer.member_show,
pool_id
)
v2_utils.wait_for_delete(
status_f=member_show,
res_id=id
)
class UnsetMember(command.Command):
"""Clear member settings"""
@ -346,6 +395,11 @@ class UnsetMember(command.Command):
action='store_true',
help="Reset the member weight to the API default."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
@ -366,3 +420,13 @@ class UnsetMember(command.Command):
self.app.client_manager.load_balancer.member_set(
pool_id=pool_id, member_id=member_id, json=body)
if parsed_args.wait:
member_show = functools.partial(
self.app.client_manager.load_balancer.member_show,
pool_id
)
v2_utils.wait_for_active(
status_f=member_show,
res_id=member_id
)

View File

@ -123,6 +123,11 @@ class CreatePool(command.ShowOne):
default=None,
help="Disable backend member re-encryption."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -133,6 +138,19 @@ class CreatePool(command.ShowOne):
body = {"pool": attrs}
data = self.app.client_manager.load_balancer.pool_create(
json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=(self.app.client_manager.load_balancer.
load_balancer_show),
res_id=data['pool']['loadbalancers'][0]['id']
)
data = {
'pool': (
self.app.client_manager.load_balancer.pool_show(
data['pool']['id']))
}
formatters = {'loadbalancers': v2_utils.format_list,
'members': v2_utils.format_list,
'listeners': v2_utils.format_list,
@ -154,6 +172,11 @@ class DeletePool(command.Command):
metavar="<pool>",
help="Pool to delete (name or ID)."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -163,6 +186,12 @@ class DeletePool(command.Command):
self.app.client_manager.load_balancer.pool_delete(
pool_id=pool_id)
if parsed_args.wait:
v2_utils.wait_for_delete(
status_f=self.app.client_manager.load_balancer.pool_show,
res_id=pool_id
)
class ListPool(lister.Lister):
"""List pools"""
@ -306,6 +335,11 @@ class SetPool(command.Command):
default=None,
help="disable backend associated members re-encryption."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
@ -318,6 +352,12 @@ class SetPool(command.Command):
self.app.client_manager.load_balancer.pool_set(
pool_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=self.app.client_manager.load_balancer.pool_show,
res_id=pool_id
)
class UnsetPool(command.Command):
"""Clear pool settings"""
@ -362,6 +402,11 @@ class UnsetPool(command.Command):
action='store_true',
help="Clear the certificate reference for this pool."
)
parser.add_argument(
'--wait',
action='store_true',
help='Wait for action to complete',
)
return parser
def take_action(self, parsed_args):
@ -377,3 +422,9 @@ class UnsetPool(command.Command):
self.app.client_manager.load_balancer.pool_set(
pool_id, json=body)
if parsed_args.wait:
v2_utils.wait_for_active(
status_f=self.app.client_manager.load_balancer.pool_show,
res_id=pool_id
)

View File

@ -12,9 +12,13 @@
# under the License.
#
from osc_lib import exceptions
import munch
from openstackclient.identity import common as identity_common
from osc_lib import exceptions as osc_exc
from osc_lib import utils
from octaviaclient.api import exceptions
from octaviaclient.osc.v2 import constants
def _map_attrs(args, source_attr_map):
@ -95,7 +99,7 @@ def get_resource_id(resource, resource_name, name):
msg = ("{0} {1} found with name or ID of {2}. Please try "
"again with UUID".format(len(names), resource_name,
name))
raise exceptions.CommandError(msg)
raise osc_exc.CommandError(msg)
else:
return names[0].get('id')
elif resource_name == 'l7rules':
@ -110,12 +114,12 @@ def get_resource_id(resource, resource_name, name):
msg = ("{0} {1} found with name or ID of {2}. Please try "
"again with UUID".format(len(names), resource_name,
name))
raise exceptions.CommandError(msg)
raise osc_exc.CommandError(msg)
else:
return names[0].get('id')
except IndexError:
msg = "Unable to locate {0} in {1}".format(name, resource_name)
raise exceptions.CommandError(msg)
raise osc_exc.CommandError(msg)
def get_loadbalancer_attrs(client_manager, parsed_args):
@ -547,4 +551,39 @@ def _format_str_if_need_treat_unset(data):
def get_unsets(parsed_args):
return {arg: None for arg, value in vars(parsed_args).items() if
value is True}
value is True and arg != 'wait'}
def wait_for_active(status_f, res_id):
success = utils.wait_for_status(
status_f=lambda x: munch.Munch(status_f(x)),
res_id=res_id,
status_field=constants.PROVISIONING_STATUS,
sleep_time=3
)
if not success:
raise exceptions.OctaviaClientException(
code="n/a",
message="The resource did not successfully reach ACTIVE status.")
def wait_for_delete(status_f, res_id):
class Getter(object):
@staticmethod
def get(id):
return munch.Munch(status_f(id))
try:
success = utils.wait_for_delete(
manager=Getter,
res_id=res_id,
status_field=constants.PROVISIONING_STATUS,
sleep_time=3
)
if not success:
raise exceptions.OctaviaClientException(
code="n/a",
message="The resource could not be successfully deleted.")
except exceptions.OctaviaClientException as e:
if e.code != 404:
raise

View File

@ -19,6 +19,7 @@ from requests_mock.contrib import fixture
from osc_lib.tests import utils
from octaviaclient.api import exceptions
from octaviaclient.api.v2 import octavia
FAKE_ACCOUNT = 'q12we34r'
@ -204,7 +205,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.load_balancer_create,
json=SINGLE_LB_RESP)
@ -226,7 +227,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.load_balancer_set,
FAKE_LB,
@ -248,7 +249,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=409,
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.load_balancer_failover,
FAKE_LB)
@ -269,7 +270,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.load_balancer_delete,
FAKE_LB)
@ -331,7 +332,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.listener_create,
json=SINGLE_LI_RESP)
@ -353,7 +354,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.listener_set,
FAKE_LI, json=SINGLE_LI_UPDATE)
@ -374,7 +375,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.listener_delete,
FAKE_LI)
@ -426,7 +427,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.pool_create,
json=SINGLE_PO_RESP)
@ -448,7 +449,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.pool_set,
FAKE_PO, json=SINGLE_PO_UPDATE)
@ -469,7 +470,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.pool_delete,
FAKE_PO)
@ -511,7 +512,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.member_create,
json=SINGLE_ME_RESP, pool_id=FAKE_PO)
@ -534,7 +535,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.member_set,
pool_id=FAKE_PO, member_id=FAKE_ME,
@ -556,7 +557,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.member_delete,
pool_id=FAKE_PO, member_id=FAKE_ME)
@ -598,7 +599,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.l7policy_create,
json=SINGLE_L7PO_RESP)
@ -620,7 +621,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.l7policy_set,
FAKE_L7PO, json=SINGLE_L7PO_UPDATE)
@ -641,7 +642,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.l7policy_delete,
FAKE_L7PO)
@ -683,7 +684,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.l7rule_create,
FAKE_L7PO, json=SINGLE_L7RU_RESP)
@ -709,7 +710,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.l7rule_set,
l7rule_id=FAKE_L7RU,
@ -735,7 +736,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.l7rule_delete,
l7rule_id=FAKE_L7RU,
@ -778,7 +779,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.health_monitor_create,
json=SINGLE_HM_RESP)
@ -800,7 +801,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.health_monitor_set,
FAKE_HM, json=SINGLE_HM_UPDATE)
@ -821,7 +822,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.health_monitor_delete,
FAKE_HM)
@ -863,7 +864,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.quota_set,
FAKE_PRJ, json=SINGLE_QT_UPDATE)
@ -884,7 +885,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.quota_reset,
FAKE_PRJ)
@ -925,7 +926,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=409,
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.amphora_configure,
FAKE_AMP)
@ -946,7 +947,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=409,
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.amphora_failover,
FAKE_AMP)
@ -1010,7 +1011,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.flavor_create,
json=SINGLE_FV_RESP)
@ -1032,7 +1033,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.flavor_set,
FAKE_FV,
@ -1054,7 +1055,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.flavor_delete,
FAKE_FV)
@ -1096,7 +1097,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.flavorprofile_create,
json=SINGLE_FVPF_RESP)
@ -1118,7 +1119,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.flavorprofile_set,
FAKE_FVPF, json=SINGLE_FVPF_UPDATE)
@ -1139,7 +1140,7 @@ class TestLoadBalancer(TestOctaviaClient):
text='{"faultstring": "%s"}' % self._error_message,
status_code=400
)
self.assertRaisesRegex(octavia.OctaviaClientException,
self.assertRaisesRegex(exceptions.OctaviaClientException,
self._error_message,
self.api.flavorprofile_delete,
FAKE_FVPF)

View File

@ -38,9 +38,7 @@ class TestAmphora(fakes.TestOctaviaClient):
]}
self.api_mock = mock.Mock()
self.api_mock.amphora_list.return_value = info_list
self.api_mock.amphora_show.return_value = {
"amphora": info_list['amphorae'][0],
}
self.api_mock.amphora_show.return_value = info_list['amphorae'][0]
lb_client = self.app.client_manager
lb_client.load_balancer = self.api_mock
@ -130,6 +128,34 @@ class TestAmphoraConfigure(TestAmphora):
self.api_mock.amphora_configure.assert_called_with(
amphora_id=self._amp.id)
@mock.patch('osc_lib.utils.wait_for_status')
def test_amphora_configure_linked_wait(self, mock_wait):
arglist = [self._amp.id, '--wait']
verify_list = [('amphora_id', self._amp.id)]
parsed_args = self.check_parser(self.cmd, arglist, verify_list)
self.cmd.take_action(parsed_args)
self.api_mock.amphora_configure.assert_called_with(
amphora_id=self._amp.id)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._amp.loadbalancer_id,
sleep_time=mock.ANY,
status_field='provisioning_status')
@mock.patch('osc_lib.utils.wait_for_status')
def test_amphora_configure_unlinked_wait(self, mock_wait):
self.api_mock.amphora_show.return_value.pop('loadbalancer_id')
arglist = [self._amp.id, '--wait']
verify_list = [('amphora_id', self._amp.id)]
parsed_args = self.check_parser(self.cmd, arglist, verify_list)
self.cmd.take_action(parsed_args)
self.api_mock.amphora_configure.assert_called_with(
amphora_id=self._amp.id)
# TODO(rm_work): No wait expected if the amp isn't linked to an LB?
mock_wait.assert_not_called()
class TestAmphoraFailover(TestAmphora):
def setUp(self):
@ -144,3 +170,46 @@ class TestAmphoraFailover(TestAmphora):
self.cmd.take_action(parsed_args)
self.api_mock.amphora_failover.assert_called_with(
amphora_id=self._amp.id)
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('osc_lib.utils.wait_for_delete')
def test_amphora_failover_linked_wait(self, mock_wait_delete,
mock_wait_active):
arglist = [self._amp.id, '--wait']
verify_list = [
('amphora_id', self._amp.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verify_list)
self.cmd.take_action(parsed_args)
self.api_mock.amphora_failover.assert_called_with(
amphora_id=self._amp.id)
mock_wait_active.assert_called_once_with(
status_f=mock.ANY,
res_id=self._amp.loadbalancer_id,
sleep_time=mock.ANY,
status_field='provisioning_status')
mock_wait_delete.assert_not_called()
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('osc_lib.utils.wait_for_delete')
def test_amphora_failover_unlinked_wait(self, mock_wait_delete,
mock_wait_active):
self.api_mock.amphora_show.return_value.pop('loadbalancer_id')
arglist = [self._amp.id, '--wait']
verify_list = [
('amphora_id', self._amp.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verify_list)
self.cmd.take_action(parsed_args)
self.api_mock.amphora_failover.assert_called_with(
amphora_id=self._amp.id)
mock_wait_active.assert_not_called()
mock_wait_delete.assert_called_once_with(
manager=mock.ANY,
res_id=self._amp.id,
sleep_time=mock.ANY,
status_field='provisioning_status')

View File

@ -79,6 +79,24 @@ class TestHealthMonitorDelete(TestHealthMonitor):
self.api_mock.health_monitor_delete.assert_called_with(
health_monitor_id=self._hm.id)
@mock.patch('osc_lib.utils.wait_for_delete')
def test_health_monitor_delete_wait(self, mock_wait):
arglist = [self._hm.id, '--wait']
verifylist = [
('health_monitor', self._hm.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.health_monitor_delete.assert_called_with(
health_monitor_id=self._hm.id)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self._hm.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_health_monitor_delete_failure(self):
arglist = ['unknown_hm']
verifylist = [
@ -131,6 +149,47 @@ class TestHealthMonitorCreate(TestHealthMonitor):
self.api_mock.health_monitor_create.assert_called_with(
json={'healthmonitor': self.hm_info})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_health_monitor_attrs')
def test_health_monitor_create_wait(self, mock_client, mock_wait):
self.hm_info['pools'] = [{'id': 'mock_pool_id'}]
mock_client.return_value = self.hm_info
self.api_mock.pool_show.return_value = {
'loadbalancers': [{'id': 'mock_lb_id'}]}
self.api_mock.health_monitor_show.return_value = self.hm_info
arglist = ['mock_pool_id',
'--name', self._hm.name,
'--delay', str(self._hm.delay),
'--timeout', str(self._hm.timeout),
'--max-retries', str(self._hm.max_retries),
'--type', self._hm.type.lower(),
'--http-method', self._hm.http_method.lower(),
'--http-version', str(self._hm.http_version),
'--domain-name', self._hm.domain_name,
'--wait']
verifylist = [
('pool', 'mock_pool_id'),
('name', self._hm.name),
('delay', str(self._hm.delay)),
('timeout', str(self._hm.timeout)),
('max_retries', self._hm.max_retries),
('type', self._hm.type),
('http_method', self._hm.http_method),
('http_version', self._hm.http_version),
('domain_name', self._hm.domain_name),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.health_monitor_create.assert_called_with(
json={'healthmonitor': self.hm_info})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id='mock_lb_id',
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestHealthMonitorShow(TestHealthMonitor):
@ -180,6 +239,25 @@ class TestHealthMonitorSet(TestHealthMonitor):
'name': 'new_name', 'http_version': self._hm.http_version,
'domain_name': self._hm.domain_name}})
@mock.patch('osc_lib.utils.wait_for_status')
def test_health_monitor_set_wait(self, mock_wait):
arglist = [self._hm.id, '--name', 'new_name', '--wait']
verifylist = [
('health_monitor', self._hm.id),
('name', 'new_name'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.health_monitor_set.assert_called_with(
self._hm.id, json={'healthmonitor': {'name': 'new_name'}})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._hm.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestHealthMonitorUnset(TestHealthMonitor):
PARAMETERS = ('name', 'domain_name', 'expected_codes', 'http_method',
@ -207,6 +285,9 @@ class TestHealthMonitorUnset(TestHealthMonitor):
def test_hm_unset_name(self):
self._test_hm_unset_param('name')
def test_hm_unset_name_wait(self):
self._test_hm_unset_param_wait('name')
def test_hm_unset_url_path(self):
self._test_hm_unset_param('url_path')
@ -225,6 +306,28 @@ class TestHealthMonitorUnset(TestHealthMonitor):
self.api_mock.health_monitor_set.assert_called_once_with(
self._hm.id, json=ref_body)
@mock.patch('osc_lib.utils.wait_for_status')
def _test_hm_unset_param_wait(self, param, mock_wait):
self.api_mock.health_monitor_set.reset_mock()
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._hm.id, '--%s' % arg_param, '--wait']
ref_body = {'healthmonitor': {param: None}}
verifylist = [
('health_monitor', self._hm.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.health_monitor_set.assert_called_once_with(
self._hm.id, json=ref_body)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._hm.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_hm_unset_all(self):
self.api_mock.health_monitor_set.reset_mock()
ref_body = {'healthmonitor': {x: None for x in self.PARAMETERS}}

View File

@ -95,6 +95,24 @@ class TestL7PolicyDelete(TestL7Policy):
self.api_mock.l7policy_delete.assert_called_with(
l7policy_id=self._l7po.id)
@mock.patch('osc_lib.utils.wait_for_delete')
def test_l7policy_delete_wait(self, mock_wait):
arglist = [self._l7po.id, '--wait']
verifylist = [
('l7policy', self._l7po.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7policy_delete.assert_called_with(
l7policy_id=self._l7po.id)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self._l7po.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_l7policy_delete_failure(self):
arglist = ['unknown_policy']
verifylist = [
@ -147,6 +165,47 @@ class TestL7PolicyCreate(TestL7Policy):
'redirect_pool_id': self._l7po.redirect_pool_id
}})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_l7policy_attrs')
def test_l7policy_create_wait(self, mock_attrs, mock_wait):
mock_attrs.return_value = {
'listener_id': self._l7po.listener_id,
'name': self._l7po.name,
'action': 'REDIRECT_TO_POOL',
'redirect_pool_id': self._l7po.redirect_pool_id
}
self.api_mock.listener_show.return_value = {
'loadbalancers': [{'id': 'mock_lb_id'}]}
self.api_mock.l7policy_show.return_value = self.l7po_info
arglist = ['mock_li_id',
'--name', self._l7po.name,
'--action', 'REDIRECT_TO_POOL'.lower(),
'--redirect-pool', self._l7po.redirect_pool_id,
'--wait']
verifylist = [
('listener', 'mock_li_id'),
('name', self._l7po.name),
('action', 'REDIRECT_TO_POOL'),
('redirect_pool', self._l7po.redirect_pool_id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7policy_create.assert_called_with(
json={'l7policy': {
'listener_id': self._l7po.listener_id,
'name': self._l7po.name,
'action': 'REDIRECT_TO_POOL',
'redirect_pool_id': self._l7po.redirect_pool_id
}})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id='mock_lb_id',
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestL7PolicyShow(TestL7Policy):
@ -191,6 +250,25 @@ class TestL7PolicySet(TestL7Policy):
self.api_mock.l7policy_set.assert_called_with(
self._l7po.id, json={'l7policy': {'name': 'new_name'}})
@mock.patch('osc_lib.utils.wait_for_status')
def test_l7policy_set_wait(self, mock_wait):
arglist = [self._l7po.id, '--name', 'new_name', '--wait']
verifylist = [
('l7policy', self._l7po.id),
('name', 'new_name'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7policy_set.assert_called_with(
self._l7po.id, json={'l7policy': {'name': 'new_name'}})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._l7po.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestL7PolicyUnset(TestL7Policy):
PARAMETERS = ('name', 'description', 'redirect_http_code')
@ -205,6 +283,9 @@ class TestL7PolicyUnset(TestL7Policy):
def test_l7policy_unset_name(self):
self._test_l7policy_unset_param('name')
def test_l7policy_unset_name_wait(self):
self._test_l7policy_unset_param_wait('name')
def test_l7policy_unset_redirect_http_code(self):
self._test_l7policy_unset_param('redirect_http_code')
@ -223,6 +304,28 @@ class TestL7PolicyUnset(TestL7Policy):
self.api_mock.l7policy_set.assert_called_once_with(
self._l7po.id, json=ref_body)
@mock.patch('osc_lib.utils.wait_for_status')
def _test_l7policy_unset_param_wait(self, param, mock_wait):
self.api_mock.l7policy_set.reset_mock()
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._l7po.id, '--%s' % arg_param, '--wait']
ref_body = {'l7policy': {param: None}}
verifylist = [
('l7policy', self._l7po.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7policy_set.assert_called_once_with(
self._l7po.id, json=ref_body)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._l7po.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_l7policy_unset_all(self):
self.api_mock.l7policy_set.reset_mock()
ref_body = {'l7policy': {x: None for x in self.PARAMETERS}}

View File

@ -89,6 +89,36 @@ class TestL7RuleDelete(TestL7Rule):
l7policy_id=self._l7po.id
)
@mock.patch('functools.partial')
@mock.patch('osc_lib.utils.wait_for_delete')
@mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs')
def test_l7rule_delete_wait(self, mock_attrs, mock_wait, mock_partial):
mock_attrs.return_value = {
'l7policy_id': self._l7po.id,
'l7rule_id': self._l7ru.id,
}
arglist = [self._l7po.id, self._l7ru.id, '--wait']
verifylist = [
('l7policy', self._l7po.id),
('l7rule', self._l7ru.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7rule_delete.assert_called_with(
l7rule_id=self._l7ru.id,
l7policy_id=self._l7po.id
)
mock_partial.assert_called_once_with(
self.api_mock.l7rule_show, self._l7po.id
)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self._l7ru.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestL7RuleCreate(TestL7Rule):
@ -131,6 +161,49 @@ class TestL7RuleCreate(TestL7Rule):
'type': 'HOST_NAME'}
})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs')
def test_l7rule_create_wait(self, mock_attrs, mock_wait):
mock_attrs.return_value = {
'l7policy_id': self._l7po.id,
'compare-type': 'ENDS_WITH',
'value': '.example.com',
'type': 'HOST_NAME'
}
self.api_mock.l7policy_show.return_value = {
'listener_id': 'mock_listener_id'}
self.api_mock.listener_show.return_value = {
'loadbalancers': [{'id': 'mock_lb_id'}]}
self.api_mock.l7rule_show.return_value = self.l7rule_info
arglist = [self._l7po.id,
'--compare-type', 'ENDS_WITH',
'--value', '.example.com',
'--type', 'HOST_NAME'.lower(),
'--wait']
verifylist = [
('l7policy', self._l7po.id),
('compare_type', 'ENDS_WITH'),
('value', '.example.com'),
('type', 'HOST_NAME'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7rule_create.assert_called_with(
l7policy_id=self._l7po.id,
json={'rule': {
'compare-type': 'ENDS_WITH',
'value': '.example.com',
'type': 'HOST_NAME'}
})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id='mock_lb_id',
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestL7RuleShow(TestL7Rule):
@ -188,6 +261,43 @@ class TestL7RuleSet(TestL7Rule):
l7policy_id=self._l7po.id,
json={'rule': {'admin_state_up': False}})
@mock.patch('functools.partial')
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_l7rule_attrs')
def test_l7rule_set_wait(self, mock_attrs, mock_wait, mock_partial):
mock_attrs.return_value = {
'admin_state_up': False,
'l7policy_id': self._l7po.id,
'l7rule_id': self._l7ru.id
}
arglist = [
self._l7po.id,
self._l7ru.id,
'--disable',
'--wait',
]
verifylist = [
('l7policy', self._l7po.id),
('l7rule', self._l7ru.id),
('disable', True),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7rule_set.assert_called_with(
l7rule_id=self._l7ru.id,
l7policy_id=self._l7po.id,
json={'rule': {'admin_state_up': False}})
mock_partial.assert_called_once_with(
self.api_mock.l7rule_show, self._l7po.id
)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._l7ru.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestL7RuleUnset(TestL7Rule):
PARAMETERS = ('invert', 'key')
@ -199,6 +309,9 @@ class TestL7RuleUnset(TestL7Rule):
def test_l7rule_unset_invert(self):
self._test_l7rule_unset_param('invert')
def test_l7rule_unset_invert_wait(self):
self._test_l7rule_unset_param_wait('invert')
def test_l7rule_unset_key(self):
self._test_l7rule_unset_param('key')
@ -217,6 +330,33 @@ class TestL7RuleUnset(TestL7Rule):
self.api_mock.l7rule_set.assert_called_once_with(
l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json=ref_body)
@mock.patch('functools.partial')
@mock.patch('osc_lib.utils.wait_for_status')
def _test_l7rule_unset_param_wait(self, param, mock_wait, mock_partial):
self.api_mock.l7rule_set.reset_mock()
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._l7po.id, self._l7ru.id, '--%s' % arg_param, '--wait']
ref_body = {'rule': {param: None}}
verifylist = [
('l7policy', self._l7po.id),
('l7rule_id', self._l7ru.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.l7rule_set.assert_called_once_with(
l7policy_id=self._l7po.id, l7rule_id=self._l7ru.id, json=ref_body)
mock_partial.assert_called_once_with(
self.api_mock.l7rule_show, self._l7po.id
)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._l7ru.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_l7rule_unset_all(self):
self.api_mock.l7rule_set.reset_mock()
ref_body = {'rule': {x: None for x in self.PARAMETERS}}

View File

@ -86,6 +86,24 @@ class TestListenerDelete(TestListener):
self.api_mock.listener_delete.assert_called_with(
listener_id=self._listener.id)
@mock.patch('osc_lib.utils.wait_for_delete')
def test_listener_delete_wait(self, mock_wait):
arglist = [self._listener.id, '--wait']
verifylist = [
('listener', self._listener.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.listener_delete.assert_called_with(
listener_id=self._listener.id)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self._listener.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_listener_delete_failure(self):
arglist = ['unknown_lb']
verifylist = [
@ -127,6 +145,35 @@ class TestListenerCreate(TestListener):
self.api_mock.listener_create.assert_called_with(
json={'listener': self.listener_info})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs')
def test_listener_create_wait(self, mock_client, mock_wait):
self.listener_info['loadbalancers'] = [{'id': 'mock_lb_id'}]
mock_client.return_value = self.listener_info
self.api_mock.listener_show.return_value = self.listener_info
arglist = ['mock_lb_id',
'--name', self._listener.name,
'--protocol', 'HTTP',
'--protocol-port', '80',
'--wait']
verifylist = [
('loadbalancer', 'mock_lb_id'),
('name', self._listener.name),
('protocol', 'HTTP'),
('protocol_port', '80'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.listener_create.assert_called_with(
json={'listener': self.listener_info})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self.listener_info['loadbalancers'][0]['id'],
sleep_time=mock.ANY,
status_field='provisioning_status')
@mock.patch('octaviaclient.osc.v2.utils.get_listener_attrs')
def test_tls_listener_create(self, mock_client):
mock_client.return_value = self.listener_info
@ -271,6 +318,25 @@ class TestListenerSet(TestListener):
'allowed_cidrs': self._listener.allowed_cidrs,
}})
@mock.patch('osc_lib.utils.wait_for_status')
def test_listener_set_wait(self, mock_wait):
arglist = [self._listener.id, '--name', 'new_name', '--wait']
verifylist = [
('listener', self._listener.id),
('name', 'new_name'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.listener_set.assert_called_with(
self._listener.id, json={'listener': {'name': 'new_name'}})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._listener.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestListenerStatsShow(TestListener):
@ -311,6 +377,9 @@ class TestListenerUnset(TestListener):
def test_listener_unset_name(self):
self._test_listener_unset_param('name')
def test_listener_unset_name_wait(self):
self._test_listener_unset_param_wait('name')
def test_listener_unset_description(self):
self._test_listener_unset_param('description')
@ -371,6 +440,31 @@ class TestListenerUnset(TestListener):
self.api_mock.listener_set.assert_called_once_with(
self._listener.id, json=ref_body)
@mock.patch('osc_lib.utils.wait_for_status')
def _test_listener_unset_param_wait(self, param, mock_wait):
self.api_mock.listener_set.reset_mock()
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._listener.id, '--%s' % arg_param, '--wait']
# Handle the special rename case of default_pool rename
if param == 'default_pool':
param = 'default_pool_id'
ref_body = {'listener': {param: None}}
verifylist = [
('listener', self._listener.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.listener_set.assert_called_once_with(
self._listener.id, json=ref_body)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._listener.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_listener_unset_all(self):
self.api_mock.listener_set.reset_mock()
ref_body = {'listener': {x: None for x in self.PARAMETERS}}

View File

@ -15,6 +15,7 @@ import copy
import itertools
import mock
import munch
from osc_lib import exceptions
from oslo_utils import uuidutils
@ -214,6 +215,24 @@ class TestLoadBalancerDelete(TestLoadBalancer):
self.api_mock.load_balancer_delete.assert_called_with(
lb_id=self._lb.id)
@mock.patch('osc_lib.utils.wait_for_delete')
def test_load_balancer_delete_wait(self, mock_wait):
arglist = [self._lb.id, '--wait']
verifylist = [
('loadbalancer', self._lb.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.load_balancer_delete.assert_called_with(
lb_id=self._lb.id)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self.lb_info['id'],
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_load_balancer_delete_failure(self):
arglist = ['unknown_lb']
verifylist = [
@ -257,6 +276,34 @@ class TestLoadBalancerCreate(TestLoadBalancer):
self.api_mock.load_balancer_create.assert_called_with(
json={'loadbalancer': self.lb_info})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs')
def test_load_balancer_create_wait(self, mock_client, mock_wait):
mock_client.return_value = self.lb_info
self.api_mock.load_balancer_show.return_value = self.lb_info
arglist = ['--name', self._lb.name,
'--vip-network-id', self._lb.vip_network_id,
'--project', self._lb.project_id,
'--flavor', self._lb.flavor_id,
'--wait']
verifylist = [
('name', self._lb.name),
('vip_network_id', self._lb.vip_network_id),
('project', self._lb.project_id),
('flavor', self._lb.flavor_id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.load_balancer_create.assert_called_with(
json={'loadbalancer': self.lb_info})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self.lb_info['id'],
sleep_time=mock.ANY,
status_field='provisioning_status')
@mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs')
def test_load_balancer_create_with_qos_policy(self, mock_client):
qos_policy_id = 'qos_id'
@ -322,6 +369,8 @@ class TestLoadBalancerCreate(TestLoadBalancer):
# subtract comb's keys from attrs_list
filtered_attrs = {k: v for k, v in attrs_list.items() if (
k not in comb)}
# Add the 'wait' attribute, which isn't part of an LB directly
filtered_attrs['wait'] = False
mock_client.return_value = filtered_attrs
if not any(k in filtered_attrs for k in args) or all(
k in filtered_attrs for k in ("vip_network_id",
@ -333,7 +382,7 @@ class TestLoadBalancerCreate(TestLoadBalancer):
filtered_attrs)
else:
try:
self.cmd.take_action(filtered_attrs)
self.cmd.take_action(munch.Munch(filtered_attrs))
except exceptions.CommandError as e:
self.fail("%s raised unexpectedly" % e)
@ -393,6 +442,39 @@ class TestLoadBalancerSet(TestLoadBalancer):
}
})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs')
def test_load_balancer_set_wait(self, mock_attrs, mock_wait):
qos_policy_id = uuidutils.generate_uuid()
mock_attrs.return_value = {
'loadbalancer_id': self._lb.id,
'name': 'new_name',
'vip_qos_policy_id': qos_policy_id,
}
arglist = [self._lb.id, '--name', 'new_name',
'--vip-qos-policy-id', qos_policy_id, '--wait']
verifylist = [
('loadbalancer', self._lb.id),
('name', 'new_name'),
('vip_qos_policy_id', qos_policy_id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.load_balancer_set.assert_called_with(
self._lb.id, json={
'loadbalancer': {
'name': 'new_name',
'vip_qos_policy_id': qos_policy_id,
}
})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self.lb_info['id'],
sleep_time=mock.ANY,
status_field='provisioning_status')
@mock.patch('octaviaclient.osc.v2.utils.get_loadbalancer_attrs')
def test_load_balancer_remove_qos_policy(self, mock_attrs):
mock_attrs.return_value = {
@ -477,6 +559,24 @@ class TestLoadBalancerFailover(TestLoadBalancer):
self.api_mock.load_balancer_failover.assert_called_with(
lb_id=self._lb.id)
@mock.patch('osc_lib.utils.wait_for_status')
def test_load_balancer_failover_wait(self, mock_wait):
arglist = [self._lb.id, '--wait']
verifylist = [
('loadbalancer', self._lb.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.load_balancer_failover.assert_called_with(
lb_id=self._lb.id)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._lb.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestLoadBalancerUnset(TestLoadBalancer):
PARAMETERS = ('name', 'description', 'vip_qos_policy_id')
@ -490,6 +590,9 @@ class TestLoadBalancerUnset(TestLoadBalancer):
def test_load_balancer_unset_name(self):
self._test_load_balancer_unset_param('name')
def test_load_balancer_unset_name_wait(self):
self._test_load_balancer_unset_param_wait('name')
def test_load_balancer_unset_description(self):
self._test_load_balancer_unset_param('description')
@ -511,6 +614,28 @@ class TestLoadBalancerUnset(TestLoadBalancer):
self.api_mock.load_balancer_set.assert_called_once_with(
self._lb.id, json=ref_body)
@mock.patch('osc_lib.utils.wait_for_status')
def _test_load_balancer_unset_param_wait(self, param, mock_wait):
self.api_mock.load_balancer_set.reset_mock()
ref_body = {'loadbalancer': {param: None}}
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._lb.id, '--%s' % arg_param, '--wait']
verifylist = [
('loadbalancer', self._lb.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.load_balancer_set.assert_called_once_with(
self._lb.id, json=ref_body)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self.lb_info['id'],
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_load_balancer_unset_all(self):
self.api_mock.load_balancer_set.reset_mock()
ref_body = {'loadbalancer': {x: None for x in self.PARAMETERS}}

View File

@ -115,6 +115,44 @@ class TestCreateMember(TestMember):
'admin_state_up': True,
'backup': False}})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_member_attrs')
def test_member_create_wait(self, mock_attrs, mock_wait):
mock_attrs.return_value = {
'ip_address': '192.0.2.122',
'protocol_port': self._mem.protocol_port,
'weight': self._mem.weight,
'admin_state_up': True,
'pool_id': self._mem.pool_id,
'backup': False}
self.api_mock.pool_show.return_value = {
'loadbalancers': [{'id': 'mock_lb_id'}]}
self.api_mock.member_show.return_value = self.mem_info
arglist = ['pool_id', '--address', '192.0.2.122',
'--protocol-port', '80',
'--weight', '1', '--enable', '--disable-backup', '--wait']
verifylist = [
('address', '192.0.2.122'),
('protocol_port', 80),
('weight', 1),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.member_create.assert_called_with(
pool_id=self._mem.pool_id, json={
'member': {'ip_address': '192.0.2.122',
'protocol_port': self._mem.protocol_port,
'weight': self._mem.weight,
'admin_state_up': True,
'backup': False}})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id='mock_lb_id',
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestMemberDelete(TestMember):
@ -124,15 +162,44 @@ class TestMemberDelete(TestMember):
@mock.patch('octaviaclient.osc.v2.utils.get_member_attrs')
def test_member_delete(self, mock_attrs):
mock_attrs.return_value = {'pool_id': 'test_pool_id',
'member_id': 'test_mem_id'}
arglist = ['test_pool_id', 'test_mem_id']
verifylist = []
mock_attrs.return_value = {'pool_id': self._mem.pool_id,
'member_id': self._mem.id}
arglist = [self._mem.pool_id, self._mem.id]
verifylist = [
('pool', self._mem.pool_id),
('member', self._mem.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.member_delete.assert_called_with(
pool_id='test_pool_id', member_id='test_mem_id')
pool_id=self._mem.pool_id, member_id=self._mem.id)
@mock.patch('functools.partial')
@mock.patch('osc_lib.utils.wait_for_delete')
@mock.patch('octaviaclient.osc.v2.utils.get_member_attrs')
def test_member_delete_wait(self, mock_attrs, mock_wait, mock_partial):
mock_attrs.return_value = {'pool_id': self._mem.pool_id,
'member_id': self._mem.id}
arglist = [self._mem.pool_id, self._mem.id, '--wait']
verifylist = [
('pool', self._mem.pool_id),
('member', self._mem.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.member_delete.assert_called_with(
pool_id=self._mem.pool_id, member_id=self._mem.id)
mock_partial.assert_called_once_with(
self.api_mock.member_show, self._mem.pool_id
)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self._mem.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestMemberSet(TestMember):
@ -143,25 +210,56 @@ class TestMemberSet(TestMember):
@mock.patch('octaviaclient.osc.v2.utils.get_member_attrs')
def test_member_set(self, mock_attrs):
mock_attrs.return_value = {'pool_id': 'test_pool_id',
'member_id': 'test_mem_id',
mock_attrs.return_value = {'pool_id': self._mem.pool_id,
'member_id': self._mem.id,
'name': 'new_name',
'backup': True}
arglist = ['test_pool_id', 'test_mem_id', '--name',
arglist = [self._mem.pool_id, self._mem.id, '--name',
'new_name', '--enable-backup']
verifylist = [
('pool', 'test_pool_id'),
('member', 'test_mem_id'),
('name', 'new_name')
('pool', self._mem.pool_id),
('member', self._mem.id),
('name', 'new_name'),
('enable_backup', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.member_set.assert_called_with(
pool_id='test_pool_id', member_id='test_mem_id',
pool_id=self._mem.pool_id, member_id=self._mem.id,
json={'member': {'name': 'new_name',
'backup': True}})
@mock.patch('functools.partial')
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_member_attrs')
def test_member_set_wait(self, mock_attrs, mock_wait, mock_partial):
mock_attrs.return_value = {'pool_id': self._mem.pool_id,
'member_id': self._mem.id,
'name': 'new_name'}
arglist = [self._mem.pool_id, self._mem.id, '--name',
'new_name', '--wait']
verifylist = [
('pool', self._mem.pool_id),
('member', self._mem.id),
('name', 'new_name'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.member_set.assert_called_with(
pool_id=self._mem.pool_id, member_id=self._mem.id,
json={'member': {'name': 'new_name'}})
mock_partial.assert_called_once_with(
self.api_mock.member_show, self._mem.pool_id
)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._mem.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestMemberShow(TestMember):
@ -211,6 +309,9 @@ class TestMemberUnset(TestMember):
def test_member_unset_name(self):
self._test_member_unset_param('name')
def test_member_unset_name_wait(self):
self._test_member_unset_param_wait('name')
def test_member_unset_weight(self):
self._test_member_unset_param('weight')
@ -219,7 +320,10 @@ class TestMemberUnset(TestMember):
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._mem.pool_id, self._mem.id, '--%s' % arg_param]
ref_body = {'member': {param: None}}
verifylist = [('member', self._mem.id)]
verifylist = [
('pool', self._mem.pool_id),
('member', self._mem.id),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -227,6 +331,34 @@ class TestMemberUnset(TestMember):
self.api_mock.member_set.assert_called_once_with(
pool_id=self._mem.pool_id, member_id=self._mem.id, json=ref_body)
@mock.patch('functools.partial')
@mock.patch('osc_lib.utils.wait_for_status')
def _test_member_unset_param_wait(self, param, mock_wait, mock_partial):
self.api_mock.member_set.reset_mock()
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._mem.pool_id, self._mem.id, '--%s' % arg_param,
'--wait']
ref_body = {'member': {param: None}}
verifylist = [
('pool', self._mem.pool_id),
('member', self._mem.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.member_set.assert_called_once_with(
pool_id=self._mem.pool_id, member_id=self._mem.id, json=ref_body)
mock_partial.assert_called_once_with(
self.api_mock.member_show, self._mem.pool_id
)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._mem.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_member_unset_all(self):
self.api_mock.pool_set.reset_mock()
ref_body = {'member': {x: None for x in self.PARAMETERS}}

View File

@ -77,6 +77,24 @@ class TestPoolDelete(TestPool):
self.api_mock.pool_delete.assert_called_with(
pool_id=self._po.id)
@mock.patch('osc_lib.utils.wait_for_delete')
def test_pool_delete_wait(self, mock_wait):
arglist = [self._po.id, '--wait']
verifylist = [
('pool', self._po.id),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.pool_delete.assert_called_with(
pool_id=self._po.id)
mock_wait.assert_called_once_with(
manager=mock.ANY,
res_id=self._po.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_listener_delete_failure(self):
arglist = ['unknown_pool']
verifylist = [
@ -127,6 +145,36 @@ class TestPoolCreate(TestPool):
self.api_mock.pool_create.assert_called_with(
json={'pool': self.pool_info})
@mock.patch('osc_lib.utils.wait_for_status')
@mock.patch('octaviaclient.osc.v2.utils.get_pool_attrs')
def test_pool_create_wait(self, mock_attrs, mock_wait):
self.pool_info['loadbalancers'] = [{'id': 'mock_lb_id'}]
mock_attrs.return_value = self.pool_info
self.api_mock.pool_show.return_value = self.pool_info
arglist = ['--loadbalancer', 'mock_lb_id',
'--name', self._po.name,
'--protocol', 'HTTP',
'--lb-algorithm', 'ROUND_ROBIN',
'--wait']
verifylist = [
('loadbalancer', 'mock_lb_id'),
('name', self._po.name),
('protocol', 'HTTP'),
('lb_algorithm', 'ROUND_ROBIN'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.pool_create.assert_called_with(
json={'pool': self.pool_info})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id='mock_lb_id',
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestPoolShow(TestPool):
@ -175,6 +223,24 @@ class TestPoolSet(TestPool):
'crl_container_ref': new_crl_id,
'tls_enabled': True}})
@mock.patch('osc_lib.utils.wait_for_status')
def test_pool_set_wait(self, mock_wait):
arglist = [self._po.id, '--name', 'new_name', '--wait']
verifylist = [
('pool', self._po.id),
('name', 'new_name'),
('wait', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.pool_set.assert_called_with(
self._po.id, json={'pool': {'name': 'new_name'}})
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._po.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
class TestPoolUnset(TestPool):
PARAMETERS = ('name', 'description', 'ca_tls_container_ref',
@ -188,6 +254,9 @@ class TestPoolUnset(TestPool):
def test_pool_unset_name(self):
self._test_pool_unset_param('name')
def test_pool_unset_name_wait(self):
self._test_pool_unset_param_wait('name')
def test_pool_unset_description(self):
self._test_pool_unset_param('description')
@ -218,6 +287,28 @@ class TestPoolUnset(TestPool):
self.api_mock.pool_set.assert_called_once_with(
self._po.id, json=ref_body)
@mock.patch('osc_lib.utils.wait_for_status')
def _test_pool_unset_param_wait(self, param, mock_wait):
self.api_mock.pool_set.reset_mock()
arg_param = param.replace('_', '-') if '_' in param else param
arglist = [self._po.id, '--%s' % arg_param, '--wait']
ref_body = {'pool': {param: None}}
verifylist = [
('pool', self._po.id),
('wait', True),
]
for ref_param in self.PARAMETERS:
verifylist.append((ref_param, param == ref_param))
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.cmd.take_action(parsed_args)
self.api_mock.pool_set.assert_called_once_with(
self._po.id, json=ref_body)
mock_wait.assert_called_once_with(
status_f=mock.ANY,
res_id=self._po.id,
sleep_time=mock.ANY,
status_field='provisioning_status')
def test_pool_unset_all(self):
self.api_mock.pool_set.reset_mock()
ref_body = {'pool': {x: None for x in self.PARAMETERS}}

View File

@ -0,0 +1,6 @@
---
features:
- |
Commands that can cause loadbalancers to enter an immutable status (Create,
Update, and Delete operations) now have a ``--wait`` argument. If set, the
client will continue to poll until the status is no longer immutable.