aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xkolla/cmd/build.py4
-rwxr-xr-xkolla/common/config.py4
-rwxr-xr-xkolla/image/build.py34
-rw-r--r--kolla/tests/test_build.py14
-rw-r--r--releasenotes/notes/allowed-to-fail-e2ff5bf61c857b55.yaml9
5 files changed, 47 insertions, 18 deletions
diff --git a/kolla/cmd/build.py b/kolla/cmd/build.py
index 67a350415..e7b2cd76d 100755
--- a/kolla/cmd/build.py
+++ b/kolla/cmd/build.py
@@ -32,8 +32,8 @@ def main():
try:
statuses = build.run_build()
if statuses:
- (bad_results, good_results, unmatched_results,
- skipped_results, unbuildable_results) = statuses
+ (bad_results, good_results, unmatched_results, skipped_results,
+ unbuildable_results, allowed_to_fail_results) = statuses
if bad_results:
return 1
return 0
diff --git a/kolla/common/config.py b/kolla/common/config.py
index c3e8f9801..b87a70eb0 100755
--- a/kolla/common/config.py
+++ b/kolla/common/config.py
@@ -273,7 +273,9 @@ _BASE_OPTS = [
cfg.StrOpt('squash-tmp-dir',
help='Temporary directory to be used during squashing'),
cfg.BoolOpt('clean_package_cache', default=True,
- help='Clean all package cache.')
+ help='Clean all package cache.'),
+ cfg.ListOpt('allowed-to-fail', default=[],
+ help='Images which are allowed to fail'),
]
diff --git a/kolla/image/build.py b/kolla/image/build.py
index 62db92ebf..d5b058419 100755
--- a/kolla/image/build.py
+++ b/kolla/image/build.py
@@ -759,6 +759,7 @@ class KollaWorker(object):
self.image_statuses_unmatched = dict()
self.image_statuses_skipped = dict()
self.image_statuses_unbuildable = dict()
+ self.image_statuses_allowed_to_fail = dict()
self.maintainer = conf.maintainer
self.distro_python_version = conf.distro_python_version
@@ -1153,12 +1154,19 @@ class KollaWorker(object):
'name': name,
})
- if self.image_statuses_bad:
+ if self.image_statuses_bad or self.image_statuses_allowed_to_fail:
LOG.info("===========================")
LOG.info("Images that failed to build")
LOG.info("===========================")
- for name, status in sorted(self.image_statuses_bad.items()):
- LOG.error('%s Failed with status: %s', name, status.value)
+ all_bad_statuses = self.image_statuses_bad.copy()
+ all_bad_statuses.update(self.image_statuses_allowed_to_fail)
+ for name, status in sorted(all_bad_statuses.items()):
+ if name in self.image_statuses_allowed_to_fail:
+ LOG.error('%s Failed with status: %s (allowed to fail)',
+ name, status.value)
+ else:
+ LOG.error('%s Failed with status: %s', name, status.value)
+
results['failed'].append({
'name': name,
'status': status.value,
@@ -1211,12 +1219,14 @@ class KollaWorker(object):
self.image_statuses_good,
self.image_statuses_unmatched,
self.image_statuses_skipped,
- self.image_statuses_unbuildable]):
+ self.image_statuses_unbuildable,
+ self.image_statuses_allowed_to_fail]):
return (self.image_statuses_bad,
self.image_statuses_good,
self.image_statuses_unmatched,
self.image_statuses_skipped,
- self.image_statuses_unbuildable)
+ self.image_statuses_unbuildable,
+ self.image_statuses_allowed_to_fail)
for image in self.images:
if image.status == Status.BUILT:
self.image_statuses_good[image.name] = image.status
@@ -1227,12 +1237,17 @@ class KollaWorker(object):
elif image.status == Status.UNBUILDABLE:
self.image_statuses_unbuildable[image.name] = image.status
else:
- self.image_statuses_bad[image.name] = image.status
+ if image.name in self.conf.allowed_to_fail:
+ self.image_statuses_allowed_to_fail[
+ image.name] = image.status
+ else:
+ self.image_statuses_bad[image.name] = image.status
return (self.image_statuses_bad,
self.image_statuses_good,
self.image_statuses_unmatched,
self.image_statuses_skipped,
- self.image_statuses_unbuildable)
+ self.image_statuses_unbuildable,
+ self.image_statuses_allowed_to_fail)
def build_image_list(self):
def process_source_installation(image, section):
@@ -1403,8 +1418,9 @@ class KollaWorker(object):
def run_build():
"""Build container images.
- :return: A 4-tuple containing bad, good, unmatched and skipped container
- image status dicts, or None if no images were built.
+ :return: A 6-tuple containing bad, good, unmatched, skipped,
+ unbuildable and allowed to fail container image status dicts,
+ or None if no images were built.
"""
conf = cfg.ConfigOpts()
common_config.parse(conf, sys.argv[1:], prog='kolla-build')
diff --git a/kolla/tests/test_build.py b/kolla/tests/test_build.py
index 00bdd6d32..8dd34f2fd 100644
--- a/kolla/tests/test_build.py
+++ b/kolla/tests/test_build.py
@@ -648,9 +648,11 @@ class KollaWorkerTest(base.TestCase):
kolla.images = self.images
kolla.image_statuses_good['good'] = build.Status.BUILT
kolla.image_statuses_bad['bad'] = build.Status.ERROR
+ kolla.image_statuses_allowed_to_fail['bad2'] = build.Status.ERROR
kolla.image_statuses_unmatched['unmatched'] = build.Status.UNMATCHED
results = kolla.summary()
- self.assertEqual('error', results['failed'][0]['status'])
+ self.assertEqual('error', results['failed'][0]['status']) # bad
+ self.assertEqual('error', results['failed'][1]['status']) # bad2
@mock.patch('shutil.copytree')
def test_work_dir(self, copytree_mock):
@@ -664,14 +666,14 @@ class MainTest(base.TestCase):
@mock.patch.object(build, 'run_build')
def test_images_built(self, mock_run_build):
- image_statuses = ({}, {'img': 'built'}, {}, {}, {})
+ image_statuses = ({}, {'img': 'built'}, {}, {}, {}, {})
mock_run_build.return_value = image_statuses
result = build_cmd.main()
self.assertEqual(0, result)
@mock.patch.object(build, 'run_build')
def test_images_unmatched(self, mock_run_build):
- image_statuses = ({}, {}, {'img': 'unmatched'}, {}, {})
+ image_statuses = ({}, {}, {'img': 'unmatched'}, {}, {}, {})
mock_run_build.return_value = image_statuses
result = build_cmd.main()
self.assertEqual(0, result)
@@ -684,7 +686,7 @@ class MainTest(base.TestCase):
@mock.patch.object(build, 'run_build')
def test_bad_images(self, mock_run_build):
- image_statuses = ({'img': 'error'}, {}, {}, {}, {})
+ image_statuses = ({'img': 'error'}, {}, {}, {}, {}, {})
mock_run_build.return_value = image_statuses
result = build_cmd.main()
self.assertEqual(1, result)
@@ -697,14 +699,14 @@ class MainTest(base.TestCase):
@mock.patch.object(build, 'run_build')
def test_skipped_images(self, mock_run_build):
- image_statuses = ({}, {}, {}, {'img': 'skipped'}, {})
+ image_statuses = ({}, {}, {}, {'img': 'skipped'}, {}, {})
mock_run_build.return_value = image_statuses
result = build_cmd.main()
self.assertEqual(0, result)
@mock.patch.object(build, 'run_build')
def test_unbuildable_images(self, mock_run_build):
- image_statuses = ({}, {}, {}, {}, {'img': 'unbuildable'})
+ image_statuses = ({}, {}, {}, {}, {'img': 'unbuildable'}, {})
mock_run_build.return_value = image_statuses
result = build_cmd.main()
self.assertEqual(0, result)
diff --git a/releasenotes/notes/allowed-to-fail-e2ff5bf61c857b55.yaml b/releasenotes/notes/allowed-to-fail-e2ff5bf61c857b55.yaml
new file mode 100644
index 000000000..595c97b18
--- /dev/null
+++ b/releasenotes/notes/allowed-to-fail-e2ff5bf61c857b55.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ New option 'allowed-to-fail' can be used in Kolla build config files. It
+ provides list of images which are allowed to fail during build without
+ marking whole build as failed.
+
+ Main use of this option is to keep CI systems in working state despite some
+ less important images failing.