Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion openwisp_controller/connection/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,8 @@ def _exec_command(self):
command = self.get_type_display()
# user registered command
else:
command = self._callable(**self.input)
input = self.input or {}
command = self._callable(**input)
output, exit_code = self.connection.connector_instance.exec_command(
command, raise_unexpected_exit=False
)
Expand Down
10 changes: 9 additions & 1 deletion openwisp_controller/connection/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,20 @@
},
'message': _('Command cannot be empty.'),
'required': ['command'],
'additionalProperties': False,
},
},
),
(
'reboot',
{'label': _('Reboot'), 'schema': {'title': _('Reboot'), 'type': 'null'}},
{
'label': _('Reboot'),
'schema': {
'title': _('Reboot'),
'type': 'null',
'additionalProperties': False,
},
},
),
(
'change_password',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,9 @@ function initCommandOverlay($) {
});

function closeOverlay() {
$('#id_command_set-0-type').val('reboot');
$('#id_command_set-0-type').trigger('change');
// The user may close the form without submitting it.
// The following line ensures that all input fields are cleared.
$('#command_set-0 .jsoneditor-wrapper input').val('');
$('#command_set-group').css('display', 'none');
$('.ow-command-overlay-errornote').addClass('ow-hide');
commandConfirmationDialog.hide();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class TestCommandUtilities(TestCase):
REBOOT_SCHEMA = {'title': 'Reboot', 'type': 'null'}
REBOOT_SCHEMA = {'title': 'Reboot', 'type': 'null', 'additionalProperties': False}

def test_get_command_schema(self):
with self.subTest('Test existing command option'):
Expand Down
41 changes: 41 additions & 0 deletions openwisp_controller/connection/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,47 @@ def _command_assertions(destination_address, mocked_exec_command):
unregister_command('callable_ping')
unregister_command('path_ping')

@mock.patch(_connect_path)
@mock.patch.dict(COMMANDS, {})
@mock.patch.dict(ORGANIZATION_ENABLED_COMMANDS, {'__all__': ('restart_network')})
@mock.patch(_exec_command_path)
def test_execute_user_registered_command_without_input(
self, mocked_exec_command, connect_mocked
):
restart_network_schema = {
'label': 'Restart Network',
'schema': {
'title': 'Restart Network',
'type': 'null',
'additionalProperties': False,
},
'callable': 'openwisp_controller.connection.tests.utils'
'._restart_network_command_callable',
}
dc = self._create_device_connection()
register_command('restart_network', restart_network_schema)
command = Command(
device=dc.device,
connection=dc,
type='restart_network',
)
command.full_clean()
mocked_exec_command.return_value = self._exec_command_return_value(
stdout='Network restarted'
)
command.save()
# must call this explicitly because lack of transactions in this test case
command.execute()
connect_mocked.assert_called()
mocked_exec_command.assert_called_once()
mocked_exec_command.assert_called_with(
'/etc/init.d/networking restart',
timeout=app_settings.SSH_COMMAND_TIMEOUT,
)
command.refresh_from_db()
self.assertEqual(command.status, 'success')
self.assertEqual(command.output, 'Network restarted\n')

def test_command_permissions(self):
ct = ContentType.objects.get_by_natural_key(
app_label=self.app_label, model='command'
Expand Down
4 changes: 4 additions & 0 deletions openwisp_controller/connection/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,7 @@ def _ping_command_callable(destination_address, interface_name=None):
if interface_name:
command += f' -I {interface_name}'
return command


def _restart_network_command_callable():
return '/etc/init.d/networking restart'