diff --git a/fuelclient/commands/base.py b/fuelclient/commands/base.py index 8f4351c8..e1754c1d 100644 --- a/fuelclient/commands/base.py +++ b/fuelclient/commands/base.py @@ -172,3 +172,46 @@ class BaseDeleteCommand(BaseCommand): msg.format( ent=self.entity_name.capitalize(), ent_id=parsed_args.id)) + + +@six.add_metaclass(abc.ABCMeta) +class BaseTasksExecuteCommand(BaseCommand): + def get_parser(self, prog_name): + parser = super(BaseTasksExecuteCommand, self).get_parser(prog_name) + + parser.add_argument( + '-e', '--env', + type=int, + required=True, + help='Id of the environment' + ) + parser.add_argument( + '--force', + action="store_true", + default=False, + help='Force run all deployment tasks without skipping.') + + parser.add_argument( + '--trace', + action="store_true", + default=False, + help='Enable debugging mode in tasks executor.' + ) + + mode_group = parser.add_mutually_exclusive_group() + mode_group.add_argument( + '--dry-run', + action="store_true", + default=False, + help='Specifies to dry-run a deployment by configuring ' + 'task executor to dump the deployment graph to a dot file.' + ) + mode_group.add_argument( + '--noop', + action="store_true", + default=False, + help='Specifies noop-run deployment configuring tasks executor ' + 'to run all tasks in noop mode. ' + 'Execution result summary can be got via history of tasks.') + + return parser diff --git a/fuelclient/commands/graph.py b/fuelclient/commands/graph.py index c97e34a8..f785734a 100644 --- a/fuelclient/commands/graph.py +++ b/fuelclient/commands/graph.py @@ -152,70 +152,44 @@ class GraphUpload(base.BaseCommand, FileMethodsMixin): self.app.stdout.write("Deployment graph was successfully uploaded.\n") -class GraphExecute(base.BaseCommand): +class GraphExecute(base.BaseTasksExecuteCommand): """Start deployment with given graph type.""" entity_name = 'graph' def get_parser(self, prog_name): parser = super(GraphExecute, self).get_parser(prog_name) - parser.add_argument('-e', - '--env', - type=int, - required=True, - help='Id of the environment') - parser.add_argument('-t', - '--types', - type=str, - nargs='+', - required=False, - help='Types of the deployment graph in order ' - 'of execution') - parser.add_argument('-n', - '--nodes', - type=int, - nargs='+', - required=False, - help='Ids of the nodes to use for deployment.') - parser.add_argument('-T', - '--task-names', - type=str, - nargs='+', - required=False, - help='List of deployment tasks to run.') - parser.add_argument('-d', - '--dry-run', - action="store_true", - required=False, - default=False, - help='Specifies to dry-run a deployment by ' - 'configuring task executor to dump the ' - 'deployment graph to a dot file.') - parser.add_argument('-f', - '--force', - action="store_true", - required=False, - default=False, - help='Force run all deployment tasks without ' - 'skipping.') - parser.add_argument('--noop', - action="store_true", - required=False, - default=False, - help='Specifies noop-run deployment configuring ' - 'tasks executor to run puppet and shell tasks in ' - 'noop mode and skip all other. Stores noop-run ' - 'result summary in nailgun database.') + parser.add_argument( + '-t', + '--graph-types', + nargs='+', + required=True, + help='Types of the deployment graph in order of execution' + ) + parser.add_argument( + '-n', + '--nodes', + type=int, + nargs='+', + help='Ids of the nodes to use for deployment.' + ) + parser.add_argument( + '-T', + '--task-names', + nargs='+', + help='List of deployment tasks to run.' + ) return parser def take_action(self, args): result = self.client.execute( env_id=args.env, - graph_types=args.types, + graph_types=args.graph_types, nodes=args.nodes, task_names=args.task_names, dry_run=args.dry_run, noop_run=args.noop, - force=args.force + force=args.force, + debug=args.trace ) msg = 'Deployment task with id {t} for the environment {e} ' \ 'has been started.\n'.format(t=result.data['id'], diff --git a/fuelclient/commands/sequence.py b/fuelclient/commands/sequence.py index 51f3eace..ac9ec2f3 100644 --- a/fuelclient/commands/sequence.py +++ b/fuelclient/commands/sequence.py @@ -185,7 +185,7 @@ class SequenceList(SequenceMixIn, base.BaseListCommand): return parser -class SequenceExecute(SequenceMixIn, base.BaseCommand): +class SequenceExecute(SequenceMixIn, base.BaseTasksExecuteCommand): """Executes sequence on specified environment.""" def get_parser(self, prog_name): @@ -195,34 +195,6 @@ class SequenceExecute(SequenceMixIn, base.BaseCommand): type=int, help='Id of the Sequence.' ) - parser.add_argument( - '-e', '--env', - type=int, - required=True, - help='Id of the environment' - ) - parser.add_argument( - '--dry-run', - action="store_true", - default=False, - help='Specifies to dry-run a deployment by configuring ' - 'task executor to dump the deployment graph to a dot file.') - parser.add_argument( - '--force', - action="store_true", - default=False, - help='Force run all deployment tasks ' - 'without evaluating conditions.' - ) - parser.add_argument( - '--noop', - action="store_true", - default=False, - help='Specifies noop-run deployment configuring ' - 'tasks executor to run puppet and shell tasks in ' - 'noop mode and skip all other. Stores noop-run ' - 'result summary in nailgun database.' - ) return parser def take_action(self, args): @@ -231,7 +203,8 @@ class SequenceExecute(SequenceMixIn, base.BaseCommand): env_id=args.env, dry_run=args.dry_run, noop_run=args.noop, - force=args.force + force=args.force, + debug=args.trace ) msg = 'Deployment task with id {t} for the environment {e} ' \ 'has been started.\n'.format(t=result.data['id'], diff --git a/fuelclient/tests/unit/v2/cli/test_deployment_graph.py b/fuelclient/tests/unit/v2/cli/test_deployment_graph.py index f27db788..6054ec92 100644 --- a/fuelclient/tests/unit/v2/cli/test_deployment_graph.py +++ b/fuelclient/tests/unit/v2/cli/test_deployment_graph.py @@ -156,77 +156,96 @@ class TestGraphActions(test_engine.BaseCLITest): def test_execute(self): self._test_cmd( 'execute', - '--env 1 --type custom_graph another_custom_graph --nodes 1 2 3', + '--env 1 --graph-types graph1 graph2 --nodes 1 2 3', dict( env_id=1, - graph_types=['custom_graph', 'another_custom_graph'], + graph_types=['graph1', 'graph2'], nodes=[1, 2, 3], task_names=None, dry_run=False, noop_run=False, - force=False + force=False, + debug=False ) ) def test_execute_w_dry_run(self): self._test_cmd( 'execute', - '--env 1 --type custom_graph another_custom_graph ' - '--nodes 1 2 3 --dry-run', + '--env 1 --graph-types graph1 graph2 --nodes 1 2 3 --dry-run', dict( env_id=1, - graph_types=['custom_graph', 'another_custom_graph'], + graph_types=['graph1', 'graph2'], nodes=[1, 2, 3], task_names=None, dry_run=True, noop_run=False, - force=False + force=False, + debug=False ) ) def test_execute_w_force(self): self._test_cmd( 'execute', - '--env 1 --force', + '--env 1 --graph-types graph1 --force', dict( env_id=1, - graph_types=None, + graph_types=['graph1'], nodes=None, task_names=None, dry_run=False, noop_run=False, - force=True + force=True, + debug=False ) ) def test_execute_w_task_names(self): self._test_cmd( 'execute', - '--env 1 --task-names task1 task2', + '--env 1 --graph-types graph1 --task-names task1 task2', dict( env_id=1, - graph_types=None, + graph_types=['graph1'], nodes=None, task_names=['task1', 'task2'], dry_run=False, noop_run=False, - force=False + force=False, + debug=False ) ) def test_execute_w_noop_run(self): self._test_cmd( 'execute', - '--env 1 --type custom_graph another_custom_graph ' - '--nodes 1 2 3 --noop', + '--env 1 --graph-types graph1 graph2 --nodes 1 2 3 --noop', dict( env_id=1, - graph_types=['custom_graph', 'another_custom_graph'], + graph_types=['graph1', 'graph2'], nodes=[1, 2, 3], task_names=None, dry_run=False, noop_run=True, - force=False + force=False, + debug=False + ) + ) + + def test_execute_w_trace(self): + self._test_cmd( + 'execute', + '--env 1 --graph-types graph1 --trace', + dict( + env_id=1, + graph_types=['graph1'], + nodes=None, + task_names=None, + dry_run=False, + noop_run=False, + force=False, + debug=True ) ) diff --git a/fuelclient/tests/unit/v2/cli/test_sequences.py b/fuelclient/tests/unit/v2/cli/test_sequences.py index d74637f9..9b55ca88 100644 --- a/fuelclient/tests/unit/v2/cli/test_sequences.py +++ b/fuelclient/tests/unit/v2/cli/test_sequences.py @@ -73,10 +73,20 @@ class TestSequenceActions(test_engine.BaseCLITest): self.exec_command('sequence delete 1') self.m_client.delete_by_id.assert_called_once_with(1) - def test_execute(self): + def test_execute_with_dry_run_and_force(self): self.exec_command( 'sequence execute 1 -e 2 --dry-run --force' ) self.m_client.execute.assert_called_once_with( - sequence_id=1, env_id=2, dry_run=True, noop_run=False, force=True + sequence_id=1, env_id=2, + dry_run=True, noop_run=False, force=True, debug=False + ) + + def test_execute_with_noop_and_trace(self): + self.exec_command( + 'sequence execute 1 -e 2 --noop --trace' + ) + self.m_client.execute.assert_called_once_with( + sequence_id=1, env_id=2, + dry_run=False, noop_run=True, force=False, debug=True ) diff --git a/fuelclient/v1/graph.py b/fuelclient/v1/graph.py index 378102c4..483bd5c5 100644 --- a/fuelclient/v1/graph.py +++ b/fuelclient/v1/graph.py @@ -86,7 +86,7 @@ class GraphClient(base_v1.BaseV1Client): method(data, related_model, related_id, graph_type) def execute(self, env_id, nodes=None, graph_types=None, task_names=None, - dry_run=False, noop_run=False, force=False): + **kwargs): request_data = {'cluster': env_id} def map_args_to_graph_types(graph): @@ -103,15 +103,7 @@ class GraphClient(base_v1.BaseV1Client): map_args_to_graph_types, graph_types )) - if dry_run: - request_data['dry_run'] = True - - if noop_run: - request_data['noop_run'] = True - - if force: - request_data['force'] = True - + request_data.update(kwargs) deploy_data = self.connection.post_request( self.cluster_deploy_api_path, request_data