Add sw-manager --active show command

- Add a new --active option for 'show' commands to only show
stages, phases, and steps that are in progress.

- Refactor initialization and execution of the CLI commands
to reuse common code and simplify adding new update orchestrations.

- Add unit tests for all strategies and action types for the CLI
 which increases test coverage for shell.py from 69 to 95 percent

Story: 2008137
Task: 42199
Signed-off-by: albailey <Al.Bailey@windriver.com>
Change-Id: I4280ef41ba7586c822d4d39629e51b4592fd996a
This commit is contained in:
albailey 2021-03-18 16:58:19 -05:00 committed by Al Bailey
parent 2368f9128c
commit 483dc779b5
4 changed files with 666 additions and 584 deletions

View File

@ -11,76 +11,367 @@ import sys
from nfv_client import sw_update
REGISTERED_STRATEGIES = {}
def register_strategy(cmd_area, strategy_name):
"""
Registers a parser command with an update strategy name
:param cmd_area: the parser command to register
:param strategy_name: the strategy to associate with this parser
"""
REGISTERED_STRATEGIES[cmd_area] = strategy_name
def get_strategy_name(cmd_area):
"""
Determines the strategy name for a parser command
:param cmd_area: the parser command to lookup
:returns: the strategy name associated with the parser
:raises: ValueError if the parser was never registered
"""
strategy_name = REGISTERED_STRATEGIES.get(cmd_area, None)
if strategy_name is None:
raise ValueError("Unknown command area, %s, given" % cmd_area)
return strategy_name
def get_extra_create_args(cmd_area, args):
"""
Return the extra create arguments supported by a strategy type
:param cmd_area: the strategy that supports additional create arguments
:param args: the parsed arguments to extract the additional fields from
:returns: a dictionary of additional kwargs for the create_strategy command
:raises: ValueError if a strategy has been registered but not update here
"""
if 'patch-strategy' == cmd_area:
# no additional kwargs for patch
return {}
elif 'upgrade-strategy' == cmd_area:
# upgrade supports: complete_upgrade
return {'complete_upgrade': args.complete_upgrade}
elif 'fw-update-strategy' == cmd_area:
# no additional kwargs for firmware update
return {}
elif 'kube-upgrade-strategy' == cmd_area:
# kube upgrade supports: to_version
return {'to_version': args.to_version}
else:
raise ValueError("Unknown command area, %s, given" % cmd_area)
def add_list_arg(some_cmd, some_arg, some_list):
"""
Adds an argument to a command accepting a list of valid values.
:param some_cmd: a command parser object that is adding a new argument
:param some_arg: a string indicating the new argument. ex: --foo
:param some_list: a list of valid values for the argument.
The list cannot be empty. The first item in the list is the default
"""
default = some_list[0]
some_cmd.add_argument(some_arg,
default=default,
choices=some_list,
help='defaults to ' + default)
def setup_abort_cmd(parser):
"""
Sets up an 'abort' command for a strategy command parser.
ex: sw-manager patch-strategy abort <some args>
:param parser: the strategy parser to add the create command to.
"""
abort_cmd = parser.add_parser('abort',
help='Abort a strategy')
abort_cmd.set_defaults(cmd='abort')
abort_cmd.add_argument('--stage-id',
help='stage identifier to abort')
return abort_cmd
def setup_apply_cmd(parser):
"""
Sets up an 'apply' command for a strategy command parser.
ex: sw-manager patch-strategy apply <some args>
:param parser: the strategy parser to register the command under
"""
apply_cmd = parser.add_parser('apply',
help='Apply a strategy')
apply_cmd.set_defaults(cmd='apply')
apply_cmd.add_argument('--stage-id',
default=None,
help='stage identifier to apply')
return apply_cmd
def setup_create_cmd(parser,
controller_types,
storage_types,
worker_types,
instance_actions,
alarm_restrictions,
min_parallel=1,
max_parallel=5):
"""
Sets up a 'create' command for a strategy command parser.
ex: sw-manager patch-strategy create <some args>
:param parser: the strategy parser to register the command under
:param controller_types: list of the valid apply types for controller
:param storage_types: list of the valid apply types for storage
:param worker_types: list of the valid apply types for worker
:param instance_actions: list of valid VM actions during worker apply
:param alarm_restrictions: list of valid alarm restrictions
:param min_parallel: minimum value (inclusive) for updating parallel hosts
:param max_parallel: maximum value (inclusive) for updating parallel hosts
The lists cannot be empty. The first item in the lists is the default
"""
create_cmd = parser.add_parser('create', help='Create a strategy')
create_cmd.set_defaults(cmd='create')
add_list_arg(create_cmd, '--controller-apply-type', controller_types)
add_list_arg(create_cmd, '--storage-apply-type', storage_types)
add_list_arg(create_cmd, '--worker-apply-type', worker_types)
add_list_arg(create_cmd, '--instance-action', instance_actions)
add_list_arg(create_cmd, '--alarm-restrictions', alarm_restrictions)
create_cmd.add_argument('--max-parallel-worker-hosts',
type=int,
choices=range(min_parallel, max_parallel + 1),
help='maximum worker hosts to update in parallel')
return create_cmd
def setup_delete_cmd(parser):
"""
Sets up a 'delete' command for a strategy command parser.
ex: sw-manager patch-strategy delete <some args>
:param parser: the strategy parser to register the command under
"""
delete_cmd = parser.add_parser('delete', help='Delete a strategy')
delete_cmd.set_defaults(cmd='delete')
delete_cmd.add_argument('--force',
action='store_true',
help=argparse.SUPPRESS)
return delete_cmd
def setup_show_cmd(parser):
"""
Sets up a 'show' command for a strategy command parser.
ex: sw-manager patch-strategy show <some args>
:param parser: the strategy parser to register the command under
"""
show_cmd = parser.add_parser('show', help='Show a strategy')
show_cmd.set_defaults(cmd='show')
show_cmd.add_argument('--details',
action='store_true',
help='show strategy details')
show_cmd.add_argument('--active',
action='store_true',
help='show currently active strategy step')
return show_cmd
def setup_fw_update_parser(commands):
"""Firmware Update Strategy Commands"""
cmd_area = 'fw-update-strategy'
register_strategy(cmd_area, sw_update.STRATEGY_NAME_FW_UPDATE)
cmd_parser = commands.add_parser(cmd_area,
help='Firmware Update Strategy')
cmd_parser.set_defaults(cmd_area=cmd_area)
sub_cmds = cmd_parser.add_subparsers(title='Firmware Update Commands',
metavar='')
sub_cmds.required = True
# define the create command
# alarm restrictions, defaults to strict
create_strategy_cmd = setup_create_cmd(
sub_cmds,
[sw_update.APPLY_TYPE_IGNORE], # controller supports ignore
[sw_update.APPLY_TYPE_IGNORE], # storage supports ignore
[sw_update.APPLY_TYPE_SERIAL, # worker supports serial and parallel
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
[sw_update.INSTANCE_ACTION_STOP_START, # instance actions
sw_update.INSTANCE_ACTION_MIGRATE],
[sw_update.ALARM_RESTRICTIONS_STRICT, # alarm restrictions
sw_update.ALARM_RESTRICTIONS_RELAXED],
min_parallel=2,
max_parallel=5 # fw update supports 2..5 workers in parallel
)
# There are no additional create options for firmware update
# define the delete command
delete_strategy_cmd = setup_delete_cmd(sub_cmds)
# define the apply command
apply_strategy_cmd = setup_apply_cmd(sub_cmds)
# define the abort command
abort_strategy_cmd = setup_abort_cmd(sub_cmds)
# define the show command
show_strategy_cmd = setup_show_cmd(sub_cmds)
def setup_kube_upgrade_parser(commands):
# Kubernetes Upgrade Commands
kube_upgrade_parser = commands.add_parser('kube-upgrade-strategy',
help='Kubernetes Upgrade Strategy')
kube_upgrade_parser.set_defaults(cmd_area='kube-upgrade-strategy')
"""Kubernetes Upgrade Strategy Commands"""
kube_upgrade_cmds = kube_upgrade_parser.add_subparsers(
title='Kubernetes Upgrade Commands', metavar='')
kube_upgrade_cmds.required = True
cmd_area = 'kube-upgrade-strategy'
register_strategy(cmd_area, sw_update.STRATEGY_NAME_KUBE_UPGRADE)
cmd_parser = commands.add_parser(cmd_area,
help='Kubernetes Upgrade Strategy')
cmd_parser.set_defaults(cmd_area=cmd_area)
kube_upgrade_create_strategy_cmd \
= kube_upgrade_cmds.add_parser('create', help='Create a strategy')
kube_upgrade_create_strategy_cmd.set_defaults(cmd='create')
kube_upgrade_create_strategy_cmd.add_argument('--controller-apply-type',
default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
kube_upgrade_create_strategy_cmd.add_argument('--storage-apply-type',
default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
kube_upgrade_create_strategy_cmd.add_argument('--worker-apply-type',
default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL,
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
sub_cmds = cmd_parser.add_subparsers(title='Kubernetes Upgrade Commands',
metavar='')
sub_cmds.required = True
kube_upgrade_create_strategy_cmd.add_argument(
'--max-parallel-worker-hosts', type=int, choices=range(2, 6),
help='maximum worker hosts to update in parallel')
# define the create command
create_strategy_cmd = setup_create_cmd(
sub_cmds,
[sw_update.APPLY_TYPE_SERIAL, # controller supports serial only
sw_update.APPLY_TYPE_IGNORE],
[sw_update.APPLY_TYPE_SERIAL, # storage supports serial only
sw_update.APPLY_TYPE_IGNORE],
[sw_update.APPLY_TYPE_SERIAL, # worker supports serial and parallel
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
[sw_update.INSTANCE_ACTION_STOP_START, # instance actions
sw_update.INSTANCE_ACTION_MIGRATE],
[sw_update.ALARM_RESTRICTIONS_STRICT, # alarm restrictions
sw_update.ALARM_RESTRICTIONS_RELAXED],
min_parallel=2,
max_parallel=10 # kube upgrade supports 2..10 workers in parallel
)
kube_upgrade_create_strategy_cmd.add_argument('--instance-action',
default=sw_update.INSTANCE_ACTION_STOP_START,
choices=[sw_update.INSTANCE_ACTION_MIGRATE,
sw_update.INSTANCE_ACTION_STOP_START],
help='defaults to stop-start')
# add kube specific arguments to the create command
# The get_extra_create_args method is updated to align with these
# kube upgrade create requires 'to-version'
create_strategy_cmd.add_argument(
'--to-version',
required=True,
help='The kubernetes version')
kube_upgrade_create_strategy_cmd.add_argument('--alarm-restrictions',
default=sw_update.ALARM_RESTRICTIONS_STRICT,
choices=[sw_update.ALARM_RESTRICTIONS_STRICT,
sw_update.ALARM_RESTRICTIONS_RELAXED],
help='defaults to strict')
# define the delete command
delete_strategy_cmd = setup_delete_cmd(sub_cmds)
# define the apply command
apply_strategy_cmd = setup_apply_cmd(sub_cmds)
# define the abort command
abort_strategy_cmd = setup_abort_cmd(sub_cmds)
# define the show command
show_strategy_cmd = setup_show_cmd(sub_cmds)
kube_upgrade_create_strategy_cmd.add_argument(
'--to-version', required=True, help='The kubernetes version')
kube_upgrade_delete_strategy_cmd \
= kube_upgrade_cmds.add_parser('delete', help='Delete a strategy')
kube_upgrade_delete_strategy_cmd.set_defaults(cmd='delete')
kube_upgrade_delete_strategy_cmd.add_argument(
'--force', action='store_true', help=argparse.SUPPRESS)
def setup_patch_parser(commands):
"""Patch Strategy Commands"""
kube_upgrade_apply_strategy_cmd \
= kube_upgrade_cmds.add_parser('apply', help='Apply a strategy')
kube_upgrade_apply_strategy_cmd.set_defaults(cmd='apply')
kube_upgrade_apply_strategy_cmd.add_argument(
'--stage-id', default=None, help='stage identifier to apply')
cmd_area = 'patch-strategy'
register_strategy(cmd_area, sw_update.STRATEGY_NAME_SW_PATCH)
cmd_parser = commands.add_parser(cmd_area,
help='Patch Strategy')
cmd_parser.set_defaults(cmd_area=cmd_area)
kube_upgrade_abort_strategy_cmd \
= kube_upgrade_cmds.add_parser('abort', help='Abort a strategy')
kube_upgrade_abort_strategy_cmd.set_defaults(cmd='abort')
kube_upgrade_abort_strategy_cmd.add_argument(
'--stage-id', help='stage identifier to abort')
sub_cmds = cmd_parser.add_subparsers(title='Software Patch Commands',
metavar='')
sub_cmds.required = True
kube_upgrade_show_strategy_cmd \
= kube_upgrade_cmds.add_parser('show', help='Show a strategy')
kube_upgrade_show_strategy_cmd.set_defaults(cmd='show')
kube_upgrade_show_strategy_cmd.add_argument(
'--details', action='store_true', help='show strategy details')
# define the create command
# alarm restrictions, defaults to strict
create_strategy_cmd = setup_create_cmd(
sub_cmds,
[sw_update.APPLY_TYPE_SERIAL, # controller supports serial
sw_update.APPLY_TYPE_IGNORE],
[sw_update.APPLY_TYPE_SERIAL, # storage supports serial and parallel
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
[sw_update.APPLY_TYPE_SERIAL, # worker supports serial and parallel
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
[sw_update.INSTANCE_ACTION_STOP_START, # instance actions
sw_update.INSTANCE_ACTION_MIGRATE],
[sw_update.ALARM_RESTRICTIONS_STRICT, # alarm restrictions
sw_update.ALARM_RESTRICTIONS_RELAXED],
min_parallel=2,
max_parallel=100 # patch supports 2..100 workers in parallel
)
# define the delete command
delete_strategy_cmd = setup_delete_cmd(sub_cmds)
# define the apply command
apply_strategy_cmd = setup_apply_cmd(sub_cmds)
# define the abort command
abort_strategy_cmd = setup_abort_cmd(sub_cmds)
# define the show command
show_strategy_cmd = setup_show_cmd(sub_cmds)
def setup_upgrade_parser(commands):
"""Upgrade Strategy Commands"""
cmd_area = 'upgrade-strategy'
register_strategy(cmd_area, sw_update.STRATEGY_NAME_SW_UPGRADE)
cmd_parser = commands.add_parser(cmd_area,
help='Upgrade Strategy')
cmd_parser.set_defaults(cmd_area=cmd_area)
sub_cmds = cmd_parser.add_subparsers(title='Software Upgrade Commands',
metavar='')
sub_cmds.required = True
# define the create command
# alarm restrictions, defaults to strict
create_strategy_cmd = setup_create_cmd(
sub_cmds,
[sw_update.APPLY_TYPE_SERIAL], # hard coded to serial
[sw_update.APPLY_TYPE_SERIAL, # storage supports serial and parallel
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
[sw_update.APPLY_TYPE_SERIAL, # worker supports serial and parallel
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
[sw_update.INSTANCE_ACTION_MIGRATE], # hardcoded to migrate
[sw_update.ALARM_RESTRICTIONS_STRICT, # alarm restrictions
sw_update.ALARM_RESTRICTIONS_RELAXED],
min_parallel=2,
max_parallel=10 # upgrade supports 2..10 workers in parallel
)
# add upgrade specific arguments to the create command
# The get_extra_create_args method is updated to align with these
# Disable support for --start-upgrade as it was not completed
# create_strategy_cmd.add_argument('--start-upgrade',
# action='store_true',
# help=argparse.SUPPRESS)
create_strategy_cmd.add_argument('--complete-upgrade',
action='store_true',
help=argparse.SUPPRESS)
# define the delete command
delete_strategy_cmd = setup_delete_cmd(sub_cmds)
# define the apply command
apply_strategy_cmd = setup_apply_cmd(sub_cmds)
# define the abort command
abort_strategy_cmd = setup_abort_cmd(sub_cmds)
# define the show command
show_strategy_cmd = setup_show_cmd(sub_cmds)
def process_main(argv=sys.argv[1:]): # pylint: disable=dangerous-default-value
@ -102,201 +393,18 @@ def process_main(argv=sys.argv[1:]): # pylint: disable=dangerous-default-value
commands = parser.add_subparsers(title='Commands', metavar='')
commands.required = True
# Software Patch Commands
sw_patch_parser = commands.add_parser('patch-strategy',
help='Patch Strategy')
sw_patch_parser.set_defaults(cmd_area='patch-strategy')
# Add firmware update strategy commands
setup_fw_update_parser(commands)
sw_patch_cmds = sw_patch_parser.add_subparsers(
title='Software Patch Commands', metavar='')
sw_patch_cmds.required = True
sw_patch_create_strategy_cmd \
= sw_patch_cmds.add_parser('create', help='Create a strategy')
sw_patch_create_strategy_cmd.set_defaults(cmd='create')
sw_patch_create_strategy_cmd.add_argument(
'--controller-apply-type', default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
sw_patch_create_strategy_cmd.add_argument(
'--storage-apply-type', default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
sw_patch_create_strategy_cmd.add_argument(
'--worker-apply-type', default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
sw_patch_create_strategy_cmd.add_argument(
'--max-parallel-worker-hosts', type=int, choices=range(2, 101),
help='maximum worker hosts to patch in parallel')
sw_patch_create_strategy_cmd.add_argument(
'--instance-action', default=sw_update.INSTANCE_ACTION_STOP_START,
choices=[sw_update.INSTANCE_ACTION_MIGRATE,
sw_update.INSTANCE_ACTION_STOP_START],
help='defaults to stop-start')
sw_patch_create_strategy_cmd.add_argument(
'--alarm-restrictions', default=sw_update.ALARM_RESTRICTIONS_STRICT,
choices=[sw_update.ALARM_RESTRICTIONS_STRICT,
sw_update.ALARM_RESTRICTIONS_RELAXED],
help='defaults to strict')
sw_patch_delete_strategy_cmd \
= sw_patch_cmds.add_parser('delete', help='Delete a strategy')
sw_patch_delete_strategy_cmd.set_defaults(cmd='delete')
sw_patch_delete_strategy_cmd.add_argument(
'--force', action='store_true', help=argparse.SUPPRESS)
sw_patch_apply_strategy_cmd \
= sw_patch_cmds.add_parser('apply', help='Apply a strategy')
sw_patch_apply_strategy_cmd.set_defaults(cmd='apply')
sw_patch_apply_strategy_cmd.add_argument(
'--stage-id', default=None, help='stage identifier to apply')
sw_patch_abort_strategy_cmd \
= sw_patch_cmds.add_parser('abort', help='Abort a strategy')
sw_patch_abort_strategy_cmd.set_defaults(cmd='abort')
sw_patch_abort_strategy_cmd.add_argument(
'--stage-id', help='stage identifier to abort')
sw_patch_show_strategy_cmd \
= sw_patch_cmds.add_parser('show', help='Show a strategy')
sw_patch_show_strategy_cmd.set_defaults(cmd='show')
sw_patch_show_strategy_cmd.add_argument(
'--details', action='store_true', help='show strategy details')
# Software Upgrade Commands
sw_upgrade_parser = commands.add_parser('upgrade-strategy',
help='Upgrade Strategy')
sw_upgrade_parser.set_defaults(cmd_area='upgrade-strategy')
sw_upgrade_cmds = sw_upgrade_parser.add_subparsers(
title='Software Upgrade Commands', metavar='')
sw_upgrade_cmds.required = True
sw_upgrade_create_strategy_cmd \
= sw_upgrade_cmds.add_parser('create', help='Create a strategy')
sw_upgrade_create_strategy_cmd.set_defaults(cmd='create')
sw_upgrade_create_strategy_cmd.add_argument(
'--storage-apply-type', default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
sw_upgrade_create_strategy_cmd.add_argument(
'--worker-apply-type', default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL, sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
sw_upgrade_create_strategy_cmd.add_argument(
'--max-parallel-worker-hosts', type=int, choices=range(2, 11),
help='maximum worker hosts to upgrade in parallel')
# Disable support for --start-upgrade as it was not completed
# sw_upgrade_create_strategy_cmd.add_argument(
# '--start-upgrade', action='store_true',
# help=argparse.SUPPRESS)
sw_upgrade_create_strategy_cmd.add_argument(
'--complete-upgrade', action='store_true', help=argparse.SUPPRESS)
sw_upgrade_create_strategy_cmd.add_argument(
'--alarm-restrictions', default=sw_update.ALARM_RESTRICTIONS_STRICT,
choices=[sw_update.ALARM_RESTRICTIONS_STRICT,
sw_update.ALARM_RESTRICTIONS_RELAXED],
help='defaults to strict')
sw_upgrade_delete_strategy_cmd \
= sw_upgrade_cmds.add_parser('delete', help='Delete a strategy')
sw_upgrade_delete_strategy_cmd.set_defaults(cmd='delete')
sw_upgrade_delete_strategy_cmd.add_argument(
'--force', action='store_true', help=argparse.SUPPRESS)
sw_upgrade_apply_strategy_cmd \
= sw_upgrade_cmds.add_parser('apply', help='Apply a strategy')
sw_upgrade_apply_strategy_cmd.set_defaults(cmd='apply')
sw_upgrade_apply_strategy_cmd.add_argument(
'--stage-id', default=None, help='stage identifier to apply')
sw_upgrade_abort_strategy_cmd \
= sw_upgrade_cmds.add_parser('abort', help='Abort a strategy')
sw_upgrade_abort_strategy_cmd.set_defaults(cmd='abort')
sw_upgrade_abort_strategy_cmd.add_argument(
'--stage-id', help='stage identifier to abort')
sw_upgrade_show_strategy_cmd \
= sw_upgrade_cmds.add_parser('show', help='Show a strategy')
sw_upgrade_show_strategy_cmd.set_defaults(cmd='show')
sw_upgrade_show_strategy_cmd.add_argument(
'--details', action='store_true', help='show strategy details')
# Firmware Update Commands
fw_update_parser = commands.add_parser('fw-update-strategy',
help='Firmware Update Strategy')
fw_update_parser.set_defaults(cmd_area='fw-update-strategy')
fw_update_cmds = fw_update_parser.add_subparsers(
title='Firmware Update Commands', metavar='')
fw_update_cmds.required = True
fw_update_create_strategy_cmd \
= fw_update_cmds.add_parser('create', help='Create a strategy')
fw_update_create_strategy_cmd.set_defaults(cmd='create')
fw_update_create_strategy_cmd.add_argument('--controller-apply-type',
default=sw_update.APPLY_TYPE_IGNORE,
choices=[sw_update.APPLY_TYPE_IGNORE],
help='defaults to ignore')
fw_update_create_strategy_cmd.add_argument('--storage-apply-type',
default=sw_update.APPLY_TYPE_IGNORE,
choices=[sw_update.APPLY_TYPE_IGNORE],
help='defaults to ignore')
fw_update_create_strategy_cmd.add_argument('--worker-apply-type',
default=sw_update.APPLY_TYPE_SERIAL,
choices=[sw_update.APPLY_TYPE_SERIAL,
sw_update.APPLY_TYPE_PARALLEL,
sw_update.APPLY_TYPE_IGNORE],
help='defaults to serial')
fw_update_create_strategy_cmd.add_argument(
'--max-parallel-worker-hosts', type=int, choices=range(2, 6),
help='maximum worker hosts to update in parallel')
fw_update_create_strategy_cmd.add_argument('--instance-action',
default=sw_update.INSTANCE_ACTION_STOP_START,
choices=[sw_update.INSTANCE_ACTION_MIGRATE,
sw_update.INSTANCE_ACTION_STOP_START],
help='defaults to stop-start')
fw_update_create_strategy_cmd.add_argument('--alarm-restrictions',
default=sw_update.ALARM_RESTRICTIONS_STRICT,
choices=[sw_update.ALARM_RESTRICTIONS_STRICT,
sw_update.ALARM_RESTRICTIONS_RELAXED],
help='defaults to strict')
fw_update_delete_strategy_cmd \
= fw_update_cmds.add_parser('delete', help='Delete a strategy')
fw_update_delete_strategy_cmd.set_defaults(cmd='delete')
fw_update_delete_strategy_cmd.add_argument(
'--force', action='store_true', help=argparse.SUPPRESS)
fw_update_apply_strategy_cmd \
= fw_update_cmds.add_parser('apply', help='Apply a strategy')
fw_update_apply_strategy_cmd.set_defaults(cmd='apply')
fw_update_apply_strategy_cmd.add_argument(
'--stage-id', default=None, help='stage identifier to apply')
fw_update_abort_strategy_cmd \
= fw_update_cmds.add_parser('abort', help='Abort a strategy')
fw_update_abort_strategy_cmd.set_defaults(cmd='abort')
fw_update_abort_strategy_cmd.add_argument(
'--stage-id', help='stage identifier to abort')
fw_update_show_strategy_cmd \
= fw_update_cmds.add_parser('show', help='Show a strategy')
fw_update_show_strategy_cmd.set_defaults(cmd='show')
fw_update_show_strategy_cmd.add_argument(
'--details', action='store_true', help='show strategy details')
# Register kubernetes upgrade command parser
# Add kubernetes upgrade strategy commands
setup_kube_upgrade_parser(commands)
# Add software patch strategy commands
setup_patch_parser(commands)
# Add software upgrade strategy commands
setup_upgrade_parser(commands)
args = parser.parse_args(argv)
if args.debug:
@ -362,261 +470,74 @@ def process_main(argv=sys.argv[1:]): # pylint: disable=dangerous-default-value
print("Openstack interface not given")
return
if 'patch-strategy' == args.cmd_area:
if 'create' == args.cmd:
sw_update.create_strategy(
args.os_auth_url, args.os_project_name,
args.os_project_domain_name, args.os_username, args.os_password,
args.os_user_domain_name, args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_SW_PATCH,
args.controller_apply_type,
args.storage_apply_type, sw_update.APPLY_TYPE_IGNORE,
args.worker_apply_type,
args.max_parallel_worker_hosts,
args.instance_action,
args.alarm_restrictions)
elif 'delete' == args.cmd:
sw_update.delete_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_PATCH,
args.force)
elif 'apply' == args.cmd:
sw_update.apply_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_PATCH,
args.stage_id)
elif 'abort' == args.cmd:
sw_update.abort_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_PATCH,
args.stage_id)
elif 'show' == args.cmd:
sw_update.show_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_PATCH,
args.details)
else:
raise ValueError("Unknown command, %s, given for patch-strategy"
% args.cmd)
elif 'upgrade-strategy' == args.cmd_area:
if 'create' == args.cmd:
sw_update.create_strategy(
args.os_auth_url, args.os_project_name,
args.os_project_domain_name, args.os_username, args.os_password,
args.os_user_domain_name, args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_SW_UPGRADE,
sw_update.APPLY_TYPE_IGNORE,
args.storage_apply_type, sw_update.APPLY_TYPE_IGNORE,
args.worker_apply_type,
args.max_parallel_worker_hosts,
None, args.alarm_restrictions,
# start_upgrade=args.start_upgrade,
complete_upgrade=args.complete_upgrade
)
elif 'delete' == args.cmd:
sw_update.delete_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_UPGRADE,
args.force)
elif 'apply' == args.cmd:
sw_update.apply_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_UPGRADE,
args.stage_id)
elif 'abort' == args.cmd:
sw_update.abort_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_UPGRADE,
args.stage_id)
elif 'show' == args.cmd:
sw_update.show_strategy(args.os_auth_url, args.os_project_name,
args.os_project_domain_name,
args.os_username, args.os_password,
args.os_user_domain_name,
args.os_region_name, args.os_interface,
sw_update.STRATEGY_NAME_SW_UPGRADE,
args.details)
else:
raise ValueError("Unknown command, %s, given for upgrade-strategy"
% args.cmd)
elif 'fw-update-strategy' == args.cmd_area:
if 'create' == args.cmd:
sw_update.create_strategy(
args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_FW_UPDATE,
args.controller_apply_type,
args.storage_apply_type,
sw_update.APPLY_TYPE_IGNORE,
args.worker_apply_type,
args.max_parallel_worker_hosts,
args.instance_action,
args.alarm_restrictions)
elif 'delete' == args.cmd:
sw_update.delete_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_FW_UPDATE,
args.force)
elif 'apply' == args.cmd:
sw_update.apply_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_FW_UPDATE,
args.stage_id)
elif 'abort' == args.cmd:
sw_update.abort_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_FW_UPDATE,
args.stage_id)
elif 'show' == args.cmd:
sw_update.show_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
sw_update.STRATEGY_NAME_FW_UPDATE,
args.details)
else:
raise ValueError("Unknown command, %s, "
"given for fw-update-strategy"
% args.cmd)
elif 'kube-upgrade-strategy' == args.cmd_area:
strategy_type = sw_update.STRATEGY_NAME_KUBE_UPGRADE
if 'create' == args.cmd:
sw_update.create_strategy(
args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_type,
args.controller_apply_type,
args.storage_apply_type,
sw_update.APPLY_TYPE_IGNORE,
args.worker_apply_type,
args.max_parallel_worker_hosts,
args.instance_action,
args.alarm_restrictions,
to_version=args.to_version)
elif 'delete' == args.cmd:
sw_update.delete_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_type,
args.force)
elif 'apply' == args.cmd:
sw_update.apply_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_type,
args.stage_id)
elif 'abort' == args.cmd:
sw_update.abort_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_type,
args.stage_id)
elif 'show' == args.cmd:
sw_update.show_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_type,
args.details)
else:
raise ValueError("Unknown command, %s , given for %s"
% args.cmd, args.cmd_area)
strategy_name = get_strategy_name(args.cmd_area)
if 'create' == args.cmd:
extra_create_args = get_extra_create_args(args.cmd_area, args)
sw_update.create_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_name,
args.controller_apply_type,
args.storage_apply_type,
sw_update.APPLY_TYPE_IGNORE,
args.worker_apply_type,
args.max_parallel_worker_hosts,
args.instance_action,
args.alarm_restrictions,
**extra_create_args)
elif 'delete' == args.cmd:
sw_update.delete_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_name,
force=args.force)
elif 'apply' == args.cmd:
sw_update.apply_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_name,
stage_id=args.stage_id)
elif 'abort' == args.cmd:
sw_update.abort_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_name,
stage_id=args.stage_id)
elif 'show' == args.cmd:
sw_update.show_strategy(args.os_auth_url,
args.os_project_name,
args.os_project_domain_name,
args.os_username,
args.os_password,
args.os_user_domain_name,
args.os_region_name,
args.os_interface,
strategy_name,
details=args.details,
active=args.active)
else:
raise ValueError("Unknown command area, %s, given" % args.cmd_area)
raise ValueError("Unknown command, %s, given for %s"
% (args.cmd, args.cmd_area))
except KeyboardInterrupt:
print("Keyboard Interrupt received.")

