From 663f4840ea7cce803e334a04fea0238d6393b3c9 Mon Sep 17 00:00:00 2001 From: Hongbin Lu Date: Sun, 23 Jun 2019 21:49:39 +0000 Subject: [PATCH] Add 'tty' property to container Change-Id: I166c87b24eb0384ba32a3c47030d452d0b5a5ee2 --- .zuul.yaml | 2 +- api-ref/source/capsules.inc | 3 ++ api-ref/source/containers.inc | 6 ++++ api-ref/source/parameters.yaml | 16 +++++++-- .../source/samples/capsule-get-all-resp.json | 3 +- api-ref/source/samples/capsule-show-resp.json | 3 +- .../source/samples/container-create-req.json | 1 + .../source/samples/container-create-resp.json | 1 + .../samples/container-get-all-resp.json | 1 + .../source/samples/container-rename-resp.json | 3 +- .../source/samples/container-show-resp.json | 1 + .../source/samples/container-update-resp.json | 1 + zun/api/controllers/v1/containers.py | 14 +++++++- zun/api/controllers/v1/schemas/containers.py | 1 + .../controllers/v1/views/containers_view.py | 1 + zun/api/controllers/versions.py | 3 +- zun/api/rest_api_version_history.rst | 6 ++++ zun/container/docker/driver.py | 2 +- .../b2bda272f4dd_add_tty_to_container.py | 33 +++++++++++++++++++ zun/db/sqlalchemy/models.py | 1 + zun/objects/container.py | 13 +++++--- zun/tests/unit/api/base.py | 2 +- zun/tests/unit/api/controllers/test_root.py | 4 +-- zun/tests/unit/db/utils.py | 1 + zun/tests/unit/objects/test_objects.py | 8 ++--- 25 files changed, 110 insertions(+), 20 deletions(-) create mode 100644 zun/db/sqlalchemy/alembic/versions/b2bda272f4dd_add_tty_to_container.py diff --git a/.zuul.yaml b/.zuul.yaml index 44140e4a1..06b114560 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -26,7 +26,7 @@ test-config: $TEMPEST_CONFIG: container_service: - min_microversion: 1.35 + min_microversion: 1.36 devstack_services: tempest: true devstack_plugins: diff --git a/api-ref/source/capsules.inc b/api-ref/source/capsules.inc index 19f3726cf..99ca2733b 100644 --- a/api-ref/source/capsules.inc +++ b/api-ref/source/capsules.inc @@ -159,6 +159,7 @@ Capsule Container - registry_id: registry_id - ports: ports - interactive: interactive + - tty: tty Response Example ---------------- @@ -250,6 +251,7 @@ Capsule Container - registry_id: registry_id - ports: ports - interactive: interactive + - tty: tty Response Example ---------------- @@ -344,6 +346,7 @@ Capsule Container - registry_id: registry_id - ports: ports - interactive: interactive + - tty: tty Response Example ---------------- diff --git a/api-ref/source/containers.inc b/api-ref/source/containers.inc index a7b097f1c..032755adc 100644 --- a/api-ref/source/containers.inc +++ b/api-ref/source/containers.inc @@ -47,6 +47,7 @@ Request - environment: environment-request - restart_policy: restart_policy-request - interactive: interactive-request + - tty: tty-request - image_driver: image_driver-request - security_groups: security_groups-request - nets: nets @@ -86,6 +87,7 @@ Response - environment: environment - restart_policy: restart_policy - interactive: interactive + - tty: tty - uuid: uuid - hostname: hostname - status: status @@ -165,6 +167,7 @@ Response - environment: environment - restart_policy: restart_policy - interactive: interactive + - tty: tty - uuid: uuid - hostname: hostname - status: status @@ -233,6 +236,7 @@ Response - environment: environment - restart_policy: restart_policy - interactive: interactive + - tty: tty - uuid: uuid - hostname: hostname - status: status @@ -439,6 +443,7 @@ Return new container with updated attributes. - environment: environment - restart_policy: restart_policy - interactive: interactive + - tty: tty - uuid: uuid - hostname: hostname - status: status @@ -737,6 +742,7 @@ Response - environment: environment - restart_policy: restart_policy - interactive: interactive + - tty: tty - uuid: uuid - hostname: hostname - status: status diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index a216c684b..2c4832e30 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -1111,13 +1111,13 @@ image_pull_policy-request: type: string interactive: description: | - Keep STDIN open even if not attached, allocate a pseudo-TTY. + Keep STDIN open even if not attached. in: body required: true type: boolean interactive-request: description: | - Keep STDIN open even if not attached, allocate a pseudo-TTY. + Keep STDIN open even if not attached. in: body required: false type: boolean @@ -1390,6 +1390,18 @@ task_state: in: body required: true type: string +tty: + description: | + Whether this container allocate a TTY for itself. + in: body + required: true + type: boolean +tty-request: + description: | + Whether this container should allocate a TTY for itself. + in: body + required: false + type: boolean updated_at: description: | The date and time when the resource was updated. diff --git a/api-ref/source/samples/capsule-get-all-resp.json b/api-ref/source/samples/capsule-get-all-resp.json index e95c41e2b..092232d8f 100644 --- a/api-ref/source/samples/capsule-get-all-resp.json +++ b/api-ref/source/samples/capsule-get-all-resp.json @@ -68,7 +68,8 @@ "ports": [ 80 ], - "interactive": true + "interactive": true, + "tty": true } ], "addresses": { diff --git a/api-ref/source/samples/capsule-show-resp.json b/api-ref/source/samples/capsule-show-resp.json index d58879471..d6cb4ab64 100644 --- a/api-ref/source/samples/capsule-show-resp.json +++ b/api-ref/source/samples/capsule-show-resp.json @@ -64,7 +64,8 @@ ], "registry_id": null, "ports": [80], - "interactive": true + "interactive": true, + "tty": true } ], "addresses": { diff --git a/api-ref/source/samples/container-create-req.json b/api-ref/source/samples/container-create-req.json index e52c5ee63..ffb0c1e3e 100644 --- a/api-ref/source/samples/container-create-req.json +++ b/api-ref/source/samples/container-create-req.json @@ -20,6 +20,7 @@ "MaximumRetryCount": 0 }, "interactive": false, + "tty": false, "image_driver": "docker", "security_groups": [ "default" diff --git a/api-ref/source/samples/container-create-resp.json b/api-ref/source/samples/container-create-resp.json index 9345d3e56..b2b0f67c8 100644 --- a/api-ref/source/samples/container-create-resp.json +++ b/api-ref/source/samples/container-create-resp.json @@ -42,6 +42,7 @@ ], "cpu": 2.0, "interactive": false, + "tty": false, "runtime": "runc", "hostname": "testhost", "auto_remove": false, diff --git a/api-ref/source/samples/container-get-all-resp.json b/api-ref/source/samples/container-get-all-resp.json index f2a21753a..15ca58b19 100644 --- a/api-ref/source/samples/container-get-all-resp.json +++ b/api-ref/source/samples/container-get-all-resp.json @@ -60,6 +60,7 @@ ], "cpu": 2.0, "interactive": false, + "tty": false, "cpu_policy": "shared", "registry_id": null, "healthcheck": { diff --git a/api-ref/source/samples/container-rename-resp.json b/api-ref/source/samples/container-rename-resp.json index 70c28794b..a063a69bb 100644 --- a/api-ref/source/samples/container-rename-resp.json +++ b/api-ref/source/samples/container-rename-resp.json @@ -60,5 +60,6 @@ "auto_heal": false, "cpu_policy": "shared", "registry_id": null, - "interactive": false + "interactive": false, + "tty": false } diff --git a/api-ref/source/samples/container-show-resp.json b/api-ref/source/samples/container-show-resp.json index e16a9cb15..9d5bf7072 100644 --- a/api-ref/source/samples/container-show-resp.json +++ b/api-ref/source/samples/container-show-resp.json @@ -57,6 +57,7 @@ ], "cpu": 2.0, "interactive": false, + "tty": false, "cpu_policy": "shared", "registry_id": null, "healthcheck": { diff --git a/api-ref/source/samples/container-update-resp.json b/api-ref/source/samples/container-update-resp.json index 337078ad0..0b607939b 100644 --- a/api-ref/source/samples/container-update-resp.json +++ b/api-ref/source/samples/container-update-resp.json @@ -60,6 +60,7 @@ "runtime": "runc", "cpu": 3.0, "interactive": false, + "tty": false, "privileged": false, "project_id": "493378c3aa3e4315a39fe8b125f9eaaa", "disk": 0, diff --git a/zun/api/controllers/v1/containers.py b/zun/api/controllers/v1/containers.py index a245c4882..65b7bba0c 100644 --- a/zun/api/controllers/v1/containers.py +++ b/zun/api/controllers/v1/containers.py @@ -264,7 +264,19 @@ class ContainersController(base.Controller): return self._do_post(run, **container_dict) - @base.Controller.api_version("1.20") # noqa + @base.Controller.api_version("1.20", "1.35") # noqa + @pecan.expose('json') + @api_utils.enforce_content_types(['application/json']) + @exception.wrap_pecan_controller_exception + @validation.validate_query_param(pecan.request, schema.query_param_create) + @validation.validated(schema.container_create) + def post(self, run=False, **container_dict): + interactive = container_dict.get('interactive') + if interactive is not None: + container_dict['tty'] = interactive + return self._do_post(run, **container_dict) + + @base.Controller.api_version("1.36") # noqa @pecan.expose('json') @api_utils.enforce_content_types(['application/json']) @exception.wrap_pecan_controller_exception diff --git a/zun/api/controllers/v1/schemas/containers.py b/zun/api/controllers/v1/schemas/containers.py index 4ef3826d7..014d51b4d 100644 --- a/zun/api/controllers/v1/schemas/containers.py +++ b/zun/api/controllers/v1/schemas/containers.py @@ -28,6 +28,7 @@ _legacy_container_properties = { 'environment': parameter_types.environment, 'restart_policy': parameter_types.restart_policy, 'interactive': parameter_types.boolean, + 'tty': parameter_types.boolean, 'image_driver': parameter_types.image_driver, 'security_groups': parameter_types.security_groups, 'hints': parameter_types.hints, diff --git a/zun/api/controllers/v1/views/containers_view.py b/zun/api/controllers/v1/views/containers_view.py index e0b5de60b..02c82c478 100644 --- a/zun/api/controllers/v1/views/containers_view.py +++ b/zun/api/controllers/v1/views/containers_view.py @@ -40,6 +40,7 @@ _basic_keys = ( 'restart_policy', 'status_detail', 'interactive', + 'tty', 'image_driver', 'security_groups', 'auto_remove', diff --git a/zun/api/controllers/versions.py b/zun/api/controllers/versions.py index 82d0940c9..27439818f 100644 --- a/zun/api/controllers/versions.py +++ b/zun/api/controllers/versions.py @@ -68,10 +68,11 @@ REST_API_VERSION_HISTORY = """REST API Version History: * 1.33 - Add 'finish_time' to container actions * 1.34 - Add 'init_containers' to capsule * 1.35 - Support exposing container ports in capsule + * 1.36 - Add 'tty' to container """ BASE_VER = '1.1' -CURRENT_MAX_VER = '1.35' +CURRENT_MAX_VER = '1.36' class Version(object): diff --git a/zun/api/rest_api_version_history.rst b/zun/api/rest_api_version_history.rst index 1d3192022..20aa28612 100644 --- a/zun/api/rest_api_version_history.rst +++ b/zun/api/rest_api_version_history.rst @@ -275,3 +275,9 @@ user documentation. ports: - containerPort: 80 protocol: TCP + +1.36 +---- + + Add 'tty' to container. + This field indicate if the container should allocate a TTY for itself. diff --git a/zun/container/docker/driver.py b/zun/container/docker/driver.py index a3450260a..d8c03ba12 100644 --- a/zun/container/docker/driver.py +++ b/zun/container/docker/driver.py @@ -263,7 +263,7 @@ class DockerDriver(driver.ContainerDriver): 'environment': container.environment, 'working_dir': container.workdir, 'labels': container.labels, - 'tty': container.interactive, + 'tty': container.tty, 'stdin_open': container.interactive, 'hostname': container.hostname, } diff --git a/zun/db/sqlalchemy/alembic/versions/b2bda272f4dd_add_tty_to_container.py b/zun/db/sqlalchemy/alembic/versions/b2bda272f4dd_add_tty_to_container.py new file mode 100644 index 000000000..56d2f3295 --- /dev/null +++ b/zun/db/sqlalchemy/alembic/versions/b2bda272f4dd_add_tty_to_container.py @@ -0,0 +1,33 @@ +# 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. + +"""add tty to container + +Revision ID: b2bda272f4dd +Revises: 157a0595e13e +Create Date: 2019-06-23 21:22:18.324322 + +""" + +# revision identifiers, used by Alembic. +revision = 'b2bda272f4dd' +down_revision = '157a0595e13e' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.add_column('container', + sa.Column('tty', sa.Boolean(), nullable=True)) diff --git a/zun/db/sqlalchemy/models.py b/zun/db/sqlalchemy/models.py index 48b4f6a44..be3061c99 100644 --- a/zun/db/sqlalchemy/models.py +++ b/zun/db/sqlalchemy/models.py @@ -162,6 +162,7 @@ class Container(Base): restart_policy = Column(JSONEncodedDict) status_detail = Column(String(50)) interactive = Column(Boolean, default=False) + tty = Column(Boolean, default=False) image_driver = Column(String(255)) websocket_url = Column(String(255)) websocket_token = Column(String(255)) diff --git a/zun/objects/container.py b/zun/objects/container.py index b589148fc..9dd271b12 100644 --- a/zun/objects/container.py +++ b/zun/objects/container.py @@ -88,6 +88,7 @@ class ContainerBase(base.ZunPersistentObject, base.ZunObject): 'restart_policy': fields.DictOfStringsField(nullable=True), 'status_detail': fields.StringField(nullable=True), 'interactive': fields.BooleanField(nullable=True), + 'tty': fields.BooleanField(nullable=True), 'image_driver': fields.StringField(nullable=True), 'websocket_url': fields.StringField(nullable=True), 'websocket_token': fields.StringField(nullable=True), @@ -399,7 +400,8 @@ class Container(ContainerBase): # Version 1.37: Add 'exposed_ports' attribute # Version 1.38: Add 'cpuset' attribute # Version 1.39: Add 'register' and 'registry_id' attributes - VERSION = '1.39' + # Version 1.40: Add 'tty' attributes + VERSION = '1.40' container_type = consts.TYPE_CONTAINER @@ -407,7 +409,8 @@ class Container(ContainerBase): @base.ZunObjectRegistry.register class Capsule(ContainerBase): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Add 'tty' attributes + VERSION = '1.1' container_type = consts.TYPE_CAPSULE @@ -447,7 +450,8 @@ class Capsule(ContainerBase): @base.ZunObjectRegistry.register class CapsuleContainer(ContainerBase): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Add 'tty' attributes + VERSION = '1.1' container_type = consts.TYPE_CAPSULE_CONTAINER @@ -472,7 +476,8 @@ class CapsuleContainer(ContainerBase): @base.ZunObjectRegistry.register class CapsuleInitContainer(ContainerBase): # Version 1.0: Initial version - VERSION = '1.0' + # Version 1.1: Add 'tty' attributes + VERSION = '1.1' container_type = consts.TYPE_CAPSULE_INIT_CONTAINER diff --git a/zun/tests/unit/api/base.py b/zun/tests/unit/api/base.py index f70cf8877..d7f1f3f0c 100644 --- a/zun/tests/unit/api/base.py +++ b/zun/tests/unit/api/base.py @@ -26,7 +26,7 @@ from zun.tests.unit.db import base PATH_PREFIX = '/v1' -CURRENT_VERSION = "container 1.35" +CURRENT_VERSION = "container 1.36" class FunctionalTest(base.DbTestCase): diff --git a/zun/tests/unit/api/controllers/test_root.py b/zun/tests/unit/api/controllers/test_root.py index 5cbbc6ded..18010ca2e 100644 --- a/zun/tests/unit/api/controllers/test_root.py +++ b/zun/tests/unit/api/controllers/test_root.py @@ -28,7 +28,7 @@ class TestRootController(api_base.FunctionalTest): 'default_version': {'id': 'v1', 'links': [{'href': 'http://localhost/v1/', 'rel': 'self'}], - 'max_version': '1.35', + 'max_version': '1.36', 'min_version': '1.1', 'status': 'CURRENT'}, 'description': 'Zun is an OpenStack project which ' @@ -37,7 +37,7 @@ class TestRootController(api_base.FunctionalTest): 'versions': [{'id': 'v1', 'links': [{'href': 'http://localhost/v1/', 'rel': 'self'}], - 'max_version': '1.35', + 'max_version': '1.36', 'min_version': '1.1', 'status': 'CURRENT'}]} diff --git a/zun/tests/unit/db/utils.py b/zun/tests/unit/db/utils.py index ff2ea5842..b0d0ec40b 100644 --- a/zun/tests/unit/db/utils.py +++ b/zun/tests/unit/db/utils.py @@ -80,6 +80,7 @@ def get_test_container(**kwargs): {'Name': 'no', 'MaximumRetryCount': '0'}), 'status_detail': kwargs.get('status_detail', 'up from 5 hours'), 'interactive': kwargs.get('interactive', True), + 'tty': kwargs.get('tty', True), 'image_driver': kwargs.get('image_driver', 'glance'), 'websocket_url': 'ws://127.0.0.1:6784/4c03164962fa/attach/' 'ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1', diff --git a/zun/tests/unit/objects/test_objects.py b/zun/tests/unit/objects/test_objects.py index aaba8e332..6281c0fe7 100644 --- a/zun/tests/unit/objects/test_objects.py +++ b/zun/tests/unit/objects/test_objects.py @@ -344,10 +344,10 @@ class TestObject(test_base.TestCase, _TestObject): # For more information on object version testing, read # https://docs.openstack.org/zun/latest/ object_data = { - 'Capsule': '1.0-fb200a8860db6d6fd9b2cf4b9efbf3a3', - 'CapsuleContainer': '1.0-c7f84d8e07d854ddfc20140f2e6dd703', - 'CapsuleInitContainer': '1.0-c7f84d8e07d854ddfc20140f2e6dd703', - 'Container': '1.39-1ac92cdfe46067b990ed147038229a81', + 'Capsule': '1.1-829f8acb1ca4b57d33fa09233c9520d3', + 'CapsuleContainer': '1.1-712817e2fcc085dbf0a794b3770e1907', + 'CapsuleInitContainer': '1.1-712817e2fcc085dbf0a794b3770e1907', + 'Container': '1.40-a24b78bcfb8c2c7e77ed24bd4a43dda1', 'Cpuset': '1.0-06c4e6335683c18b87e2e54080f8c341', 'Volume': '1.0-034768f2f5c5e89acb5ee45c6d3f3403', 'VolumeMapping': '1.5-57febc66526185a75a744637e7a387c7',