You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1227 lines
44 KiB
1227 lines
44 KiB
# Copyright 2015 Red Hat, Inc. |
|
# |
|
# 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. |
|
# |
|
|
|
import fixtures |
|
from io import StringIO |
|
import mock |
|
import os |
|
import requests |
|
import shutil |
|
import sys |
|
import tempfile |
|
from urllib import parse |
|
import uuid |
|
import yaml |
|
|
|
from osc_lib import exceptions as oscexc |
|
from tripleo_common.image import kolla_builder |
|
from tripleoclient import constants |
|
from tripleoclient.tests.v1.test_plugin import TestPluginV1 |
|
from tripleoclient.v1 import container_image |
|
|
|
|
|
class TestContainerImageUpload(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestContainerImageUpload, self).setUp() |
|
|
|
# Get the command object to test |
|
self.cmd = container_image.UploadImage(self.app, None) |
|
|
|
@mock.patch('tripleo_common.utils.locks.processlock.' |
|
'ProcessLock') |
|
@mock.patch('sys.exit') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_container_image_upload_noargs(self, mock_manager, exit_mock, |
|
mock_lock): |
|
arglist = [] |
|
verifylist = [] |
|
|
|
mock_lockobj = mock.MagicMock() |
|
mock_lock.return_value = mock_lockobj |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
self.cmd.take_action(parsed_args) |
|
# argparse will complain that --config-file is missing and exit with 2 |
|
exit_mock.assert_called_with(2) |
|
|
|
@mock.patch('tripleo_common.utils.locks.processlock.' |
|
'ProcessLock') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_container_image_upload_conf_files(self, mock_manager, mock_lock): |
|
arglist = [ |
|
'--config-file', |
|
'/tmp/foo.yaml', |
|
'--config-file', |
|
'/tmp/bar.yaml' |
|
] |
|
verifylist = [] |
|
|
|
mock_lockobj = mock.MagicMock() |
|
mock_lock.return_value = mock_lockobj |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_manager.assert_called_once_with( |
|
['/tmp/foo.yaml', '/tmp/bar.yaml'], cleanup='full', |
|
lock=mock_lockobj) |
|
mock_manager.return_value.upload.assert_called_once_with() |
|
|
|
|
|
class TestContainerImagePush(TestPluginV1): |
|
def setUp(self): |
|
super(TestContainerImagePush, self).setUp() |
|
|
|
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock') |
|
self.mock_lock = lock.start() |
|
self.addCleanup(lock.stop) |
|
|
|
self.cmd = container_image.TripleOContainerImagePush(self.app, None) |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.UploadTask') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action(self, mock_manager, mock_task, mock_get_uc_registry): |
|
arglist = ['docker.io/namespace/foo'] |
|
verifylist = [('image_to_push', 'docker.io/namespace/foo')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
# mock upload task |
|
mock_uploadtask = mock.Mock() |
|
mock_task.return_value = mock_uploadtask |
|
|
|
# mock add upload task action |
|
mock_add_upload = mock.Mock() |
|
data = [] |
|
mock_add_upload.return_value = data |
|
mock_uploader.add_upload_task = mock_add_upload |
|
|
|
# mock run tasks action |
|
mock_run_tasks = mock.Mock() |
|
mock_uploader.run_tasks = mock_run_tasks |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_task.assert_called_once_with( |
|
image_name='namespace/foo', |
|
pull_source='docker.io', |
|
push_destination='uc.ctlplane.somedomain', |
|
append_tag=parsed_args.append_tag, |
|
modify_role=None, |
|
modify_vars=None, |
|
cleanup=False, |
|
multi_arch=parsed_args.multi_arch) |
|
|
|
mock_add_upload.assert_called_once_with(mock_uploadtask) |
|
mock_run_tasks.assert_called_once() |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.UploadTask') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action_local(self, mock_manager, mock_task, |
|
mock_get_uc_registry): |
|
arglist = ['docker.io/namespace/foo', '--local'] |
|
verifylist = [('image_to_push', 'docker.io/namespace/foo'), |
|
('local', True)] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
# mock upload task |
|
mock_uploadtask = mock.Mock() |
|
mock_task.return_value = mock_uploadtask |
|
|
|
# mock add upload task action |
|
mock_add_upload = mock.Mock() |
|
data = [] |
|
mock_add_upload.return_value = data |
|
mock_uploader.add_upload_task = mock_add_upload |
|
|
|
# mock run tasks action |
|
mock_run_tasks = mock.Mock() |
|
mock_uploader.run_tasks = mock_run_tasks |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_task.assert_called_once_with( |
|
image_name='containers-storage:docker.io/namespace/foo', |
|
pull_source=None, |
|
push_destination='uc.ctlplane.somedomain', |
|
append_tag=parsed_args.append_tag, |
|
modify_role=None, |
|
modify_vars=None, |
|
cleanup=False, |
|
multi_arch=parsed_args.multi_arch) |
|
|
|
mock_add_upload.assert_called_once_with(mock_uploadtask) |
|
mock_run_tasks.assert_called_once() |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.UploadTask') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action_local_path(self, mock_manager, mock_task, |
|
mock_get_uc_registry): |
|
arglist = ['containers-storage:docker.io/namespace/foo'] |
|
verifylist = [('image_to_push', |
|
'containers-storage:docker.io/namespace/foo')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
# mock upload task |
|
mock_uploadtask = mock.Mock() |
|
mock_task.return_value = mock_uploadtask |
|
|
|
# mock add upload task action |
|
mock_add_upload = mock.Mock() |
|
data = [] |
|
mock_add_upload.return_value = data |
|
mock_uploader.add_upload_task = mock_add_upload |
|
|
|
# mock run tasks action |
|
mock_run_tasks = mock.Mock() |
|
mock_uploader.run_tasks = mock_run_tasks |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_task.assert_called_once_with( |
|
image_name='containers-storage:docker.io/namespace/foo', |
|
pull_source=None, |
|
push_destination='uc.ctlplane.somedomain', |
|
append_tag=parsed_args.append_tag, |
|
modify_role=None, |
|
modify_vars=None, |
|
cleanup=False, |
|
multi_arch=parsed_args.multi_arch) |
|
|
|
mock_add_upload.assert_called_once_with(mock_uploadtask) |
|
mock_run_tasks.assert_called_once() |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.UploadTask') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action_oserror(self, mock_manager, mock_task, |
|
mock_get_uc_registry): |
|
arglist = ['docker.io/namespace/foo'] |
|
verifylist = [('image_to_push', 'docker.io/namespace/foo')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
# mock upload task |
|
mock_uploadtask = mock.Mock() |
|
mock_task.return_value = mock_uploadtask |
|
|
|
# mock add upload task action |
|
mock_add_upload = mock.Mock() |
|
data = [] |
|
mock_add_upload.return_value = data |
|
mock_uploader.add_upload_task = mock_add_upload |
|
|
|
# mock run tasks action |
|
mock_run_tasks = mock.Mock() |
|
mock_run_tasks.side_effect = OSError('Fail') |
|
mock_uploader.run_tasks = mock_run_tasks |
|
|
|
self.assertRaises(oscexc.CommandError, |
|
self.cmd.take_action, |
|
parsed_args) |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.UploadTask') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action_all_options(self, mock_manager, mock_task, |
|
mock_get_uc_registry): |
|
arglist = ['--registry-url', '127.0.0.1:8787', |
|
'--append-tag', 'test', |
|
'--source-username', 'sourceuser', |
|
'--source-password', 'sourcepassword', |
|
'--username', 'user', |
|
'--password', 'password', |
|
'--dry-run', |
|
'--multi-arch', |
|
'--cleanup', |
|
'docker.io/namespace/foo:tag'] |
|
verifylist = [('registry_url', '127.0.0.1:8787'), |
|
('append_tag', 'test'), |
|
('username', 'user'), |
|
('password', 'password'), |
|
('dry_run', True), |
|
('multi_arch', True), |
|
('cleanup', True), |
|
('image_to_push', 'docker.io/namespace/foo:tag')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
# mock upload task |
|
mock_uploadtask = mock.Mock() |
|
mock_task.return_value = mock_uploadtask |
|
|
|
# mock add upload task action |
|
mock_add_upload = mock.Mock() |
|
data = [] |
|
mock_add_upload.return_value = data |
|
mock_uploader.add_upload_task = mock_add_upload |
|
|
|
# mock run tasks action |
|
mock_run_tasks = mock.Mock() |
|
mock_uploader.run_tasks = mock_run_tasks |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
source_url = parse.urlparse("docker://docker.io/namespace/foo:tag") |
|
registry_url = parse.urlparse("docker://127.0.0.1:8787") |
|
auth_calls = [mock.call(source_url, |
|
parsed_args.source_username, |
|
parsed_args.source_password), |
|
mock.call(registry_url, |
|
parsed_args.username, |
|
parsed_args.password)] |
|
mock_uploader.authenticate.assert_has_calls(auth_calls) |
|
|
|
mock_task.assert_not_called() |
|
mock_add_upload.assert_not_called() |
|
mock_run_tasks.assert_not_called() |
|
|
|
|
|
class TestContainerImageDelete(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestContainerImageDelete, self).setUp() |
|
|
|
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock') |
|
self.mock_lock = lock.start() |
|
self.addCleanup(lock.stop) |
|
|
|
self.cmd = container_image.TripleOContainerImageDelete(self.app, None) |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_oserror(self, mock_manager, mock_get_uc_registry): |
|
|
|
arglist = ['-y', 'foo'] |
|
verifylist = [('yes', True), |
|
('image_to_delete', 'foo')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return url object from uploader._image_to_url |
|
mock_url = mock.Mock() |
|
mock_url.geturl.return_value = 'munged-reg-url' |
|
|
|
mock_uploader._image_to_url.return_value = mock_url |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
mock_uploader.delete.side_effect = OSError('Errno 13') |
|
self.assertRaises(oscexc.CommandError, |
|
self.cmd.take_action, |
|
parsed_args) |
|
mock_uploader.delete.assert_called_once_with('foo', |
|
session=mock_session) |
|
|
|
|
|
class TestContainerImageList(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestContainerImageList, self).setUp() |
|
|
|
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock') |
|
self.mock_lock = lock.start() |
|
self.addCleanup(lock.stop) |
|
|
|
self.cmd = container_image.TripleOContainerImageList(self.app, None) |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action(self, mock_manager, mock_get_uc_registry): |
|
arglist = [] |
|
verifylist = [] |
|
|
|
mock_manager.return_value.uploader.return_value.list.return_value = \ |
|
['a', 'b'] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
rv = self.cmd.take_action(parsed_args) |
|
actual = (('Image Name',), [('a',), ('b',)]) |
|
self.assertEqual(actual, rv) |
|
|
|
@mock.patch('tripleo_common.image.image_uploader.get_undercloud_registry', |
|
return_value='uc.ctlplane.somedomain') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action_auth(self, mock_manager, mock_get_uc_registry): |
|
# check arg parsing items |
|
arglist = ['--registry-url', 'reg-url', |
|
'--username', 'foo', |
|
'--password', 'bar'] |
|
verifylist = [('registry_url', 'reg-url'), |
|
('username', 'foo'), |
|
('password', 'bar')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return url object from uploader._image_to_url |
|
mock_url = mock.Mock() |
|
mock_url.geturl.return_value = 'munged-reg-url' |
|
|
|
mock_uploader._image_to_url.return_value = mock_url |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
|
|
# mock image list function |
|
mock_uploader.list.return_value = ['a', 'b'] |
|
|
|
rv = self.cmd.take_action(parsed_args) |
|
|
|
# check various functions are called with expected inputs |
|
mock_mgr.uploader.assert_called_with('python') |
|
mock_uploader._image_to_url.assert_called_with('reg-url') |
|
mock_uploader.authenticate.assert_called_with(mock_url, 'foo', 'bar') |
|
mock_uploader.list.assert_called_with('munged-reg-url', |
|
session=mock_session) |
|
|
|
# check data format for lister |
|
actual = (('Image Name',), [('a',), ('b',)]) |
|
self.assertEqual(actual, rv) |
|
|
|
|
|
class TestContainerImageShow(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestContainerImageShow, self).setUp() |
|
|
|
lock = mock.patch('tripleo_common.utils.locks.processlock.ProcessLock') |
|
self.mock_lock = lock.start() |
|
self.addCleanup(lock.stop) |
|
|
|
self.cmd = container_image.TripleOContainerImageShow(self.app, None) |
|
|
|
@mock.patch('tripleoclient.v1.container_image.TripleOContainerImageShow.' |
|
'format_image_inspect') |
|
@mock.patch('tripleo_common.image.image_uploader.ImageUploadManager') |
|
def test_take_action(self, mock_manager, mock_formatter): |
|
|
|
arglist = ['foo'] |
|
verifylist = [('image_to_inspect', 'foo')] |
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
# mock manager object |
|
mock_mgr = mock.Mock() |
|
mock_manager.return_value = mock_mgr |
|
|
|
# mock uploader object |
|
mock_uploader = mock.Mock() |
|
mock_mgr.uploader.return_value = mock_uploader |
|
|
|
# mock return url object from uploader._image_to_url |
|
mock_url = mock.Mock() |
|
mock_url.geturl.return_value = 'munged-reg-url' |
|
|
|
mock_uploader._image_to_url.return_value = mock_url |
|
|
|
# mock return session object from uploader.authenticate |
|
mock_session = mock.Mock() |
|
mock_uploader.authenticate.return_value = mock_session |
|
mock_inspect = mock.Mock() |
|
data = {'Name': 'a', 'Layers': 'b'} |
|
mock_inspect.return_value = data |
|
mock_uploader.inspect = mock_inspect |
|
|
|
# mock format image inspect |
|
formatted_data = (['Name', 'Layers'], ['a', 'b']) |
|
mock_formatter.return_value = formatted_data |
|
|
|
rv = self.cmd.take_action(parsed_args) |
|
|
|
mock_formatter.assert_called_once_with(data) |
|
self.assertEqual(formatted_data, rv) |
|
|
|
def test_format_image_inspect(self): |
|
test_data = {'Name': 'foo', 'Layers': 'bar'} |
|
self.assertEqual(self.cmd.format_image_inspect(test_data), |
|
(['Name', 'Layers'], ['foo', 'bar'])) |
|
|
|
|
|
class TestContainerImagePrepare(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestContainerImagePrepare, self).setUp() |
|
|
|
# Get the command object to test |
|
self.cmd = container_image.PrepareImageFiles(self.app, None) |
|
kolla_builder.DEFAULT_TEMPLATE_FILE = os.path.join( |
|
'/tmp/overcloud_containers.yaml.j2' |
|
) |
|
self.roles_yaml = ''' |
|
- name: EnabledRole |
|
CountDefault: 1 |
|
ServicesDefault: |
|
- OS::TripleO::Services::AodhEvaluator |
|
- name: RoleDisabledViaRolesData |
|
CountDefault: 0 |
|
ServicesDefault: |
|
- OS::TripleO::Services::AodhApi |
|
- name: RoleDisabledViaEnvironment |
|
CountDefault: 1 |
|
ServicesDefault: |
|
- OS::TripleO::Services::Disabled |
|
- name: RoleOverwrittenViaEnvironment |
|
CountDefault: 1 |
|
ServicesDefault: |
|
- OS::TripleO::Services::Overwritten |
|
''' |
|
|
|
@mock.patch('tripleo_common.image.kolla_builder.' |
|
'container_images_prepare_defaults', create=True) |
|
@mock.patch('tripleo_common.image.kolla_builder.' |
|
'container_images_prepare', create=True) |
|
@mock.patch('requests.get') |
|
@mock.patch('tripleo_common.image.kolla_builder.' |
|
'build_service_filter') |
|
def test_container_image_prepare_noargs(self, mock_bsf, mock_get, mock_cip, |
|
mock_cipd): |
|
mock_bsf.return_value = None |
|
mock_cipd.return_value = { |
|
'neutron_driver': 'ovn', |
|
'name_suffix': '', |
|
'tag': 'latest', |
|
'namespace': 'docker.io/tripleomaster', |
|
'name_prefix': |
|
'centos-binary-' |
|
} |
|
arglist = [] |
|
verifylist = [] |
|
|
|
mock_cip.return_value = {'container_images.yaml': {}} |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_cip.assert_called_with( |
|
excludes=[], |
|
includes=[], |
|
mapping_args={ |
|
'neutron_driver': 'ovn', |
|
'name_suffix': '', |
|
'tag': 'latest', |
|
'namespace': 'docker.io/tripleomaster', |
|
'name_prefix': |
|
'centos-binary-' |
|
}, |
|
output_env_file=None, |
|
output_images_file='container_images.yaml', |
|
push_destination=None, |
|
service_filter=None, |
|
tag_from_label=None, |
|
modify_role=None, |
|
modify_vars=None, |
|
append_tag=None, |
|
template_file=kolla_builder.DEFAULT_TEMPLATE_FILE |
|
) |
|
|
|
@mock.patch('tripleoclient.utils.fetch_roles_file') |
|
@mock.patch('tripleo_common.image.kolla_builder.' |
|
'container_images_prepare_defaults', create=True) |
|
@mock.patch('tripleo_common.image.kolla_builder.' |
|
'container_images_prepare', create=True) |
|
@mock.patch('heatclient.common.template_utils.' |
|
'process_multiple_environments_and_files') |
|
@mock.patch('tripleo_common.image.kolla_builder.' |
|
'build_service_filter') |
|
@mock.patch('requests.get') |
|
def test_container_image_prepare(self, mock_get, mock_bsf, pmef, mock_cip, |
|
mock_cipd, mock_roles): |
|
|
|
temp = tempfile.mkdtemp() |
|
self.addCleanup(shutil.rmtree, temp) |
|
images_file = os.path.join(temp, 'overcloud_containers.yaml') |
|
env_file = os.path.join(temp, 'containers_env.yaml') |
|
tmpl_file = os.path.join(temp, 'overcloud_containers.yaml.j2') |
|
aodh_file = os.path.join(temp, 'docker', 'services', 'aodh.yaml') |
|
roles_file = os.path.join(temp, 'roles_data.yaml') |
|
with open(roles_file, 'w') as f: |
|
f.write(self.roles_yaml) |
|
modify_vars_file = os.path.join(temp, 'modify_vars.yaml') |
|
with open(modify_vars_file, 'w') as f: |
|
f.write('foo: bar') |
|
mock_get.side_effect = requests.exceptions.SSLError('ouch') |
|
mock_bsf.return_value = set(['OS::TripleO::Services::AodhEvaluator']) |
|
|
|
resource_registry = { |
|
'parameter_defaults': { |
|
'NeutronMechanismDrivers': 'ovn', |
|
}, |
|
'resource_registry': { |
|
'OS::TripleO::Services::AodhEvaluator': aodh_file, |
|
'OS::TripleO::Services::AodhApi': aodh_file |
|
} |
|
} |
|
pmef.return_value = None, resource_registry |
|
|
|
arglist = [ |
|
'--template-file', |
|
tmpl_file, |
|
'--tag', |
|
'passed-ci', |
|
'--namespace', |
|
'192.0.2.0:8787/t', |
|
'--prefix', |
|
'os-', |
|
'--suffix', |
|
'foo', |
|
'--output-images-file', |
|
images_file, |
|
'--output-env-file', |
|
env_file, |
|
'--set', |
|
'ceph_namespace=myceph', |
|
'--set', |
|
'ceph_image=mydaemon', |
|
'--set', |
|
'ceph_tag=mytag', |
|
'-e', |
|
'environment/docker-ha.yaml', |
|
'--roles-file', |
|
roles_file, |
|
'--modify-role', |
|
'foo-role', |
|
'--modify-vars', |
|
modify_vars_file |
|
] |
|
self.cmd.app.command_options = arglist |
|
verifylist = [] |
|
mock_cip.return_value = {images_file: [{ |
|
'imagename': '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', |
|
}, { |
|
'imagename': '192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', |
|
}], env_file: { |
|
'DockerAodhApiImage': |
|
'192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', |
|
'DockerAodhConfigImage': |
|
'192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', |
|
'DockerAodhEvaluatorImage': |
|
'192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', |
|
'DockerInsecureRegistryAddress': ['192.0.2.0:8787'] |
|
} |
|
} |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
self.cmd.take_action(parsed_args) |
|
|
|
pmef.assert_called_once_with(['environment/docker-ha.yaml'], |
|
env_path_is_object=mock.ANY, |
|
object_request=mock.ANY) |
|
mock_cip.assert_called_once_with( |
|
excludes=[], |
|
includes=[], |
|
mapping_args={ |
|
'namespace': '192.0.2.0:8787/t', |
|
'name_suffix': 'foo', |
|
'ceph_tag': 'mytag', |
|
'ceph_image': 'mydaemon', |
|
'tag': 'passed-ci', |
|
'neutron_driver': 'ovn', |
|
'ceph_namespace': 'myceph', |
|
'name_prefix': 'os-' |
|
}, |
|
output_env_file=env_file, |
|
output_images_file=images_file, |
|
push_destination=None, |
|
service_filter=set([ |
|
'OS::TripleO::Services::AodhEvaluator', |
|
]), |
|
tag_from_label=None, |
|
modify_role='foo-role', |
|
modify_vars={'foo': 'bar'}, |
|
append_tag=mock.ANY, |
|
template_file=tmpl_file |
|
) |
|
ci_data = { |
|
'container_images': [{ |
|
'imagename': '192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', |
|
}, { |
|
'imagename': '192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', |
|
}] |
|
} |
|
env_data = { |
|
'parameter_defaults': { |
|
'DockerAodhApiImage': |
|
'192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', |
|
'DockerAodhConfigImage': |
|
'192.0.2.0:8787/t/os-aodh-apifoo:passed-ci', |
|
'DockerAodhEvaluatorImage': |
|
'192.0.2.0:8787/t/os-aodh-evaluatorfoo:passed-ci', |
|
'DockerInsecureRegistryAddress': ['192.0.2.0:8787'] |
|
} |
|
} |
|
with open(images_file) as f: |
|
self.assertEqual(ci_data, yaml.safe_load(f)) |
|
with open(env_file) as f: |
|
self.assertEqual(env_data, yaml.safe_load(f)) |
|
|
|
|
|
class TestTripleoImagePrepare(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestTripleoImagePrepare, self).setUp() |
|
# Get the command object to test |
|
self.cmd = container_image.TripleOImagePrepare(self.app, None) |
|
self.cmd.app_args = mock.Mock() |
|
self.cmd.app_args.verbose_level = 3 |
|
self.temp_dir = tempfile.mkdtemp() |
|
self.addCleanup(shutil.rmtree, self.temp_dir) |
|
self.prepare_default_file = os.path.join( |
|
self.temp_dir, 'prepare_env.yaml') |
|
default_param = kolla_builder.CONTAINER_IMAGE_PREPARE_PARAM |
|
self.default_env = { |
|
'parameter_defaults': { |
|
'ContainerImagePrepare': default_param |
|
} |
|
} |
|
with open(self.prepare_default_file, 'w') as f: |
|
yaml.safe_dump(self.default_env, f) |
|
|
|
self.roles_yaml = ''' |
|
- name: EnabledRole |
|
CountDefault: 1 |
|
ServicesDefault: |
|
- OS::TripleO::Services::AodhEvaluator |
|
- name: RoleDisabledViaRolesData |
|
CountDefault: 0 |
|
ServicesDefault: |
|
- OS::TripleO::Services::AodhApi |
|
- name: RoleDisabledViaEnvironment |
|
CountDefault: 1 |
|
ServicesDefault: |
|
- OS::TripleO::Services::Disabled |
|
- name: RoleOverwrittenViaEnvironment |
|
CountDefault: 1 |
|
ServicesDefault: |
|
- OS::TripleO::Services::Overwritten |
|
''' |
|
self.roles_data_file = os.path.join( |
|
self.temp_dir, 'roles_data.yaml') |
|
with open(self.roles_data_file, 'w') as f: |
|
f.write(self.roles_yaml) |
|
|
|
@mock.patch('tripleoclient.utils.run_ansible_playbook', |
|
autospec=True) |
|
def test_tripleo_container_image_prepare(self, mock_playbook): |
|
|
|
env_file = os.path.join(self.temp_dir, 'containers_env.yaml') |
|
|
|
arglist = [ |
|
'--environment-file', self.prepare_default_file, |
|
'--roles-file', self.roles_data_file, |
|
'--output-env-file', env_file |
|
] |
|
verifylist = [] |
|
|
|
self.app.command_options = [ |
|
'tripleo', 'container', 'image', 'prepare' |
|
] + arglist |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
self.cmd.take_action(parsed_args) |
|
e_vars = {'roles_file': self.roles_data_file, |
|
'environment_directories': [mock.ANY], |
|
'environment_files': [self.temp_dir + '/prepare_env.yaml'], |
|
'cleanup': 'full', 'dry_run': False, |
|
'log_file': 'container_image_prepare.log', 'debug': True, |
|
'output_env_file': self.temp_dir + '/containers_env.yaml'} |
|
|
|
mock_playbook.assert_called_with( |
|
extra_vars=e_vars, |
|
inventory='localhost,', |
|
playbook='cli-container-image-prepare.yaml', |
|
playbook_dir='/usr/share/ansible/tripleo-playbooks', |
|
verbosity=3, workdir=mock.ANY) |
|
|
|
@mock.patch('tripleoclient.utils.rel_or_abs_path') |
|
@mock.patch('tripleoclient.utils.run_ansible_playbook', |
|
autospec=True) |
|
def test_tripleo_container_image_prepare_paths(self, mock_playbook, |
|
mock_path): |
|
arglist = ['-e', 'foo.yaml', |
|
'-e', '/bar.yaml', |
|
'--environment-directory', 'foo', |
|
'--environment-directory', '/bar', |
|
'-r', 'foo.yaml'] |
|
verifylist = [] |
|
self.app.command_options = [ |
|
'tripleo', 'container', 'image', 'prepare' |
|
] + arglist |
|
|
|
mock_path.return_value = ('/usr/share/openstack-tripleo-heat-templates' |
|
'/foo.yaml') |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
self.cmd.take_action(parsed_args) |
|
e_vars = {'roles_file': ('/usr/share/' |
|
'openstack-tripleo-heat-templates/foo.yaml'), |
|
'environment_directories': [ |
|
os.path.expanduser(constants.DEFAULT_ENV_DIRECTORY), |
|
os.getcwd() + '/foo', |
|
'/bar' |
|
], |
|
'environment_files': [ |
|
os.getcwd() + '/foo.yaml', |
|
'/bar.yaml' |
|
], |
|
'cleanup': 'full', 'dry_run': False, |
|
'log_file': 'container_image_prepare.log', 'debug': True} |
|
|
|
mock_playbook.assert_called_with( |
|
extra_vars=e_vars, |
|
inventory='localhost,', |
|
playbook='cli-container-image-prepare.yaml', |
|
playbook_dir='/usr/share/ansible/tripleo-playbooks', |
|
verbosity=3, workdir=mock.ANY) |
|
|
|
|
|
class TestTripleoImagePrepareDefault(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestTripleoImagePrepareDefault, self).setUp() |
|
# Get the command object to test |
|
self.cmd = container_image.TripleOImagePrepareDefault(self.app, None) |
|
|
|
def test_prepare_default(self): |
|
arglist = [] |
|
verifylist = [] |
|
|
|
self.app.command_options = [ |
|
'tripleo', 'container', 'image', 'prepare', 'default' |
|
] + arglist |
|
self.cmd.app.stdout = StringIO() |
|
cmd = container_image.TripleOImagePrepareDefault(self.app, None) |
|
|
|
parsed_args = self.check_parser(cmd, arglist, verifylist) |
|
cmd.take_action(parsed_args) |
|
|
|
result = self.app.stdout.getvalue() |
|
expected_param = kolla_builder.CONTAINER_IMAGE_PREPARE_PARAM |
|
expected = { |
|
'parameter_defaults': { |
|
'ContainerImagePrepare': expected_param |
|
} |
|
} |
|
self.assertEqual(expected, yaml.safe_load(result)) |
|
|
|
def test_prepare_default_local_registry(self): |
|
temp = tempfile.mkdtemp() |
|
self.addCleanup(shutil.rmtree, temp) |
|
env_file = os.path.join(temp, 'containers_env.yaml') |
|
|
|
arglist = ['--local-push-destination', '--output-env-file', env_file] |
|
verifylist = [] |
|
|
|
self.app.command_options = [ |
|
'tripleo', 'container', 'image', 'prepare', 'default' |
|
] + arglist |
|
cmd = container_image.TripleOImagePrepareDefault(self.app, None) |
|
parsed_args = self.check_parser(cmd, arglist, verifylist) |
|
|
|
cmd.take_action(parsed_args) |
|
|
|
with open(env_file) as f: |
|
result = yaml.safe_load(f) |
|
self.assertEqual( |
|
True, |
|
result['parameter_defaults']['ContainerImagePrepare'] |
|
[0]['push_destination'] |
|
) |
|
|
|
def test_prepare_default_registyr_login(self): |
|
temp = tempfile.mkdtemp() |
|
self.addCleanup(shutil.rmtree, temp) |
|
env_file = os.path.join(temp, 'containers_env.yaml') |
|
|
|
arglist = ['--enable-registry-login', '--output-env-file', env_file] |
|
verifylist = [] |
|
|
|
self.app.command_options = [ |
|
'tripleo', 'container', 'image', 'prepare', 'default' |
|
] + arglist |
|
cmd = container_image.TripleOImagePrepareDefault(self.app, None) |
|
parsed_args = self.check_parser(cmd, arglist, verifylist) |
|
|
|
cmd.take_action(parsed_args) |
|
|
|
with open(env_file) as f: |
|
result = yaml.safe_load(f) |
|
self.assertEqual( |
|
True, |
|
result['parameter_defaults']['ContainerImageRegistryLogin'] |
|
) |
|
|
|
|
|
class TestContainerImageBuild(TestPluginV1): |
|
|
|
def setUp(self): |
|
super(TestContainerImageBuild, self).setUp() |
|
|
|
# Get the command object to test |
|
self.cmd = container_image.BuildImage(self.app, None) |
|
self.cmd.app.stdout = StringIO() |
|
self.uuid = str(uuid.uuid4()) |
|
self.temp_dir = os.path.join(self.useFixture( |
|
fixtures.TempDir()).join()) |
|
self.temp_dir_uuid = os.path.join(self.temp_dir, self.uuid) |
|
|
|
# Default conf file |
|
self.default_kolla_conf = os.path.join( |
|
sys.prefix, 'share', 'tripleo-common', 'container-images', |
|
'tripleo_kolla_config_overrides.conf') |
|
|
|
@mock.patch('sys.exit') |
|
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', |
|
autospec=True) |
|
@mock.patch('os.makedirs') |
|
def test_container_image_build_noargs(self, mock_mkdirs, mock_builder, |
|
exit_mock): |
|
arglist = [] |
|
verifylist = [] |
|
mock_builder.return_value.build_images.return_value = 'done' |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
f, path = tempfile.mkstemp(dir=self.temp_dir) |
|
with mock.patch('tempfile.mkstemp') as mock_mkstemp: |
|
mock_mkstemp.return_value = f, path |
|
self.cmd.take_action(parsed_args) |
|
|
|
# argparse will complain that --config-file is missing and exit with 2 |
|
exit_mock.assert_called_with(2) |
|
|
|
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', |
|
autospec=True) |
|
@mock.patch('uuid.uuid4') |
|
def test_container_image_build(self, mock_uuid, mock_builder): |
|
arglist = [ |
|
'--config-file', |
|
'/tmp/foo.yaml', |
|
'--config-file', |
|
'/tmp/bar.yaml', |
|
'--work-dir', |
|
self.temp_dir, |
|
'--kolla-config-file', |
|
'/tmp/kolla.conf' |
|
] |
|
verifylist = [] |
|
mock_builder.return_value.build_images.return_value = 'done' |
|
mock_uuid.return_value = self.uuid |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
f, path = tempfile.mkstemp(dir=self.temp_dir) |
|
with mock.patch('tempfile.mkstemp') as mock_mkstemp: |
|
with mock.patch('os.chdir'): |
|
mock_mkstemp.return_value = f, path |
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_builder.assert_called_once_with([ |
|
'/tmp/foo.yaml', '/tmp/bar.yaml']) |
|
mock_builder.return_value.build_images.assert_called_once_with([ |
|
self.default_kolla_conf, '/tmp/kolla.conf', |
|
path |
|
], [], False, self.temp_dir_uuid) |
|
|
|
@mock.patch('os.chdir') |
|
@mock.patch('os.fdopen', autospec=True) |
|
@mock.patch('tempfile.mkstemp') |
|
@mock.patch( |
|
'tripleoclient.utils.get_from_cfg') |
|
@mock.patch( |
|
'tripleoclient.utils.getboolean_from_cfg') |
|
@mock.patch('tripleo_common.image.builder.buildah.BuildahBuilder', |
|
autospec=True) |
|
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', |
|
autospec=True) |
|
@mock.patch('tripleoclient.utils.get_read_config') |
|
@mock.patch('os.remove') |
|
def test_container_image_build_with_buildah(self, mock_remove, |
|
mock_read_conf, |
|
mock_builder, mock_buildah, |
|
mock_kolla_boolean_cfg, |
|
mock_kolla_cfg, mock_mkstemp, |
|
mock_fdopen, mock_chdir): |
|
arglist = [ |
|
'--config-file', |
|
'/tmp/bar.yaml', |
|
'--kolla-config-file', |
|
'/tmp/kolla.conf', |
|
'--use-buildah', |
|
'--work-dir', |
|
self.temp_dir, |
|
] |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, []) |
|
deps = '{"base": ["qrouterd"]}' |
|
mock_builder.return_value.build_images.return_value = deps |
|
|
|
mock_mkstemp.return_value = (1, '/tmp/whatever_file') |
|
|
|
mock_bb = mock.MagicMock() |
|
mock_bb.build_all = mock.MagicMock() |
|
mock_buildah.return_value = mock_bb |
|
self.cmd.take_action(parsed_args) |
|
|
|
cfg_files = list(parsed_args.kolla_config_files) |
|
cfg_files.append('/tmp/whatever_file') |
|
mock_read_conf.assert_any_call(cfg_files) |
|
cfg_calls = [ |
|
mock.call(mock_read_conf.return_value, 'base'), |
|
mock.call(mock_read_conf.return_value, 'type'), |
|
mock.call(mock_read_conf.return_value, 'tag'), |
|
mock.call(mock_read_conf.return_value, 'namespace'), |
|
mock.call(mock_read_conf.return_value, 'registry'), |
|
] |
|
cfg_boolean_calls = [ |
|
mock.call(mock_read_conf.return_value, 'push'), |
|
] |
|
mock_kolla_cfg.assert_has_calls(cfg_calls) |
|
mock_kolla_boolean_cfg.assert_has_calls(cfg_boolean_calls) |
|
mock_bb.build_all.assert_called_once() |
|
|
|
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', |
|
autospec=True) |
|
@mock.patch('uuid.uuid4') |
|
def test_container_image_build_with_exclude(self, mock_uuid, mock_builder): |
|
arglist = [ |
|
'--config-file', |
|
'/tmp/foo.yaml', |
|
'--config-file', |
|
'/tmp/bar.yaml', |
|
'--kolla-config-file', |
|
'/tmp/kolla.conf', |
|
'--work-dir', |
|
'/tmp/testing', |
|
'--exclude', |
|
'foo', |
|
'--exclude', |
|
'bar' |
|
] |
|
verifylist = [] |
|
mock_builder.return_value.build_images.return_value = 'done' |
|
mock_uuid.return_value = '123' |
|
|
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist) |
|
|
|
f, path = tempfile.mkstemp(dir=self.temp_dir) |
|
with mock.patch('tempfile.mkdtemp') as mock_mkd: |
|
mock_mkd.return_value = '/tmp/testing' |
|
with mock.patch('tempfile.mkstemp') as mock_mkstemp: |
|
with mock.patch('os.chdir'): |
|
mock_mkstemp.return_value = f, path |
|
self.cmd.take_action(parsed_args) |
|
|
|
mock_builder.assert_called_once_with([ |
|
'/tmp/foo.yaml', '/tmp/bar.yaml']) |
|
mock_builder.return_value.build_images.assert_called_once_with([ |
|
self.default_kolla_conf, '/tmp/kolla.conf', |
|
path |
|
], ['foo', 'bar'], False, '/tmp/testing/123') |
|
|
|
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', |
|
autospec=True) |
|
@mock.patch('os.remove') |
|
def test_container_image_build_list_images(self, mock_remove, |
|
mock_builder): |
|
arglist = [ |
|
'--list-images', |
|
'--config-file', |
|
'/tmp/bar.yaml', |
|
'--work-dir', |
|
'/tmp/testing', |
|
'--kolla-config-file', |
|
'/tmp/kolla.conf' |
|
] |
|
parsed_args = self.check_parser(self.cmd, arglist, []) |
|
deps = '{"base": ["qrouterd"]}' |
|
mock_builder.return_value.build_images.return_value = deps |
|
|
|
f, path = tempfile.mkstemp(dir=self.temp_dir) |
|
with mock.patch('tempfile.mkstemp') as mock_mkstemp: |
|
mock_mkstemp.return_value = f, path |
|
self.cmd.take_action(parsed_args) |
|
with open(path, 'r') as conf_file: |
|
self.assertEqual( |
|
conf_file.readlines(), |
|
['[DEFAULT]\n', 'list_dependencies=true']) |
|
self.assertEqual('- base\n- qrouterd\n', |
|
self.cmd.app.stdout.getvalue()) |
|
|
|
@mock.patch('tripleo_common.image.kolla_builder.KollaImageBuilder', |
|
autospec=True) |
|
@mock.patch('os.remove') |
|
@mock.patch('os.makedirs') |
|
def test_container_image_build_list_deps(self, mock_mkdirs, mock_remove, |
|
mock_builder): |
|
arglist = [ |
|
'--config-file', |
|
'/tmp/bar.yaml', |
|
'--kolla-config-file', |
|
'/tmp/kolla.conf', |
|
'--list-dependencies', |
|
] |
|
parsed_args = self.check_parser(self.cmd, arglist, []) |
|
deps = '{"base": ["qrouterd"]}' |
|
mock_builder.return_value.build_images.return_value = deps |
|
|
|
f, path = tempfile.mkstemp(dir=self.temp_dir) |
|
with mock.patch('tempfile.mkstemp') as mock_mkstemp: |
|
mock_mkstemp.return_value = f, path |
|
self.cmd.take_action(parsed_args) |
|
with open(path, 'r') as conf_file: |
|
self.assertEqual( |
|
conf_file.readlines(), |
|
['[DEFAULT]\n', 'list_dependencies=true']) |
|
self.assertEqual('base:\n- qrouterd\n', |
|
self.cmd.app.stdout.getvalue()) |
|
|
|
def test_images_from_deps(self): |
|
deps = yaml.safe_load('''base: |
|
- qdrouterd |
|
- cron |
|
- ceph-base: |
|
- ceph-osd |
|
- ceph-rgw |
|
- ceph-mon |
|
- cephfs-fuse |
|
- ceph-mds |
|
- redis |
|
- etcd |
|
- kubernetes-entrypoint |
|
- kolla-toolbox |
|
- telegraf |
|
- openstack-base: |
|
- swift-base: |
|
- swift-proxy-server |
|
- swift-account |
|
- swift-container |
|
- swift-object-expirer |
|
- swift-rsyncd |
|
- swift-object''') |
|
|
|
images_yaml = '''- base |
|
- qdrouterd |
|
- cron |
|
- ceph-base |
|
- ceph-osd |
|
- ceph-rgw |
|
- ceph-mon |
|
- cephfs-fuse |
|
- ceph-mds |
|
- redis |
|
- etcd |
|
- kubernetes-entrypoint |
|
- kolla-toolbox |
|
- telegraf |
|
- openstack-base |
|
- swift-base |
|
- swift-proxy-server |
|
- swift-account |
|
- swift-container |
|
- swift-object-expirer |
|
- swift-rsyncd |
|
- swift-object |
|
''' |
|
images = [] |
|
self.cmd.images_from_deps(images, deps) |
|
self.assertEqual(yaml.safe_load(images_yaml), images)
|
|
|