Rename image_id to image in container object

Currently, magnum used "image_id" to reflect the image in container,
but actually, we can support use both image name and image id to create
a container. The name "image_id" may confuse user that we only support
"image_id" when create a container.

This patch rename the "image_id" field to "image" in container object.

Change-Id: Ie3639feb2a2a90300662b74f186ef998d38d6cc4
Closes-Bug: #1466278
Closes-Bug: #1465558
This commit is contained in:
Lan Qi song 2015-06-18 10:33:31 +08:00
parent 5d94fc8a06
commit 8f1255f0f0
13 changed files with 69 additions and 38 deletions

View File

@ -356,7 +356,7 @@ Next we will create a container in this bay. This container will ping the
address 8.8.8.8 four times. ::
$ BAY_UUID=$(magnum bay-list | awk '/ swarmbay /{print $2}')
$ magnum container-create --name testcontainer --image_id cirros\
$ magnum container-create --name testcontainer --image cirros\
--bay $BAY_UUID\
--command "ping -c 4 8.8.8.8"
+------------+----------------------------------------+
@ -366,7 +366,7 @@ address 8.8.8.8 four times. ::
| links | ... |
| bay_uuid | eda91c1e-6103-45d4-ab09-3f316310fa8e |
| updated_at | None |
| image_id | cirros |
| image | cirros |
| command | ping -c 4 8.8.8.8 |
| created_at | 2015-04-22T20:21:11+00:00 |
| name | test-container |

View File

