diff --git a/fuelclient/cli/arguments.py b/fuelclient/cli/arguments.py index e1e39b28..d0caa513 100644 --- a/fuelclient/cli/arguments.py +++ b/fuelclient/cli/arguments.py @@ -253,6 +253,15 @@ def get_dry_run_deployment_arg(): "to dump the deployment graph to a dot file.") +def get_noop_run_deployment_arg(): + return get_boolean_arg( + "noop", + dest='noop_run', + 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") + + def get_file_pattern_arg(): return get_str_arg( "filepattern", diff --git a/fuelclient/commands/environment.py b/fuelclient/commands/environment.py index ba983f74..b91d31f0 100644 --- a/fuelclient/commands/environment.py +++ b/fuelclient/commands/environment.py @@ -408,16 +408,24 @@ class EnvDeploy(EnvMixIn, base.BaseCommand): 'Store cluster settings and serialized ' \ 'data in the db and ask the task executor ' \ 'to dump the resulting graph into a dot file' - + noop_run_help_string = '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( '-d', '--dry-run', dest="dry_run", action='store_true', help=dry_run_help_string) + parser.add_argument( + '-n', '--noop', dest="noop_run", + action='store_true', help=noop_run_help_string) return parser def take_action(self, parsed_args): task_id = self.client.deploy_changes(parsed_args.id, - dry_run=parsed_args.dry_run) + dry_run=parsed_args.dry_run, + noop_run=parsed_args.noop_run) msg = 'Deployment task with id {t} for the environment {e} '\ 'has been started.\n'.format(t=task_id, e=parsed_args.id) @@ -430,7 +438,8 @@ class EnvRedeploy(EnvDeploy): def take_action(self, parsed_args): task_id = self.client.redeploy_changes(parsed_args.id, - dry_run=parsed_args.dry_run) + dry_run=parsed_args.dry_run, + noop_run=parsed_args.noop_run) msg = 'Deployment task with id {t} for the environment {e} '\ 'has been started.\n'.format(t=task_id, e=parsed_args.id) diff --git a/fuelclient/commands/graph.py b/fuelclient/commands/graph.py index 42bcfaae..fa94028e 100644 --- a/fuelclient/commands/graph.py +++ b/fuelclient/commands/graph.py @@ -198,6 +198,14 @@ class GraphExecute(base.BaseCommand): 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.') return parser def take_action(self, args): @@ -207,6 +215,7 @@ class GraphExecute(base.BaseCommand): nodes=args.nodes, task_names=args.task_names, dry_run=args.dry_run, + noop_run=args.noop, force=args.force ) msg = 'Deployment task with id {t} for the environment {e} ' \ diff --git a/fuelclient/objects/environment.py b/fuelclient/objects/environment.py index c486608b..7b664577 100644 --- a/fuelclient/objects/environment.py +++ b/fuelclient/objects/environment.py @@ -93,17 +93,17 @@ class Environment(BaseObject): [{"id": n.id} for n in nodes] ) - def deploy_changes(self, dry_run=False): + def deploy_changes(self, dry_run=False, noop_run=False): deploy_data = self.connection.put_request( "clusters/{0}/changes".format(self.id), - {}, dry_run=int(dry_run) + {}, dry_run=int(dry_run), noop_run=int(noop_run) ) return DeployTask.init_with_data(deploy_data) - def redeploy_changes(self, dry_run=False): + def redeploy_changes(self, dry_run=False, noop_run=False): deploy_data = self.connection.put_request( "clusters/{0}/changes/redeploy".format(self.id), - {}, dry_run=int(dry_run) + {}, dry_run=int(dry_run), noop_run=int(noop_run) ) return DeployTask.init_with_data(deploy_data) diff --git a/fuelclient/tests/unit/v1/test_environment.py b/fuelclient/tests/unit/v1/test_environment.py index 9b048b4c..b87906a3 100644 --- a/fuelclient/tests/unit/v1/test_environment.py +++ b/fuelclient/tests/unit/v1/test_environment.py @@ -62,9 +62,10 @@ class TestEnvironment(base.UnitTestCase): @mock.patch('fuelclient.objects.task.DeployTask.init_with_data') def test_deploy_changes(self, task_data): dry_run = False + noop_run = False mdeploy = self.m_request.put('/api/v1/clusters/1/changes' - '?dry_run={0}'.format( - int(dry_run)), json={}) + '?dry_run={0}&noop_run={1}'.format( + int(dry_run), int(noop_run)), json={}) cmd = ['fuel', 'deploy-changes', '--env', '1'] self.execute(cmd) @@ -108,9 +109,9 @@ class TestEnvironment(base.UnitTestCase): self.execute(cmd) self.check_deploy_redeploy_changes(dry_run, mdeploy) - def check_deploy_redeploy_changes(self, dry_run, mdeploy): - self.assertEqual(mdeploy.last_request.qs['dry_run'][0], - str(int(dry_run))) + def check_deploy_redeploy_changes(self, res, mdeploy, mode='dry_run'): + self.assertEqual(mdeploy.last_request.qs[mode][0], + str(int(res))) class TestEnvironmentOstf(base.UnitTestCase): diff --git a/fuelclient/tests/unit/v2/cli/test_deployment_graph.py b/fuelclient/tests/unit/v2/cli/test_deployment_graph.py index c74d8301..86bac811 100644 --- a/fuelclient/tests/unit/v2/cli/test_deployment_graph.py +++ b/fuelclient/tests/unit/v2/cli/test_deployment_graph.py @@ -155,6 +155,7 @@ class TestGraphActions(test_engine.BaseCLITest): nodes=[1, 2, 3], task_names=None, dry_run=False, + noop_run=False, force=False ) ) @@ -170,6 +171,7 @@ class TestGraphActions(test_engine.BaseCLITest): nodes=[1, 2, 3], task_names=None, dry_run=True, + noop_run=False, force=False ) ) @@ -184,6 +186,7 @@ class TestGraphActions(test_engine.BaseCLITest): nodes=None, task_names=None, dry_run=False, + noop_run=False, force=True ) ) @@ -198,6 +201,23 @@ class TestGraphActions(test_engine.BaseCLITest): nodes=None, task_names=['task1', 'task2'], dry_run=False, + noop_run=False, + force=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', + dict( + env_id=1, + graph_types=['custom_graph', 'another_custom_graph'], + nodes=[1, 2, 3], + task_names=None, + dry_run=False, + noop_run=True, force=False ) ) diff --git a/fuelclient/tests/unit/v2/cli/test_env.py b/fuelclient/tests/unit/v2/cli/test_env.py index 71b89303..7a340873 100644 --- a/fuelclient/tests/unit/v2/cli/test_env.py +++ b/fuelclient/tests/unit/v2/cli/test_env.py @@ -94,6 +94,7 @@ class TestEnvCommand(test_engine.BaseCLITest): def test_env_deploy(self): dry_run = False + noop_run = False args = 'env deploy' args += ' 42' @@ -102,6 +103,7 @@ class TestEnvCommand(test_engine.BaseCLITest): calls = list() calls.append(mock.call.deploy_changes(42, + noop_run=noop_run, dry_run=dry_run)) self.m_get_client.assert_called_with('environment', mock.ANY) @@ -109,6 +111,7 @@ class TestEnvCommand(test_engine.BaseCLITest): def test_env_deploy_dry_run(self): dry_run = True + noop_run = False args = 'env deploy -d' args += ' 42' @@ -117,6 +120,24 @@ class TestEnvCommand(test_engine.BaseCLITest): calls = list() calls.append(mock.call.deploy_changes(42, + noop_run=noop_run, + dry_run=dry_run)) + + self.m_get_client.assert_called_with('environment', mock.ANY) + self.m_client.assert_has_calls(calls) + + def test_env_deploy_noop_run(self): + dry_run = False + noop_run = True + + args = 'env deploy -n' + args += ' 42' + + self.exec_command(args) + + calls = list() + calls.append(mock.call.deploy_changes(42, + noop_run=noop_run, dry_run=dry_run)) self.m_get_client.assert_called_with('environment', mock.ANY) @@ -124,6 +145,7 @@ class TestEnvCommand(test_engine.BaseCLITest): def test_env_redeploy(self): dry_run = False + noop_run = False args = 'env redeploy' args += ' 42' @@ -132,6 +154,7 @@ class TestEnvCommand(test_engine.BaseCLITest): calls = list() calls.append(mock.call.redeploy_changes(42, + noop_run=noop_run, dry_run=dry_run)) self.m_get_client.assert_called_with('environment', mock.ANY) @@ -139,6 +162,7 @@ class TestEnvCommand(test_engine.BaseCLITest): def test_env_redeploy_dry_run(self): dry_run = True + noop_run = False args = 'env redeploy -d' args += ' 42' @@ -147,6 +171,24 @@ class TestEnvCommand(test_engine.BaseCLITest): calls = list() calls.append(mock.call.redeploy_changes(42, + noop_run=noop_run, + dry_run=dry_run)) + + self.m_get_client.assert_called_with('environment', mock.ANY) + self.m_client.assert_has_calls(calls) + + def test_env_redeploy_noop_run(self): + dry_run = False + noop_run = True + args = 'env redeploy -n' + + args += ' 42' + + self.exec_command(args) + + calls = list() + calls.append(mock.call.redeploy_changes(42, + noop_run=noop_run, dry_run=dry_run)) self.m_get_client.assert_called_with('environment', mock.ANY) diff --git a/fuelclient/tests/unit/v2/lib/test_deployment_graph.py b/fuelclient/tests/unit/v2/lib/test_deployment_graph.py index 6ab4a186..d886b76d 100644 --- a/fuelclient/tests/unit/v2/lib/test_deployment_graph.py +++ b/fuelclient/tests/unit/v2/lib/test_deployment_graph.py @@ -133,12 +133,14 @@ class TestDeploymentGraphFacade(test_api.BaseLibTest): graph_types=["custom_graph", "another_custom_graph"], task_names=["rsync_core_puppet"], dry_run=True, + noop_run=True, force=True ) self.assertEqual( { 'cluster': 1, 'dry_run': True, + 'noop_run': True, 'graphs': [ {'nodes': [1, 2, 3], 'type': 'custom_graph', 'tasks': ['rsync_core_puppet']}, diff --git a/fuelclient/tests/unit/v2/lib/test_environment.py b/fuelclient/tests/unit/v2/lib/test_environment.py index ffc49bc5..06ffadff 100644 --- a/fuelclient/tests/unit/v2/lib/test_environment.py +++ b/fuelclient/tests/unit/v2/lib/test_environment.py @@ -124,10 +124,9 @@ class TestEnvFacade(test_api.BaseLibTest): self.client.deploy_changes(env_id, dry_run=dry_run) self.check_deploy_redeploy_changes(dry_run, matcher) - def check_deploy_redeploy_changes(self, dry_run, matcher): + def check_deploy_redeploy_changes(self, res, matcher, mode='dry_run'): self.assertTrue(matcher.called) - self.assertEqual(matcher.last_request.qs['dry_run'][0], - str(int(dry_run))) + self.assertEqual(matcher.last_request.qs[mode][0], str(int(res))) @mock.patch.object(task_object.DeployTask, 'init_with_data') def test_env_deploy_dry_run(self, m_init): @@ -140,6 +139,17 @@ class TestEnvFacade(test_api.BaseLibTest): self.client.deploy_changes(env_id, dry_run=dry_run) self.check_deploy_redeploy_changes(dry_run, matcher) + @mock.patch.object(task_object.DeployTask, 'init_with_data') + def test_env_deploy_noop_run(self, m_init): + env_id = 42 + expected_uri = self.get_object_uri(self.res_uri, env_id, '/changes') + matcher = self.m_request.put(expected_uri, json={}) + + noop_run = True + + self.client.deploy_changes(env_id, noop_run=noop_run) + self.check_deploy_redeploy_changes(noop_run, matcher, mode='noop_run') + @mock.patch.object(task_object.DeployTask, 'init_with_data') def test_env_redeploy(self, m_init): env_id = 42 @@ -163,6 +173,18 @@ class TestEnvFacade(test_api.BaseLibTest): self.client.redeploy_changes(env_id, dry_run=dry_run) self.check_deploy_redeploy_changes(dry_run, matcher) + @mock.patch.object(task_object.DeployTask, 'init_with_data') + def test_env_redeploy_noop_run(self, m_init): + env_id = 42 + expected_uri = self.get_object_uri(self.res_uri, env_id, + '/changes/redeploy') + matcher = self.m_request.put(expected_uri, json={}) + + noop_run = True + + self.client.redeploy_changes(env_id, noop_run=noop_run) + self.check_deploy_redeploy_changes(noop_run, matcher, mode='noop_run') + @mock.patch.object(base_object.BaseObject, 'init_with_data') def test_env_update(self, m_init): env_id = 42 diff --git a/fuelclient/v1/environment.py b/fuelclient/v1/environment.py index eea994f4..0e6bc6f0 100644 --- a/fuelclient/v1/environment.py +++ b/fuelclient/v1/environment.py @@ -82,10 +82,10 @@ class EnvironmentClient(base_v1.BaseV1Client): else: env.unassign_all() - def deploy_changes(self, environment_id, dry_run=False): + def deploy_changes(self, environment_id, dry_run=False, noop_run=False): env = self._entity_wrapper(obj_id=environment_id) - deploy_task = env.deploy_changes(dry_run=dry_run) + deploy_task = env.deploy_changes(dry_run=dry_run, noop_run=noop_run) return deploy_task.id def provision_nodes(self, environment_id, node_ids): @@ -104,10 +104,11 @@ class EnvironmentClient(base_v1.BaseV1Client): nodes=nodes) return self.connection.put_request(uri, {}) - def redeploy_changes(self, environment_id, dry_run=False): + def redeploy_changes(self, environment_id, dry_run=False, noop_run=False): env = self._entity_wrapper(obj_id=environment_id) - redeploy_task = env.redeploy_changes(dry_run=dry_run) + redeploy_task = env.redeploy_changes(dry_run=dry_run, + noop_run=noop_run) return redeploy_task.id def spawn_vms(self, environment_id): diff --git a/fuelclient/v1/graph.py b/fuelclient/v1/graph.py index ed959c59..225f4ed6 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, force=False): + dry_run=False, noop_run=False, force=False): request_data = {'cluster': env_id} def map_args_to_graph_types(graph): @@ -106,6 +106,9 @@ class GraphClient(base_v1.BaseV1Client): if dry_run: request_data['dry_run'] = True + if noop_run: + request_data['noop_run'] = True + if force: request_data['force'] = True