diff --git a/tests/fake_api.py b/tests/fake_api.py index 861c8b35..7428f3d5 100644 --- a/tests/fake_api.py +++ b/tests/fake_api.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -CURRENT_VERSION = 'v1.12' +CURRENT_VERSION = 'v1.15' FAKE_CONTAINER_ID = '3cc2351ab11b' FAKE_IMAGE_ID = 'e9aa60c60128' @@ -225,6 +225,20 @@ def get_fake_export(): return status_code, response +def post_fake_execute(): + status_code = 200 + response = {'Id': FAKE_CONTAINER_ID} + return status_code, response + + +def post_fake_execute_start(): + status_code = 200 + response = (b'\x01\x00\x00\x00\x00\x00\x00\x11bin\nboot\ndev\netc\n' + b'\x01\x00\x00\x00\x00\x00\x00\x12lib\nmnt\nproc\nroot\n' + b'\x01\x00\x00\x00\x00\x00\x00\x0csbin\nusr\nvar\n') + return status_code, response + + def post_fake_stop_container(): status_code = 200 response = {'Id': FAKE_CONTAINER_ID} @@ -330,6 +344,10 @@ fake_responses = { get_fake_diff, '{1}/{0}/containers/3cc2351ab11b/export'.format(CURRENT_VERSION, prefix): get_fake_export, + '{1}/{0}/containers/shell/exec'.format(CURRENT_VERSION, prefix): + post_fake_execute, + '{1}/{0}/exec/3cc2351ab11b/start'.format(CURRENT_VERSION, prefix): + post_fake_execute_start, '{1}/{0}/containers/3cc2351ab11b/stop'.format(CURRENT_VERSION, prefix): post_fake_stop_container, '{1}/{0}/containers/3cc2351ab11b/kill'.format(CURRENT_VERSION, prefix): diff --git a/tests/integration_test.py b/tests/integration_test.py index d4900b7f..88c69dcf 100644 --- a/tests/integration_test.py +++ b/tests/integration_test.py @@ -627,6 +627,34 @@ class TestRestartingContainer(BaseTestCase): res = [x for x in containers if 'Id' in x and x['Id'].startswith(id)] self.assertEqual(len(res), 0) + +class TestExecuteCommand(BaseTestCase): + def runTest(self): + container = self.client.create_container('busybox', ['false']) + id = container['Id'] + self.client.start(id) + self.tmp_containers.append(id) + + res = self.client.execute(id, ['echo', 'hello']) + expected = b'hello\n' if six.PY3 else 'hello\n' + self.assertEqual(res, expected) + + +class TestExecuteCommandStreaming(BaseTestCase): + def runTest(self): + container = self.client.create_container('busybox', ['false']) + id = container['Id'] + self.client.start(id) + self.tmp_containers.append(id) + + chunks = self.client.execute(id, ['echo', 'hello\nworld'], stream=True) + res = b'' if six.PY3 else '' + for chunk in chunks: + res += chunk + expected = b'hello\nworld\n' if six.PY3 else 'hello\nworld\n' + self.assertEqual(res, expected) + + ################# # LINKS TESTS # ################# diff --git a/tests/test.py b/tests/test.py index 984e350e..e3a430c8 100644 --- a/tests/test.py +++ b/tests/test.py @@ -1064,6 +1064,31 @@ class DockerClientTest(Cleanup, unittest.TestCase): timeout=(docker.client.DEFAULT_TIMEOUT_SECONDS + timeout) ) + def test_execute_command(self): + try: + self.client.execute(fake_api.FAKE_CONTAINER_ID, ['ls', '-1']) + except Exception as e: + self.fail('Command should not raise exception: {0}'.format(e)) + + args = fake_request.call_args + self.assertEqual(args[0][0], + url_prefix + 'exec/3cc2351ab11b/start') + + self.assertEqual(json.loads(args[1]['data']), + json.loads('''{ + "Tty": false, + "AttachStderr": true, + "Container": "3cc2351ab11b", + "Cmd": ["ls", "-1"], + "AttachStdin": false, + "User": "", + "Detach": false, + "Privileged": false, + "AttachStdout": true}''')) + + self.assertEqual(args[1]['headers'], + {'Content-Type': 'application/json'}) + def test_kill_container(self): try: self.client.kill(fake_api.FAKE_CONTAINER_ID)