@ -72,8 +72,8 @@ class Container(base.APIBase):
name = wtypes.StringType(min_length=1, max_length=255)
"""Name of this container"""
image_id = wtypes.text
"""The image name or UUID to use as a base image for this baymodel"""
image = wtypes.text
"""The image name or ID to use as a base image for this container"""
bay_uuid = wsme.wsproperty(types.uuid, _get_bay_uuid, _set_bay_uuid,
mandatory=True)
@ -101,7 +101,7 @@ class Container(base.APIBase):
def _convert_with_links(container, url, expand=True):
if not expand:
container.unset_fields_except(['uuid', 'name', 'bay_uuid',
'image_id', 'command', 'status'])
'image', 'command', 'status'])
container.links = [link.Link.make_link(
'self', url,
@ -122,7 +122,7 @@ class Container(base.APIBase):
def sample(cls, expand=True):
sample = cls(uuid='27e3153e-d5bf-4b7e-b517-fb518e17f34c',
name='example',
image_id='ubuntu',
image='ubuntu',
command='env',
status='Running',
bay_uuid="fff114da-3bfa-4a0f-a123-c0dffad9718e",

View File

@ -15,8 +15,8 @@ import docker
from docker.utils import utils
def parse_docker_image(image_id):
image_parts = image_id.split(':', 1)
def parse_docker_image(image):
image_parts = image.split(':', 1)
image_repo = image_parts[0]
image_tag = None

View File

@ -114,14 +114,14 @@ class Handler(object):
@wrap_container_exception
def container_create(self, context, name, container_uuid, container):
docker = self.get_docker_client(context, container)
image_id = container.image_id
image = container.image
LOG.debug('Creating container with image %s name %s'
% (image_id, name))
% (image, name))
try:
image_repo, image_tag = docker_utils.parse_docker_image(image_id)
image_repo, image_tag = docker_utils.parse_docker_image(image)
docker.pull(image_repo, tag=image_tag)
docker.inspect_image(self._encode_utf8(container.image_id))
docker.create_container(image_id, name=name,
docker.inspect_image(self._encode_utf8(container.image))
docker.create_container(image, name=name,
hostname=container_uuid,
command=container.command)
container.status = obj_container.STOPPED

View File

@ -0,0 +1,31 @@
# 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.
"""rename_container_image_id
Revision ID: 1c1ff5e56048
Revises: 156ceb17fb0a
Create Date: 2015-06-18 10:21:40.991734
"""
# revision identifiers, used by Alembic.
revision = '1c1ff5e56048'
down_revision = '156ceb17fb0a'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.alter_column('container', 'image_id',
new_column_name='image',
existing_type=sa.String(255))

View File

@ -408,8 +408,8 @@ class Connection(api.Connection):
if 'name' in filters:
query = query.filter_by(name=filters['name'])
if 'image_id' in filters:
query = query.filter_by(image_id=filters['image_id'])
if 'image' in filters:
query = query.filter_by(image=filters['image'])
if 'project_id' in filters:
query = query.filter_by(project_id=filters['project_id'])
if 'user_id' in filters:

View File

@ -186,7 +186,7 @@ class Container(Base):
user_id = Column(String(255))
uuid = Column(String(36))
name = Column(String(255))
image_id = Column(String(255))
image = Column(String(255))
command = Column(String(255))
bay_uuid = Column(String(36))
status = Column(String(20))

View File

@ -40,7 +40,7 @@ class Container(base.MagnumPersistentObject, base.MagnumObject,
'name': fields.StringField(nullable=True),
'project_id': fields.StringField(nullable=True),
'user_id': fields.StringField(nullable=True),
'image_id': fields.StringField(nullable=True),
'image': fields.StringField(nullable=True),
'command': fields.StringField(nullable=True),
'bay_uuid': fields.StringField(nullable=True),
'status': fields.StringField(nullable=True),

View File

@ -35,7 +35,7 @@ class TestContainerController(db_base.DbTestCase):
def test_create_container(self, mock_container_create,):
mock_container_create.side_effect = lambda x, y, z: z
params = ('{"name": "My Docker", "image_id": "ubuntu",'
params = ('{"name": "My Docker", "image": "ubuntu",'
'"command": "env",'
'"bay_uuid": "fff114da-3bfa-4a0f-a123-c0dffad9718e"}')
response = self.app.post('/v1/containers',
@ -54,7 +54,7 @@ class TestContainerController(db_base.DbTestCase):
mock_container_show):
mock_container_create.side_effect = lambda x, y, z: z
# Create a container with a command
params = ('{"name": "My Docker", "image_id": "ubuntu",'
params = ('{"name": "My Docker", "image": "ubuntu",'
'"command": "env",'
'"bay_uuid": "fff114da-3bfa-4a0f-a123-c0dffad9718e"}')
response = self.app.post('/v1/containers',
@ -92,7 +92,7 @@ class TestContainerController(db_base.DbTestCase):
mock_container_show):
mock_container_create.side_effect = lambda x, y, z: z
# Create a container with a command
params = ('{"name": "My Docker", "image_id": "ubuntu",'
params = ('{"name": "My Docker", "image": "ubuntu",'
'"command": "env",'
'"bay_uuid": "fff114da-3bfa-4a0f-a123-c0dffad9718e"}')
response = self.app.post('/v1/containers',
@ -124,7 +124,7 @@ class TestContainerController(db_base.DbTestCase):
@patch('magnum.conductor.api.API.container_create')
def test_create_container_without_name(self, mock_container_create):
# No name param
params = ('{"image_id": "ubuntu", "command": "env",'
params = ('{"image": "ubuntu", "command": "env",'
'"bay_uuid": "fff114da-3bfa-4a0f-a123-c0dffad9718e"}')
self.assertRaises(AppError, self.app.post, '/v1/containers',
params=params, content_type='application/json')
@ -133,7 +133,7 @@ class TestContainerController(db_base.DbTestCase):
@patch('magnum.conductor.api.API.container_create')
def test_create_container_invalid_long_name(self, mock_container_create,):
# Long name
params = ('{"name": "' + 'i' * 256 + '", "image_id": "ubuntu",'
params = ('{"name": "' + 'i' * 256 + '", "image": "ubuntu",'
'"command": "env",'
'"bay_uuid": "fff114da-3bfa-4a0f-a123-c0dffad9718e"}')
self.assertRaises(AppError, self.app.post, '/v1/containers',

View File

@ -111,19 +111,19 @@ class TestDockerConductor(base.BaseTestCase):
mock_get_docker_client.return_value = mock_docker
mock_container = mock.MagicMock()
mock_container.image_id = 'test_image:some_tag'
mock_container.image = 'test_image:some_tag'
mock_container.command = None
container = self.conductor.container_create(
None, 'some-name',
'some-uuid', mock_container)
utf8_image_id = self.conductor._encode_utf8(mock_container.image_id)
utf8_image = self.conductor._encode_utf8(mock_container.image)
mock_docker.pull.assert_called_once_with('test_image',
tag='some_tag')
mock_docker.inspect_image.assert_called_once_with(utf8_image_id)
mock_docker.inspect_image.assert_called_once_with(utf8_image)
mock_docker.create_container.assert_called_once_with(
mock_container.image_id,
mock_container.image,
name='some-name',
hostname='some-uuid',
command=None)
@ -135,19 +135,19 @@ class TestDockerConductor(base.BaseTestCase):
mock_get_docker_client.return_value = mock_docker
mock_container = mock.MagicMock()
mock_container.image_id = 'test_image:some_tag'
mock_container.image = 'test_image:some_tag'
mock_container.command = 'env'
container = self.conductor.container_create(
None, 'some-name',
'some-uuid', mock_container)
utf8_image_id = self.conductor._encode_utf8(mock_container.image_id)
utf8_image = self.conductor._encode_utf8(mock_container.image)
mock_docker.pull.assert_called_once_with('test_image',
tag='some_tag')
mock_docker.inspect_image.assert_called_once_with(utf8_image_id)
mock_docker.inspect_image.assert_called_once_with(utf8_image)
mock_docker.create_container.assert_called_once_with(
mock_container.image_id,
mock_container.image,
name='some-name',
hostname='some-uuid',
command='env')
@ -158,7 +158,7 @@ class TestDockerConductor(base.BaseTestCase):
mock_docker = mock.MagicMock()
mock_get_docker_client.return_value = mock_docker
mock_container = mock.MagicMock()
mock_container.image_id = 'test_image:some_tag'
mock_container.image = 'test_image:some_tag'
with patch.object(errors.APIError, '__str__',
return_value='hit error') as mock_init:
mock_docker.pull = mock.Mock(

View File

@ -112,20 +112,20 @@ class DbContainerTestCase(base.DbTestCase):
def test_update_container(self):
container = utils.create_test_container()
old_image = container.image_id
old_image = container.image
new_image = 'new-image'
self.assertNotEqual(old_image, new_image)
res = self.dbapi.update_container(container.id,
{'image_id': new_image})
self.assertEqual(new_image, res.image_id)
{'image': new_image})
self.assertEqual(new_image, res.image)
def test_update_container_not_found(self):
container_uuid = magnum_utils.generate_uuid()
new_image = 'new-image'
self.assertRaises(exception.ContainerNotFound,
self.dbapi.update_container,
container_uuid, {'image_id': new_image})
container_uuid, {'image': new_image})
def test_update_container_uuid(self):
container = utils.create_test_container()

View File

@ -182,7 +182,7 @@ def get_test_container(**kw):
'name': kw.get('name', 'container1'),
'project_id': kw.get('project_id', 'fake_project'),
'user_id': kw.get('user_id', 'fake_user'),
'image_id': kw.get('image_id', 'ubuntu'),
'image': kw.get('image', 'ubuntu'),
'created_at': kw.get('created_at'),
'updated_at': kw.get('updated_at'),
'command': kw.get('command', 'fake_command'),

View File

@ -97,12 +97,12 @@ class TestContainerObject(base.DbTestCase):
with mock.patch.object(self.dbapi, 'update_container',
autospec=True) as mock_update_container:
container = objects.Container.get_by_uuid(self.context, uuid)
container.image_id = 'container.img'
container.image = 'container.img'
container.save()
mock_get_container.assert_called_once_with(self.context, uuid)
mock_update_container.assert_called_once_with(
uuid, {'image_id': 'container.img'})
uuid, {'image': 'container.img'})
self.assertEqual(self.context, container._context)
def test_refresh(self):