View File

@ -28,10 +28,16 @@ def _print(indent_by, field, value, remains=''):
remains))
def _display_strategy_step(strategy_step):
def _display_strategy_step(strategy_step, active=False):
"""
Software Update - Display Strategy Step Information
"""
# If active flag is passed
# skip steps that are not started:'initial' or completed cleanly: 'success'
# this leaves failed and in-progress states
if active:
if strategy_step.result in ['initial', 'success']:
return False
_print(12, "step-id", strategy_step.step_id)
_print(12, "step-name", strategy_step.step_name)
if 0 < len(strategy_step.entity_type):
@ -47,12 +53,17 @@ def _display_strategy_step(strategy_step):
_print(12, "end-date-time", strategy_step.end_date_time)
_print(12, "result", strategy_step.result)
_print(12, "reason", strategy_step.reason)
return True
def _display_strategy_stage(strategy_stage, details=False):
def _display_strategy_stage(strategy_stage, details=False, active=False):
"""
Software Update - Display Strategy Stage Information
"""
# If active flag is passed, only display a stage that is in progress
if active:
if not strategy_stage.inprogress:
return False
_print(8, "stage-id", strategy_stage.stage_id)
_print(8, "stage-name", strategy_stage.stage_name)
_print(8, "total-steps", strategy_stage.total_steps)
@ -66,17 +77,22 @@ def _display_strategy_stage(strategy_stage, details=False):
_print(8, "result", strategy_stage.result)
_print(8, "reason", strategy_stage.reason)
if details:
if details or active:
print(" steps:")
for step in strategy_stage.steps:
_display_strategy_step(step)
print("")
if _display_strategy_step(step, active):
print("")
return True
def _display_strategy_phase(strategy_phase, details=False):
def _display_strategy_phase(strategy_phase, details=False, active=False):
"""
Software Update - Display Strategy Phase Information
"""
# If active flag is passed, only display a phase that is in progress
if active:
if not strategy_phase.inprogress:
return
print(" %s-phase:" % strategy_phase.phase_name)
_print(4, "total-stages", strategy_phase.total_stages)
_print(4, "current-stage", strategy_phase.current_stage)
@ -92,14 +108,14 @@ def _display_strategy_phase(strategy_phase, details=False):
_print(4, "result", strategy_phase.result)
_print(4, "reason", strategy_phase.reason)
if details:
if details or active:
print(" stages:")
for stage in strategy_phase.stages:
_display_strategy_stage(stage, details)
print("")
if _display_strategy_stage(stage, details, active):
print("")
def _display_strategy(strategy, details=False):
def _display_strategy(strategy, details=False, active=False):
"""
Software Update - Display Strategy Information
"""
@ -128,15 +144,15 @@ def _display_strategy(strategy, details=False):
("%s%%" % strategy.current_phase_completion_percentage))
_print(2, "state", strategy.state)
if details:
if details or active:
if 0 < strategy.build_phase.total_stages:
_display_strategy_phase(strategy.build_phase, details)
_display_strategy_phase(strategy.build_phase, details, active)
if 0 < strategy.apply_phase.total_stages:
_display_strategy_phase(strategy.apply_phase, details)
_display_strategy_phase(strategy.apply_phase, details, active)
if 0 < strategy.abort_phase.total_stages:
_display_strategy_phase(strategy.abort_phase, details)
_display_strategy_phase(strategy.abort_phase, details, active)
else:
if strategy.current_phase == strategy.build_phase.phase_name:
if strategy.build_phase.inprogress:
@ -276,7 +292,7 @@ def abort_strategy(os_auth_uri, os_project_name, os_project_domain_name,
def show_strategy(os_auth_uri, os_project_name, os_project_domain_name,
os_username, os_password, os_user_domain_name, os_region_name,
os_interface, strategy_name, details=False):
os_interface, strategy_name, details=False, active=False):
"""
Software Update - Show Strategy
"""
@ -295,4 +311,4 @@ def show_strategy(os_auth_uri, os_project_name, os_project_domain_name,
print("No strategy available")
return
_display_strategy(strategy, details)
_display_strategy(strategy, details, active)

View File

@ -89,7 +89,7 @@ function _swmanager()
;;
show)
if [ "${prev}" = "${action}" ]; then
COMPREPLY=($(compgen -W "--details" -- ${cur}))
COMPREPLY=($(compgen -W "--details --active" -- ${cur}))
fi
return 0
;;
@ -160,7 +160,7 @@ function _swmanager()
;;
show)
if [ "${prev}" = "${action}" ]; then
COMPREPLY=($(compgen -W "--details" -- ${cur}))
COMPREPLY=($(compgen -W "--details --active" -- ${cur}))
fi
return 0
;;
@ -237,7 +237,7 @@ function _swmanager()
;;
show)
if [ "${prev}" = "${action}" ]; then
COMPREPLY=($(compgen -W "--details" -- ${cur}))
COMPREPLY=($(compgen -W "--details --active" -- ${cur}))
fi
return 0
;;
@ -319,7 +319,7 @@ function _swmanager()
;;
show)
if [ "${prev}" = "${action}" ]; then
COMPREPLY=($(compgen -W "--details" -- ${cur}))
COMPREPLY=($(compgen -W "--details --active" -- ${cur}))
fi
return 0
;;

