From a7ef827f8f9fb499d37ba97938f2049edfd82546 Mon Sep 17 00:00:00 2001 From: Feng Shengqin Date: Wed, 31 May 2017 15:45:08 +0800 Subject: [PATCH] Zunclient should escape special character Co-Authored-By: Hongbin Lu Change-Id: Ia863c1af602ac2b83ff7e20352323fa0529dfc43 Closes-Bug: #1694137 --- zunclient/common/utils.py | 9 ++++++ zunclient/osc/v1/containers.py | 8 ++--- zunclient/tests/functional/osc/v1/base.py | 30 +++++++++++++++++++ .../tests/functional/osc/v1/test_container.py | 24 ++++++++++++++- zunclient/tests/unit/v1/test_containers.py | 2 +- zunclient/v1/containers_shell.py | 6 ++-- 6 files changed, 70 insertions(+), 9 deletions(-) diff --git a/zunclient/common/utils.py b/zunclient/common/utils.py index c84bf9c9..d0e3d9c3 100644 --- a/zunclient/common/utils.py +++ b/zunclient/common/utils.py @@ -166,3 +166,12 @@ def list_containers(containers): utils.print_list(containers, columns, {'versions': print_list_field('versions')}, sortby_index=None) + + +def parse_command(command): + output = [] + if command: + for c in command: + c = '"' + c + '"' + output.append(c) + return " ".join(output) diff --git a/zunclient/osc/v1/containers.py b/zunclient/osc/v1/containers.py index 4c90caf1..d6963496 100644 --- a/zunclient/osc/v1/containers.py +++ b/zunclient/osc/v1/containers.py @@ -127,7 +127,7 @@ class CreateContainer(command.ShowOne): opts['image_pull_policy'] = parsed_args.image_pull_policy opts['image_driver'] = parsed_args.image_driver if parsed_args.command: - opts['command'] = ' '.join(parsed_args.command) + opts['command'] = zun_utils.parse_command(parsed_args.command) if parsed_args.restart: opts['restart_policy'] = \ zun_utils.check_restart_policy(parsed_args.restart) @@ -374,8 +374,8 @@ class ExecContainer(command.Command): def take_action(self, parsed_args): client = _get_client(self, parsed_args) container = parsed_args.container - command = ' '.join(parsed_args.command) - response = client.containers.execute(container, command) + command = zun_utils.parse_command(parsed_args.command) + response = client.containers.execute(container, command=command) output = response['output'] exit_code = response['exit_code'] print(output) @@ -591,7 +591,7 @@ class RunContainer(command.ShowOne): opts['image_pull_policy'] = parsed_args.image_pull_policy opts['image_driver'] = parsed_args.image_driver if parsed_args.command: - opts['command'] = ' '.join(parsed_args.command) + opts['command'] = zun_utils.parse_command(parsed_args.command) if parsed_args.restart: opts['restart_policy'] = \ zun_utils.check_restart_policy(parsed_args.restart) diff --git a/zunclient/tests/functional/osc/v1/base.py b/zunclient/tests/functional/osc/v1/base.py index 5434e19d..3dcb21c5 100644 --- a/zunclient/tests/functional/osc/v1/base.py +++ b/zunclient/tests/functional/osc/v1/base.py @@ -56,6 +56,27 @@ class TestCase(base.FunctionalTestBase): self.fail('Container has not been created!') return container + def container_run(self, image='cirros', name=None, params='sleep 100000'): + """Run container and add cleanup. + + :param String image: Image for a new container + :param String name: Name for a new container + :param String params: Additional args and kwargs + :return: JSON object of created container + """ + if not name: + name = data_utils.rand_name('container') + + opts = self.get_opts() + output = self.openstack('appcontainer run {0}' + ' --name {1} {2} {3}' + .format(opts, name, image, params)) + container = json.loads(output) + + if not output: + self.fail('Container has not run!') + return container + def container_delete(self, identifier, ignore_exceptions=False): """Try to delete container by name or UUID. @@ -105,3 +126,12 @@ class TestCase(base.FunctionalTestBase): """ self.openstack('appcontainer rename {0} {1}' .format(identifier, name)) + + def container_execute(self, identifier, command): + """Execute in specified container. + + :param String identifier: Name or UUID of the container + :param String command: command execute in the container + """ + return self.openstack('appcontainer exec {0} {1}' + .format(identifier, command)) diff --git a/zunclient/tests/functional/osc/v1/test_container.py b/zunclient/tests/functional/osc/v1/test_container.py index ce1d3032..ddc0e86b 100644 --- a/zunclient/tests/functional/osc/v1/test_container.py +++ b/zunclient/tests/functional/osc/v1/test_container.py @@ -68,7 +68,7 @@ class ContainerTests(base.TestCase): [x['uuid'] for x in container_list]) count = 0 while count < 5: - self.container_show(container['name']) + container = self.container_show(container['name']) if container['status'] == 'Created': break if container['status'] == 'Error': @@ -109,3 +109,25 @@ class ContainerTests(base.TestCase): self.container_rename(container['name'], new_name) container_list = self.container_list() self.assertIn(new_name, [x['name'] for x in container_list]) + + def test_execute(self): + """Check container execute command with name and UUID arguments. + + Test steps: + 1) Create container in setUp. + 2) Execute command calling it with name and UUID arguments. + 3) Check the container logs. + """ + container = self.container_run(name='test_execute') + count = 0 + while count < 50: + container = self.container_show(container['name']) + if container['status'] == 'Running': + break + if container['status'] == 'Error': + break + time.sleep(2) + count = count + 1 + command = "sh -c 'echo hello'" + result = self.container_execute(container['name'], command) + self.assertIn('hello', result) diff --git a/zunclient/tests/unit/v1/test_containers.py b/zunclient/tests/unit/v1/test_containers.py index dda77e9f..131ec41d 100644 --- a/zunclient/tests/unit/v1/test_containers.py +++ b/zunclient/tests/unit/v1/test_containers.py @@ -23,7 +23,7 @@ CONTAINER1 = {'id': '1234', 'name': 'test1', 'image_pull_policy': 'never', 'image': 'cirros', - 'command': 'sleep 100000000', + 'command': 'sh -c "echo hello"', 'cpu': '1', 'memory': '256', 'environment': 'hostname=zunsystem', diff --git a/zunclient/v1/containers_shell.py b/zunclient/v1/containers_shell.py index 27431cd1..502a2128 100644 --- a/zunclient/v1/containers_shell.py +++ b/zunclient/v1/containers_shell.py @@ -98,7 +98,7 @@ def do_create(cs, args): opts['image_pull_policy'] = args.image_pull_policy opts['image_driver'] = args.image_driver if args.command: - opts['command'] = ' '.join(args.command) + opts['command'] = zun_utils.parse_command(args.command) if args.restart: opts['restart_policy'] = zun_utils.check_restart_policy(args.restart) if args.interactive: @@ -321,7 +321,7 @@ def do_logs(cs, args): def do_exec(cs, args): """Execute command in a running container.""" opts = {} - opts['command'] = ' '.join(args.command) + opts['command'] = zun_utils.parse_command(args.command) if args.interactive: opts['interactive'] = True opts['run'] = False @@ -428,7 +428,7 @@ def do_run(cs, args): opts['image_pull_policy'] = args.image_pull_policy opts['image_driver'] = args.image_driver if args.command: - opts['command'] = ' '.join(args.command) + opts['command'] = zun_utils.parse_command(args.command) if args.restart: opts['restart_policy'] = zun_utils.check_restart_policy(args.restart) if args.interactive: