Library wrapper around kolla-build tool

This adds a python library which allows container images to be created
using the kolla-build tool. The yaml format used by
contrib/overcloud_containers.yaml is used to specify which images to
build.

It is also possible to specify the path to kolla conf files.
Every kolla option can be set by a conf file, so this is sufficient to
modify kolla-build behaviour.

The namespace and the tag in overcloud_containers.yaml is ignored
since this is driven by the kolla configuration.

The image prefixes like 'centos-binary-' are removed before passing
the remaining image name to kolla as a regex match.

This will be used by the new command "overcloud container image build"

Change-Id: I061f626fdb3d71613aa23436bf6c53cf4de62213
This commit is contained in:
Steve Baker 2017-03-22 10:48:05 +13:00
parent 75754c4658
commit b04c4d90cd
2 changed files with 183 additions and 0 deletions

View File

@ -0,0 +1,76 @@
# Copyright 2017 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 logging
import os
import re
import subprocess
import sys
from tripleo_common.image import base
if sys.version_info[0] < 3:
import codecs
_open = open
open = codecs.open
class KollaImageBuilder(base.BaseImageManager):
"""Build images using kolla-build"""
logger = logging.getLogger(__name__ + '.KollaImageBuilder')
handler = logging.StreamHandler(sys.stdout)
@staticmethod
def imagename_to_regex(imagename):
if not imagename:
return
# remove any namespace from the start
imagename = imagename.split('/')[-1]
# remove any tag from the end
imagename = imagename.split(':')[0]
# remove supported base names from the start
imagename = re.sub(r'^(centos|rhel)-', '', imagename)
# remove install_type from the start
imagename = re.sub(r'^(binary|source|rdo|rhos)-', '', imagename)
# what results should be acceptable as a regex to build one image
return imagename
def build_images(self, kolla_config_files=None):
cmd = ['kolla-build']
if kolla_config_files:
for f in kolla_config_files:
cmd.append('--config-file')
cmd.append(f)
container_images = self.load_config_files(self.CONTAINER_IMAGES) or []
container_images.sort(key=lambda i: i.get('imagename'))
for i in container_images:
image = self.imagename_to_regex(i.get('imagename'))
if image:
cmd.append(image)
self.logger.info('Running %s' % ' '.join(cmd))
env = os.environ.copy()
process = subprocess.Popen(cmd, env=env)
process.wait()
if process.returncode != 0:
raise subprocess.CalledProcessError(process.returncode, cmd)

View File

@ -0,0 +1,107 @@
# Copyright 2017 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 mock
import os
import six
import subprocess
from tripleo_common.image import kolla_builder as kb
from tripleo_common.tests import base
filedata = six.u(
"""container_images:
- imagename: tripleoupstream/heat-docker-agents-centos:latest
push_destination: localhost:8787
- imagename: tripleoupstream/centos-binary-nova-compute:liberty
uploader: docker
pull_source: docker.io
push_destination: localhost:8787
- imagename: tripleoupstream/centos-binary-nova-libvirt:liberty
uploader: docker
pull_source: docker.io
""")
class TestKollaImageBuilder(base.TestCase):
def setUp(self):
super(TestKollaImageBuilder, self).setUp()
files = []
files.append('testfile')
self.filelist = files
def test_imagename_to_regex(self):
itr = kb.KollaImageBuilder.imagename_to_regex
self.assertIsNone(itr(''))
self.assertIsNone(itr(None))
self.assertEqual('foo', itr('foo'))
self.assertEqual('foo', itr('foo:latest'))
self.assertEqual('foo', itr('tripleo/foo:latest'))
self.assertEqual('foo', itr('tripleo/foo'))
self.assertEqual('foo', itr('tripleo/centos-binary-foo:latest'))
self.assertEqual('foo', itr('centos-binary-foo:latest'))
self.assertEqual('foo', itr('centos-binary-foo'))
@mock.patch('tripleo_common.image.base.open',
mock.mock_open(read_data=filedata), create=True)
@mock.patch('os.path.isfile', return_value=True)
@mock.patch('subprocess.Popen')
def test_build_images(self, mock_popen, mock_path):
process = mock.Mock()
process.returncode = 0
mock_popen.return_value = process
builder = kb.KollaImageBuilder(self.filelist)
builder.build_images(['kolla-config.conf'])
env = os.environ.copy()
mock_popen.assert_called_once_with([
'kolla-build',
'--config-file',
'kolla-config.conf',
'nova-compute',
'nova-libvirt',
'heat-docker-agents-centos',
], env=env)
@mock.patch('subprocess.Popen')
def test_build_images_no_conf(self, mock_popen):
process = mock.Mock()
process.returncode = 0
mock_popen.return_value = process
builder = kb.KollaImageBuilder([])
builder.build_images([])
env = os.environ.copy()
mock_popen.assert_called_once_with([
'kolla-build',
], env=env)
@mock.patch('subprocess.Popen')
def test_build_images_fail(self, mock_popen):
process = mock.Mock()
process.returncode = 1
mock_popen.return_value = process
builder = kb.KollaImageBuilder([])
self.assertRaises(subprocess.CalledProcessError,
builder.build_images,
[])
env = os.environ.copy()
mock_popen.assert_called_once_with([
'kolla-build',
], env=env)