View File

@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: Apache-2.0
#
import copy
import mock
import os
@ -34,6 +35,15 @@ class TestNFVClientShell(testcase.NFVTestCase):
mock_usage.assert_called_once()
mock_message.assert_called_once()
# --- Help Cases ----
# -h will print_help and SystemExit
@mock.patch('argparse.ArgumentParser.print_help')
def _test_shell_help(self, mock_help=None, shell_args=None):
self.assertRaises(SystemExit, shell.process_main, shell_args)
mock_help.assert_called_once()
class TestNFVClientShellRobustness(TestNFVClientShell):
# invalid arguments causes process_main to exit
def test_shell_bad_args(self):
shell_args = ['invalid-arg', ]
@ -44,86 +54,221 @@ class TestNFVClientShell(testcase.NFVTestCase):
shell_args = []
self._test_shell_bad_or_empty_args(shell_args=shell_args)
# upgrade-strategy expects additional arguments
def test_shell_upgrade_strategy_incomplete_args(self):
shell_args = ['upgrade-strategy', ]
self._test_shell_bad_or_empty_args(shell_args=shell_args)
# patch-strategy expects additional arguments
def test_shell_patch_strategy_incomplete_args(self):
shell_args = ['patch-strategy', ]
self._test_shell_bad_or_empty_args(shell_args=shell_args)
class StrategyMixin(object):
# fw-update-strategy expects additional arguments
def test_shell_fw_update_strategy_incomplete_args(self):
shell_args = ['fw-update-strategy', ]
self._test_shell_bad_or_empty_args(shell_args=shell_args)
MOCK_ENV = {
'OS_AUTH_URL': 'FAKE_OS_AUTH_URL',
'OS_PROJECT_NAME': 'FAKE_OS_PROJECT_NAME',
'OS_PROJECT_DOMAIN_NAME': 'FAKE_OS_PROJECT_DOMAIN_NAME',
'OS_USERNAME': 'FAKE_OS_USERNAME',
'OS_PASSWORD': 'FAKE_OS_PASSWORD',
'OS_USER_DOMAIN_NAME': 'FAKE_OS_USER_DOMAIN_NAME',
'OS_REGION_NAME': 'FAKE_OS_REGION_NAME',
'OS_INTERFACE': 'FAKE_OS_INTERFACE'
}
# --- Help Cases ----
# -h will print_help and SystemExit
@mock.patch('argparse.ArgumentParser.print_help')
def _test_shell_help(self, mock_help=None, shell_args=None):
self.assertRaises(SystemExit, shell.process_main, shell_args)
mock_help.assert_called_once()
MOCK_ENV_OVERRIDES = {
'OS_AUTH_URL': '--os-auth-url=FAKE_OS_AUTH_URL',
'OS_PROJECT_NAME': '--os-project-name=FAKE_OS_PROJECT_NAME',
'OS_PROJECT_DOMAIN_NAME':
'--os-project-domain-name=FAKE_OS_PROJECT_DOMAIN_NAME',
'OS_USERNAME': '--os-username=FAKE_OS_USERNAME',
'OS_PASSWORD': '--os-password=FAKE_OS_PASSWORD',
'OS_USER_DOMAIN_NAME':
'--os-user-domain-name=FAKE_OS_USER_DOMAIN_NAME',
'OS_REGION_NAME': '--os-region-name=FAKE_OS_REGION_NAME',
'OS_INTERFACE': '--os-interface=FAKE_OS_INTERFACE'
}
def test_shell_upgrade_strategy_help(self):
shell_args = ['upgrade-strategy', '-h', ]
self._test_shell_help(shell_args=shell_args)
def set_strategy(self, strategy):
"""Invoked by the child class setupmethod to set the strategy"""
self.strategy = strategy
def test_shell_patch_strategy_help(self):
shell_args = ['patch-strategy', '-h', ]
self._test_shell_help(shell_args=shell_args)
def required_create_fields(self):
"""Override in the child class if create has required fields"""
return []
def test_shell_fw_update_strategy_help(self):
shell_args = ['fw-update-strategy', '-h', ]
self._test_shell_help(shell_args=shell_args)
def optional_create_fields(self):
"""Override in the child class if create has optional fields"""
return []
# -- Show commands --
# Both patch-strategy and upgrade-strategy use the same underlying
# sw_update class, but with different modes
# The strategy commands use the same underling sw_update class, but
# but with different modes
# Test the show commands are not invoked when env values missing
@mock.patch('nfv_client.sw_update.show_strategy')
def _test_shell_show_missing_env(self, mock_show=None, shell_args=None):
shell.process_main(shell_args)
mock_show.assert_not_called()
def test_shell_upgrade_strategy_show_missing_env(self):
shell_args = ['upgrade-strategy', 'show', ]
self._test_shell_show_missing_env(shell_args=shell_args)
def test_shell_patch_strategy_show_missing_env(self):
shell_args = ['patch-strategy', 'show', ]
self._test_shell_show_missing_env(shell_args=shell_args)
def test_shell_fw_update_strategy_show_missing_env(self):
shell_args = ['fw-update-strategy', 'show', ]
self._test_shell_show_missing_env(shell_args=shell_args)
# Test the show commands are invoked when env values detected
@mock.patch.dict(os.environ,
{'OS_AUTH_URL': 'FAKE_OS_AUTH_URL',
'OS_PROJECT_NAME': 'FAKE_OS_PROJECT_NAME',
'OS_PROJECT_DOMAIN_NAME': 'FAKE_OS_PROJECT_DOMAIN_NAME',
'OS_USERNAME': 'FAKE_OS_USERNAME',
'OS_PASSWORD': 'FAKE_OS_PASSWORD',
'OS_USER_DOMAIN_NAME': 'FAKE_OS_USER_DOMAIN_NAME',
'OS_REGION_NAME': 'FAKE_OS_REGION_NAME',
'OS_INTERFACE': 'FAKE_OS_INTERFACE'
})
@mock.patch('nfv_client.sw_update.show_strategy')
def _test_shell_show(self, mock_show=None, shell_args=None):
shell.process_main(shell_args)
with mock.patch.dict(os.environ, self.MOCK_ENV):
shell.process_main(shell_args)
mock_show.assert_called_once()
def test_shell_upgrade_strategy_show(self):
shell_args = ['upgrade-strategy', 'show', ]
@mock.patch('nfv_client.sw_update.show_strategy')
def _test_shell_show_incomplete_env(self,
mock_show=None,
shell_args=None,
pop_env=None,
expect_fails=True):
# setup a mostly complete environment
test_env = copy.copy(self.MOCK_ENV)
test_env.pop(pop_env)
with mock.patch.dict(os.environ, test_env):
shell.process_main(shell_args)
if expect_fails:
mock_show.assert_not_called()
else:
mock_show.assert_called_once()
def test_shell_strategy_missing_subcommand(self):
"""Test the strategy fails with a missing subcommand"""
shell_args = [self.strategy, ]
self._test_shell_bad_or_empty_args(shell_args=shell_args)
def test_shell_strategy_invalid_subcommand(self):
"""Test the strategy fails with an invalid subcommand"""
shell_args = [self.strategy, 'foo']
self._test_shell_bad_or_empty_args(shell_args=shell_args)
def test_shell_strategy_help(self):
"""Test the strategy supports the help subcommand"""
shell_args = [self.strategy, '-h', ]
self._test_shell_help(shell_args=shell_args)
def test_shell_strategy_show_incomplete_env(self):
"""Test that if any required env variable is missing, it fails"""
shell_args = [self.strategy, 'show', ]
for pop_env in self.MOCK_ENV.keys():
# remove the pop_env variable from the environment
self._test_shell_show_incomplete_env(shell_args=shell_args,
pop_env=pop_env)
def test_shell_strategy_show_env_overrides(self):
"""
Tests that passing certain values to the CLI override the env and
that removing that value from the env will not cause failure
"""
for env_val, override_val in self.MOCK_ENV_OVERRIDES.items():
shell_args = [override_val, self.strategy, 'show', ]
self._test_shell_show_incomplete_env(shell_args=shell_args,
pop_env=env_val,
expect_fails=False)
def test_shell_strategy_show(self):
shell_args = [self.strategy, 'show', ]
self._test_shell_show(shell_args=shell_args)
def test_shell_patch_strategy_show(self):
shell_args = ['patch-strategy', 'show', ]
def test_shell_strategy_show_bad_extra_arg(self):
shell_args = [self.strategy, 'show', '--bad']
self._test_shell_bad_or_empty_args(shell_args=shell_args)
def test_shell_strategy_show_debug(self):
shell_args = ["--debug", self.strategy, 'show']
self._test_shell_show(shell_args=shell_args)
def test_shell_fw_update_strategy_show(self):
shell_args = ['fw-update-strategy', 'show', ]
def test_shell_strategy_show_details(self):
shell_args = [self.strategy, 'show', '--details']
self._test_shell_show(shell_args=shell_args)
def test_shell_strategy_show_active(self):
shell_args = [self.strategy, 'show', '--active']
self._test_shell_show(shell_args=shell_args)
def test_shell_strategy_show_active_details(self):
shell_args = [self.strategy, 'show', '--details', '--active']
self._test_shell_show(shell_args=shell_args)
# -- Abort command --
# Test the abort command can be invoked. Requires the env to be set
@mock.patch('nfv_client.sw_update.abort_strategy')
def _test_shell_abort(self, mock_abort=None, shell_args=None):
with mock.patch.dict(os.environ, self.MOCK_ENV):
shell.process_main(shell_args)
mock_abort.assert_called_once()
def test_shell_strategy_abort(self):
shell_args = [self.strategy, 'abort']
self._test_shell_abort(shell_args=shell_args)
# -- Apply command --
# Test the apply command can be invoked. Requires the env to be set
@mock.patch('nfv_client.sw_update.apply_strategy')
def _test_shell_apply(self, mock_apply=None, shell_args=None):
with mock.patch.dict(os.environ, self.MOCK_ENV):
shell.process_main(shell_args)
mock_apply.assert_called_once()
def test_shell_strategy_apply(self):
shell_args = [self.strategy, 'apply']
self._test_shell_apply(shell_args=shell_args)
# -- Delete command --
# Test the delete command can be invoked. Requires the env to be set
@mock.patch('nfv_client.sw_update.delete_strategy')
def _test_shell_delete(self, mock_delete=None, shell_args=None):
with mock.patch.dict(os.environ, self.MOCK_ENV):
shell.process_main(shell_args)
mock_delete.assert_called_once()
def test_shell_strategy_delete(self):
shell_args = [self.strategy, 'delete']
self._test_shell_delete(shell_args=shell_args)
# -- Create command --
# Test the create command can be invoked. Requires the env to be set
@mock.patch('nfv_client.sw_update.create_strategy')
def _test_shell_create(self, mock_create=None, shell_args=None):
with mock.patch.dict(os.environ, self.MOCK_ENV):
shell.process_main(shell_args)
mock_create.assert_called_once()
# -- Create command --
def test_shell_strategy_create(self):
shell_args = [self.strategy, 'create']
# create may have 'required' additional fields
shell_args.extend(self.required_create_fields())
self._test_shell_create(shell_args=shell_args)
def test_shell_strategy_create_optional(self):
shell_args = [self.strategy, 'create']
# create may have 'required' additional fields and optional ones
shell_args.extend(self.required_create_fields())
shell_args.extend(self.optional_create_fields())
self._test_shell_create(shell_args=shell_args)
class TestCLIUpgradeStrategy(TestNFVClientShell,
StrategyMixin):
def setUp(self):
super(TestCLIUpgradeStrategy, self).setUp()
self.set_strategy('upgrade-strategy')
class TestCLIPatchStrategy(TestNFVClientShell,
StrategyMixin):
def setUp(self):
super(TestCLIPatchStrategy, self).setUp()
self.set_strategy('patch-strategy')
class TestCLIFwUpdateStrategy(TestNFVClientShell,
StrategyMixin):
def setUp(self):
super(TestCLIFwUpdateStrategy, self).setUp()
self.set_strategy('fw-update-strategy')
class TestCLIKubeUpgradeStrategy(TestNFVClientShell,
StrategyMixin):
def setUp(self):
super(TestCLIKubeUpgradeStrategy, self).setUp()
self.set_strategy('kube-upgrade-strategy')
def required_create_fields(self):
"""Kube Upgrade requires a to-version for create"""
return ['--to-version=1.2.3']