diff --git a/fuelclient/cli/actions/node.py b/fuelclient/cli/actions/node.py index 235950ff..f87c2cd3 100644 --- a/fuelclient/cli/actions/node.py +++ b/fuelclient/cli/actions/node.py @@ -46,6 +46,7 @@ class NodeAction(Action): Args.get_disk_arg("Node disk configuration."), Args.get_deploy_arg("Deploy specific nodes."), Args.get_hostname_arg("Set node hostname."), + Args.get_node_name_arg("Set node name."), Args.get_delete_from_db_arg( "Delete specific nodes only from fuel db.\n" "User should still delete node from cobbler"), @@ -81,6 +82,7 @@ class NodeAction(Action): ("deploy", self.start), ("provision", self.start), ("hostname", self.set_hostname), + ("name", self.set_name), ("delete-from-db", self.delete_from_db), ("tasks", self.execute_tasks), ("skip", self.execute_tasks), @@ -336,20 +338,40 @@ class NodeAction(Action): params.node) ) + @staticmethod + def _get_one_node(params): + """Ensures that only one node was passed in the command and returns it. + + :raises ArgumentException: When more than 1 node provided. + """ + if len(params.node) > 1: + raise error.ArgumentException( + "You should select only one node to change.") + + return Node(params.node[0]) + + @check_all("node", "name") + def set_name(self, params): + """To set node name: + fuel node --node-id 1 --name NewName + """ + node = self._get_one_node(params) + node.set({"name": params.name}) + self.serializer.print_to_output( + {}, + u"Name for node with id {0} has been changed to {1}." + .format(node.id, params.name) + ) + @check_all("node", "hostname") def set_hostname(self, params): """To set node hostname: fuel node --node-id 1 --hostname ctrl-01 """ - nodes = Node.get_by_ids(params.node) - - if len(nodes) > 1: - raise error.ArgumentException( - "You should select only one node to change hostname." - ) - nodes[0].set({"hostname": params.hostname}) + node = self._get_one_node(params) + node.set({"hostname": params.hostname}) self.serializer.print_to_output( {}, "Hostname for node with id {0} has been changed to {1}." - .format(params.node[0], params.hostname) + .format(node.id, params.hostname) ) diff --git a/fuelclient/cli/arguments.py b/fuelclient/cli/arguments.py index d7b973fb..6801941b 100644 --- a/fuelclient/cli/arguments.py +++ b/fuelclient/cli/arguments.py @@ -256,6 +256,10 @@ def get_file_pattern_arg(): help="Provide unix file pattern to filter tasks with files.") +def get_node_name_arg(help_msg): + return get_str_arg("name", help=help_msg) + + def get_hostname_arg(help_msg): return get_str_arg("hostname", help=help_msg) diff --git a/fuelclient/tests/functional/v1/test_client.py b/fuelclient/tests/functional/v1/test_client.py index 3a71bbda..2ceaae2f 100644 --- a/fuelclient/tests/functional/v1/test_client.py +++ b/fuelclient/tests/functional/v1/test_client.py @@ -56,11 +56,11 @@ class TestHandlers(base.BaseTestCase): def test_node_action(self): help_msg = ["fuel node [-h] [--env ENV]", "[--list | --set | --delete | --network | --disk |" - " --deploy | --hostname HOSTNAME | --delete-from-db |" - " --provision]", "-h", "--help", " -s", + " --deploy | --hostname HOSTNAME | --name NAME |" + " --delete-from-db | --provision]", "-h", "--help", " -s", "--default", " -d", "--download", " -u", "--upload", "--dir", "--node", "--node-id", " -r", - "--role", "--net", "--hostname"] + "--role", "--net", "--hostname", "--name"] self.check_all_in_msg("node --help", help_msg) self.check_for_rows_in_table("node") diff --git a/fuelclient/tests/unit/v1/test_nodes.py b/fuelclient/tests/unit/v1/test_nodes.py new file mode 100644 index 00000000..9960e200 --- /dev/null +++ b/fuelclient/tests/unit/v1/test_nodes.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- + +# Copyright 2015 Mirantis, Inc. +# +# 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. + +import mock + +from fuelclient.cli.actions import node +from fuelclient.cli import error +from fuelclient.tests.unit.v1 import base + + +class TestNodeSetAction(base.UnitTestCase): + + def setUp(self): + super(TestNodeSetAction, self).setUp() + self.node_action = node.NodeAction() + self.node_id = 1 + self.params = mock.Mock() + self.params.node = [self.node_id] + + def test_more_than_one_node(self): + mput = self.m_request.put('/api/v1/nodes/{0}/'.format(self.node_id)) + self.params.hostname = 'whatever' + self.params.name = 'whatever2' + self.params.node = [1, 2] + + error_msg = r"You should select only one node to change\." + with self.assertRaisesRegexp(error.ArgumentException, error_msg): + self.node_action.set_hostname(self.params) + + with self.assertRaisesRegexp(error.ArgumentException, error_msg): + self.node_action.set_name(self.params) + + self.assertFalse(mput.called) + + def test_set_name(self): + test_cases = ('new-name', 'New Name', u'śćż∑ Pó', u'测试 测试') + for name in test_cases: + self.params.name = name + mput = self.m_request.put( + '/api/v1/nodes/{0}/'.format(self.node_id), + json={}) + with mock.patch.object(self.node_action.serializer, + 'print_to_output') as mprint: + self.node_action.set_name(self.params) + + self.assertEqual(mput.call_count, 1) + self.assertEqual({'name': name}, mput.last_request.json()) + mprint.assert_called_once_with( + {}, + u"Name for node with id {0} has been changed to {1}.".format( + self.node_id, name) + ) + + def test_set_hostname(self): + new_hostname = 'new_hostname' + self.params.hostname = new_hostname + + mput = self.m_request.put( + '/api/v1/nodes/{0}/'.format(self.node_id), + json={}) + + with mock.patch.object(self.node_action.serializer, + 'print_to_output') as mprint: + self.node_action.set_hostname(self.params) + + self.assertEqual(mput.call_count, 1) + self.assertEqual({'hostname': new_hostname}, mput.last_request.json()) + mprint.assert_called_once_with( + {}, + "Hostname for node with id {0} has been changed to {1}.".format( + self.node_id, new_hostname) + )