Convert type of 'command' from string to list
Zun is currently using a string representation of 'command', but Docker is returning 'Cmd' in string representation. This requires a conversion of commands between list and string, which is complicated and error-prone (it might causes bugs like https://review.openstack.org/#/c/551795/). It is better to switch from string to list Co-Authored-By: Hongbin Lu <hongbin034@gmail.com> Change-Id: Ie0df504a67cc20907d35e3513fd80d3f6be687fd Closes-Bug: #1755019
This commit is contained in:
parent
e1e9ac23f4
commit
b03fbe6dfd
|
@ -13,11 +13,14 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import shlex
|
||||
|
||||
from neutronclient.common import exceptions as n_exc
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import strutils
|
||||
from oslo_utils import uuidutils
|
||||
import pecan
|
||||
import six
|
||||
|
||||
from zun.api.controllers import base
|
||||
from zun.api.controllers import link
|
||||
|
@ -269,12 +272,34 @@ class ContainersController(base.Controller):
|
|||
name = name_gen.generate()
|
||||
return name + '-container'
|
||||
|
||||
@base.Controller.api_version("1.1", "1.19")
|
||||
@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.legacy_container_create)
|
||||
def post(self, run=False, **container_dict):
|
||||
# NOTE(hongbin): We convert the representation of 'command' from
|
||||
# string to list. For example:
|
||||
# '"nginx" "-g" "daemon off;"' -> ["nginx", "-g", "daemon off;"]
|
||||
command = container_dict.pop('command', None)
|
||||
if command is not None:
|
||||
if isinstance(command, six.string_types):
|
||||
command = shlex.split(command)
|
||||
container_dict['command'] = command
|
||||
|
||||
return self._do_post(run, **container_dict)
|
||||
|
||||
@base.Controller.api_version("1.20") # 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):
|
||||
return self._do_post(run, **container_dict)
|
||||
|
||||
def _do_post(self, run=False, **container_dict):
|
||||
"""Create or run a new container.
|
||||
|
||||
:param run: if true, starts the container
|
||||
|
|
|
@ -14,7 +14,7 @@ import copy
|
|||
|
||||
from zun.api.controllers.v1.schemas import parameter_types
|
||||
|
||||
_container_properties = {
|
||||
_legacy_container_properties = {
|
||||
'name': parameter_types.container_name,
|
||||
'image': parameter_types.image_name,
|
||||
'command': parameter_types.command,
|
||||
|
@ -39,6 +39,16 @@ _container_properties = {
|
|||
'auto_heal': parameter_types.boolean,
|
||||
}
|
||||
|
||||
legacy_container_create = {
|
||||
'type': 'object',
|
||||
'properties': _legacy_container_properties,
|
||||
'required': ['image'],
|
||||
'additionalProperties': False
|
||||
}
|
||||
|
||||
_container_properties = copy.deepcopy(_legacy_container_properties)
|
||||
_container_properties['command'] = parameter_types.command_list
|
||||
|
||||
container_create = {
|
||||
'type': 'object',
|
||||
'properties': _container_properties,
|
||||
|
|
|
@ -81,6 +81,10 @@ command = {
|
|||
'type': ['string', 'null']
|
||||
}
|
||||
|
||||
command_list = {
|
||||
'type': ['array', 'null']
|
||||
}
|
||||
|
||||
auto_remove = {
|
||||
'type': ['boolean', 'null']
|
||||
}
|
||||
|
|
|
@ -52,10 +52,11 @@ REST_API_VERSION_HISTORY = """REST API Version History:
|
|||
* 1.17 - Add support for detaching ports
|
||||
* 1.18 - Modify the response of network list
|
||||
* 1.19 - Intoduce container resize API
|
||||
* 1.20 - Convert type of 'command' from string to list
|
||||
"""
|
||||
|
||||
BASE_VER = '1.1'
|
||||
CURRENT_MAX_VER = '1.19'
|
||||
CURRENT_MAX_VER = '1.20'
|
||||
|
||||
|
||||
class Version(object):
|
||||
|
|
|
@ -167,3 +167,8 @@ user documentation.
|
|||
|
||||
Introduce an API endpoint for resizing a container, such as changing the
|
||||
CPU or memory of the container.
|
||||
|
||||
1.20
|
||||
----
|
||||
|
||||
Convert type of 'command' from string to list
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import functools
|
||||
from oslo_utils import uuidutils
|
||||
import pecan
|
||||
|
||||
|
@ -96,6 +97,7 @@ def enforce_content_types(valid_content_types):
|
|||
|
||||
def content_types_decorator(fn):
|
||||
|
||||
@functools.wraps(fn)
|
||||
def content_types_enforcer(inst, *args, **kwargs):
|
||||
_do_enforce_content_types(pecan.request, valid_content_types)
|
||||
return fn(inst, *args, **kwargs)
|
||||
|
|
|
@ -639,18 +639,7 @@ class DockerDriver(driver.ContainerDriver):
|
|||
|
||||
def _populate_command(self, container, config):
|
||||
command_list = config.get('Cmd')
|
||||
command_str = None
|
||||
if command_list:
|
||||
# NOTE(hongbin): We convert the representation of the command
|
||||
# from list to string. For example:
|
||||
# * list: ["nginx", "-g", "daemon off;"]
|
||||
# * string: '"nginx" "-g" "daemon off;"'
|
||||
# In the string representation, we quote each command's token
|
||||
# to avoid potential ambiguity (without quoting, the string
|
||||
# representation will be 'nginx -g daemon off;' so we don't
|
||||
# how the original command arguments were tokenized).
|
||||
command_str = ' '.join('"%s"' % x for x in command_list)
|
||||
container.command = command_str
|
||||
container.command = command_list
|
||||
|
||||
def _populate_hostname_and_ports(self, container, config):
|
||||
# populate hostname only when container.hostname wasn't set
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
# 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.
|
||||
|
||||
|
||||
"""Convert type of 'command' from string to list
|
||||
|
||||
Revision ID: 3e80bbfd8da7
|
||||
Revises: 26896d5f9053
|
||||
Create Date: 2018-06-20 11:21:38.077673
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import shlex
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '3e80bbfd8da7'
|
||||
down_revision = '26896d5f9053'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
TABLE_MODEL = sa.Table(
|
||||
'container', sa.MetaData(),
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('command', sa.Text()))
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.alter_column('container', 'command', type_=sa.Text())
|
||||
# Convert 'command' from string to json-encoded list
|
||||
session = sa.orm.Session(bind=op.get_bind())
|
||||
with session.begin(subtransactions=True):
|
||||
for row in session.query(TABLE_MODEL):
|
||||
if row[1]:
|
||||
command = shlex.split(row[1])
|
||||
command = json.dumps(command)
|
||||
session.execute(
|
||||
TABLE_MODEL.update().values(
|
||||
command=command).where(
|
||||
TABLE_MODEL.c.id == row[0]))
|
||||
session.commit()
|
|
@ -142,7 +142,7 @@ class Container(Base):
|
|||
name = Column(String(255))
|
||||
image = Column(String(255))
|
||||
cpu = Column(Float)
|
||||
command = Column(String(255))
|
||||
command = Column(JSONEncodedList)
|
||||
memory = Column(String(255))
|
||||
status = Column(String(20))
|
||||
status_reason = Column(Text, nullable=True)
|
||||
|
|
|
@ -62,7 +62,7 @@ class Container(base.ZunPersistentObject, base.ZunObject):
|
|||
# Version 1.30: Add capsule_id attribute
|
||||
# Version 1.31: Add 'started_at' attribute
|
||||
# Version 1.32: Add 'exec_instances' attribute
|
||||
VERSION = '1.32'
|
||||
VERSION = '1.33'
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(),
|
||||
|
@ -74,7 +74,7 @@ class Container(base.ZunPersistentObject, base.ZunObject):
|
|||
'image': fields.StringField(nullable=True),
|
||||
'cpu': fields.FloatField(nullable=True),
|
||||
'memory': fields.StringField(nullable=True),
|
||||
'command': fields.StringField(nullable=True),
|
||||
'command': fields.ListOfStringsField(nullable=True),
|
||||
'status': z_fields.ContainerStatusField(nullable=True),
|
||||
'status_reason': fields.StringField(nullable=True),
|
||||
'task_state': z_fields.TaskStateField(nullable=True),
|
||||
|
|
|
@ -26,7 +26,7 @@ from zun.tests.unit.db import base
|
|||
|
||||
|
||||
PATH_PREFIX = '/v1'
|
||||
CURRENT_VERSION = "container 1.19"
|
||||
CURRENT_VERSION = "container 1.20"
|
||||
|
||||
|
||||
class FunctionalTest(base.DbTestCase):
|
||||
|
|
|
@ -28,7 +28,7 @@ class TestRootController(api_base.FunctionalTest):
|
|||
'default_version':
|
||||
{'id': 'v1',
|
||||
'links': [{'href': 'http://localhost/v1/', 'rel': 'self'}],
|
||||
'max_version': '1.19',
|
||||
'max_version': '1.20',
|
||||
'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.19',
|
||||
'max_version': '1.20',
|
||||
'min_version': '1.1',
|
||||
'status': 'CURRENT'}]}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
|
||||
response = self.post('/v1/containers?run=true',
|
||||
|
@ -50,7 +50,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
def test_run_container_wrong_run_value(self, mock_search,
|
||||
mock_container_create):
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
with self.assertRaisesRegex(AppError,
|
||||
"Invalid input for query parameters"):
|
||||
|
@ -60,7 +60,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
@patch('zun.compute.api.API.container_create')
|
||||
def test_run_container_wrong_memory_value(self, mock_container_create):
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "3",'
|
||||
'"command": ["env"], "memory": "3",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
with self.assertRaisesRegex(AppError,
|
||||
"Invalid input for query parameters"):
|
||||
|
@ -70,7 +70,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
@patch('zun.compute.api.API.container_create')
|
||||
def test_run_container_wrong_cpu_value(self, mock_container_create):
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512", "cpu": "100"'
|
||||
'"command": ["env"], "memory": "512", "cpu": "100"'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
with self.assertRaisesRegex(AppError,
|
||||
"Invalid input for query parameters"):
|
||||
|
@ -80,7 +80,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
@patch('zun.compute.api.API.container_create')
|
||||
def test_run_container_wrong_disk_value(self, mock_container_create):
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512", "disk": "0"'
|
||||
'"command": ["env"], "memory": "512", "disk": "0"'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
with self.assertRaisesRegex(AppError,
|
||||
"Invalid input for query parameters"):
|
||||
|
@ -101,7 +101,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
|
||||
def test_run_container_runtime_wrong_value(self):
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"},'
|
||||
'"runtime": 1234}')
|
||||
with self.assertRaisesRegex(AppError,
|
||||
|
@ -130,7 +130,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
response = self.post('/v1/containers?run=false',
|
||||
params=params,
|
||||
|
@ -146,7 +146,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create):
|
||||
mock_container_create.side_effect = exception.InvalidValue
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
self.assertRaises(AppError, self.post, '/v1/containers?run=wrong',
|
||||
params=params, content_type='application/json')
|
||||
|
@ -159,7 +159,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_neutron_get_network):
|
||||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
response = self.post('/v1/containers/',
|
||||
params=params,
|
||||
|
@ -181,7 +181,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
mock_can.return_value = True
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
response = self.post('/v1/containers/',
|
||||
params=params,
|
||||
|
@ -197,7 +197,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
def test_create_container_image_not_specified(self, mock_container_create):
|
||||
|
||||
params = ('{"name": "MyDocker",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
with self.assertRaisesRegex(AppError,
|
||||
"is a required property"):
|
||||
|
@ -219,7 +219,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = _create_side_effect
|
||||
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
self.post('/v1/containers/',
|
||||
params=params,
|
||||
|
@ -235,7 +235,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"}}')
|
||||
response = self.post('/v1/containers/',
|
||||
params=params,
|
||||
|
@ -267,7 +267,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_search_volume.return_value = fake_volume
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"},'
|
||||
'"runtime": "runc", "hostname": "testhost",'
|
||||
'"disk": 20, "restart_policy": {"Name": "no"},'
|
||||
|
@ -283,7 +283,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('512', c.get('memory'))
|
||||
self.assertEqual({"key1": "val1", "key2": "val2"},
|
||||
c.get('environment'))
|
||||
|
@ -341,7 +341,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertIsNotNone(c.get('name'))
|
||||
self.assertIsNone(c.get('command'))
|
||||
self.assertIsNone(None, c.get('command'))
|
||||
self.assertEqual('2048', c.get('memory'))
|
||||
self.assertEqual(1.0, c.get('cpu'))
|
||||
# TODO(kiennt): Uncomment it when bug [1] be resolved.
|
||||
|
@ -370,7 +370,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_neutron_get_network.return_value = fake_network
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env",'
|
||||
'"command": ["env"],'
|
||||
'"availability_zone": "test-az"}')
|
||||
response = self.post('/v1/containers/',
|
||||
params=params,
|
||||
|
@ -382,7 +382,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('2048', c.get('memory'))
|
||||
self.assertEqual(1.0, c.get('cpu'))
|
||||
# TODO(kiennt): Uncomment it when bug [1] be resolved.
|
||||
|
@ -409,7 +409,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_neutron_get_network.return_value = fake_network
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"restart_policy": {"Name": "no",'
|
||||
'"MaximumRetryCount": "0"}}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -422,7 +422,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('512', c.get('memory'))
|
||||
self.assertEqual({"Name": "no", "MaximumRetryCount": "0"},
|
||||
c.get('restart_policy'))
|
||||
|
@ -446,7 +446,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_neutron_get_network.return_value = fake_network
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"restart_policy": {"Name": "no",'
|
||||
'"MaximumRetryCount": "6"}}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -459,7 +459,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('512', c.get('memory'))
|
||||
self.assertEqual({"Name": "no", "MaximumRetryCount": "0"},
|
||||
c.get('restart_policy'))
|
||||
|
@ -483,7 +483,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_neutron_get_network.return_value = fake_network
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"restart_policy": {"Name": "unless-stopped",'
|
||||
'"MaximumRetryCount": "0"}}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -496,7 +496,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('512', c.get('memory'))
|
||||
self.assertEqual({"Name": "unless-stopped", "MaximumRetryCount": "0"},
|
||||
c.get('restart_policy'))
|
||||
|
@ -528,7 +528,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_show_port.return_value = {'port': fake_port}
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"},'
|
||||
'"nets": [{"port": "testport"}]}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -541,7 +541,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('512', c.get('memory'))
|
||||
self.assertEqual({"key1": "val1", "key2": "val2"},
|
||||
c.get('environment'))
|
||||
|
@ -584,7 +584,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_get_network.return_value = fake_public_network
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"},'
|
||||
'"nets": [{"network": "testpublicnet"}]}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -619,13 +619,13 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_get_network.return_value = fake_network
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"},'
|
||||
'"nets": [{"network": "fakenetid", "v4-fixed-ip": '
|
||||
'"10.0.0.10"}]}')
|
||||
response = self.app.post('/v1/containers/',
|
||||
params=params,
|
||||
content_type='application/json')
|
||||
response = self.post('/v1/containers/',
|
||||
params=params,
|
||||
content_type='application/json')
|
||||
fake_admin_authorize = True
|
||||
mock_authorize.return_value = fake_admin_authorize
|
||||
self.assertEqual(202, response.status_int)
|
||||
|
@ -648,7 +648,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_create_volume.return_value = fake_volume
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"mounts": [{"destination": "d", '
|
||||
'"size": "5"}]}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -665,7 +665,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
c = response.json['containers'][0]
|
||||
self.assertIsNotNone(c.get('uuid'))
|
||||
self.assertEqual('MyDocker', c.get('name'))
|
||||
self.assertEqual('env', c.get('command'))
|
||||
self.assertEqual(["env"], c.get('command'))
|
||||
self.assertEqual('Creating', c.get('status'))
|
||||
self.assertEqual('512', c.get('memory'))
|
||||
self.assertIn('host', c)
|
||||
|
@ -692,7 +692,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"restart_policy": {"Name": "always",'
|
||||
'"MaximumRetryCount": "1"}}')
|
||||
with self.assertRaisesRegex(
|
||||
|
@ -709,7 +709,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create):
|
||||
# Long name
|
||||
params = ('{"name": "' + 'i' * 256 + '", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512"}')
|
||||
'"command": ["env"], "memory": "512"}')
|
||||
self.assertRaises(AppError, self.post, '/v1/containers/',
|
||||
params=params, content_type='application/json')
|
||||
self.assertTrue(mock_container_create.not_called)
|
||||
|
@ -1476,7 +1476,7 @@ class TestContainerController(api_base.FunctionalTest):
|
|||
mock_container_create.side_effect = lambda x, y, **z: y
|
||||
# Create a container with a command
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512",'
|
||||
'"command": ["env"], "memory": "512",'
|
||||
'"environment": {"key1": "val1", "key2": "val2"},'
|
||||
'"image_driver": "glance"}')
|
||||
response = self.post('/v1/containers/',
|
||||
|
@ -2049,7 +2049,7 @@ class TestContainerEnforcement(api_base.FunctionalTest):
|
|||
|
||||
def test_policy_disallow_create(self):
|
||||
params = ('{"name": "MyDocker", "image": "ubuntu",'
|
||||
'"command": "env", "memory": "512"}')
|
||||
'"command": ["env"], "memory": "512"}')
|
||||
|
||||
self._common_policy_check(
|
||||
'container:create', self.post, '/v1/containers/',
|
||||
|
|
|
@ -21,7 +21,7 @@ CONTAINER_CREATE = {
|
|||
'properties': {
|
||||
'name': parameter_types.container_name,
|
||||
'image': parameter_types.image_name,
|
||||
'command': parameter_types.command,
|
||||
'command': parameter_types.command_list,
|
||||
'cpu': parameter_types.cpu,
|
||||
'memory': parameter_types.memory,
|
||||
'workdir': parameter_types.workdir,
|
||||
|
@ -55,7 +55,8 @@ class TestSchemaValidations(base.BaseTestCase):
|
|||
|
||||
def test_create_schema_with_all_valid_parameters(self):
|
||||
request_to_validate = {'name': 'test1', 'image': 'nginx',
|
||||
'command': '/bin/sh', 'cpu': 1.0,
|
||||
'command': ["/bin/sh"],
|
||||
'cpu': 1.0,
|
||||
'memory': '5', 'workdir': '/workdir',
|
||||
'image_pull_policy': 'never',
|
||||
'labels': {'abc': 12, 'bcd': 'xyz'},
|
||||
|
|
|
@ -138,7 +138,7 @@ class TestDockerDriver(base.DriverTestCase):
|
|||
kwargs = {
|
||||
'name': '%sea8e2a25-2901-438d-8157-de7ffd68d051' %
|
||||
consts.NAME_PREFIX,
|
||||
'command': 'fake_command',
|
||||
'command': ['fake_command'],
|
||||
'environment': {'key1': 'val1', 'key2': 'val2'},
|
||||
'working_dir': '/home/ubuntu',
|
||||
'labels': {'key1': 'val1', 'key2': 'val2'},
|
||||
|
@ -204,7 +204,7 @@ class TestDockerDriver(base.DriverTestCase):
|
|||
kwargs = {
|
||||
'name': '%sea8e2a25-2901-438d-8157-de7ffd68d051' %
|
||||
consts.NAME_PREFIX,
|
||||
'command': 'fake_command',
|
||||
'command': ['fake_command'],
|
||||
'environment': {'key1': 'val1', 'key2': 'val2'},
|
||||
'working_dir': '/home/ubuntu',
|
||||
'labels': {'key1': 'val1', 'key2': 'val2'},
|
||||
|
@ -389,7 +389,7 @@ class TestDockerDriver(base.DriverTestCase):
|
|||
self.driver.show(self.context, mock_container)
|
||||
self.mock_docker.inspect_container.assert_called_once_with(
|
||||
mock_container.container_id)
|
||||
self.assertEqual('"fake_command"', mock_container.command)
|
||||
self.assertEqual(['fake_command'], mock_container.command)
|
||||
|
||||
def test_show_without_command(self):
|
||||
self.mock_docker.inspect_container = mock.Mock(
|
||||
|
|
|
@ -54,7 +54,7 @@ def get_test_container(**kwargs):
|
|||
'image': kwargs.get('image', 'ubuntu'),
|
||||
'created_at': kwargs.get('created_at'),
|
||||
'updated_at': kwargs.get('updated_at'),
|
||||
'command': kwargs.get('command', 'fake_command'),
|
||||
'command': kwargs.get('command', ['fake_command']),
|
||||
'status': kwargs.get('status', 'Running'),
|
||||
'status_reason': kwargs.get('status_reason', 'Created Successfully'),
|
||||
'task_state': kwargs.get('task_state', None),
|
||||
|
|
|
@ -344,7 +344,7 @@ class TestObject(test_base.TestCase, _TestObject):
|
|||
# For more information on object version testing, read
|
||||
# https://docs.openstack.org/zun/latest/
|
||||
object_data = {
|
||||
'Container': '1.32-9e9a594ca58e978fb7b580292692a1a7',
|
||||
'Container': '1.33-5eac0a995f25329ca566fdddde45c759',
|
||||
'VolumeMapping': '1.1-50df6202f7846a136a91444c38eba841',
|
||||
'Image': '1.1-330e6205c80b99b59717e1cfc6a79935',
|
||||
'MyObj': '1.0-34c4b1aadefd177b13f9a2f894cc23cd',
|
||||
|
|
Loading…
Reference in New Issue