aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiotr Milewski <vurmil@gmail.com>2025-12-23 10:30:02 +0100
committerPiotr Milewski <vurmil@gmail.com>2026-03-30 20:47:21 +0200
commitcbca935b87b4606534fc08d2cae80d864af51c7c (patch)
tree96b0b83c431fd79c14107838a0e97ff0c4dc7cd5
parent9a09f82646c577c4b484eeaac7bf56d8005da11b (diff)
downloadkolla-cbca935b87b4606534fc08d2cae80d864af51c7c.tar.gz
kolla-cbca935b87b4606534fc08d2cae80d864af51c7c.zip
Add OCI standard labels to container images
Currently, Kolla images lack standard metadata, making it difficult to identify their build source, creation time, or exact version solely by inspecting the image artifact. This patch introduces the addition of Open Container Initiative (OCI) standard labels to all generated images. The build process now detects metadata (utilizing `direct_url.json` for pip-installed packages to avoid subprocess calls) and injects the following labels into the container runtime config: * org.opencontainers.image.authors * org.opencontainers.image.created * org.opencontainers.image.description * org.opencontainers.image.licenses * org.opencontainers.image.revision * org.opencontainers.image.source * org.opencontainers.image.title * org.opencontainers.image.url * org.opencontainers.image.version Example output: "Labels": { "org.opencontainers.image.authors": "Kolla Project (https://launchpad.net/kolla)", "org.opencontainers.image.created": "2025-12-22T14:02:47.015819", "org.opencontainers.image.description": "OpenStack Kolla keystone-ssh image", "org.opencontainers.image.licenses": "Apache-2.0", "org.opencontainers.image.revision": "96b54022857ccef8dc6bb11789abe32119827109", "org.opencontainers.image.source": "https://opendev.org/openstack/kolla", "org.opencontainers.image.title": "keystone-ssh", "org.opencontainers.image.url": "https://opendev.org/openstack/kolla", "org.opencontainers.image.version": "master-ubuntu-noble" } This enhancement improves the interoperability of Kolla images with standard container tools and registries that display OCI metadata. Change-Id: I3451940c90180ba91759c839987434e94251e32e Signed-off-by: Piotr Milewski <vurmil@gmail.com>
-rw-r--r--kolla/image/kolla_worker.py74
-rw-r--r--kolla/image/tasks.py3
-rw-r--r--releasenotes/notes/add-oci-standard-labels-f68cc6eb3a4db7c7.yaml10
3 files changed, 84 insertions, 3 deletions
diff --git a/kolla/image/kolla_worker.py b/kolla/image/kolla_worker.py
index 723914f5a..680595f86 100644
--- a/kolla/image/kolla_worker.py
+++ b/kolla/image/kolla_worker.py
@@ -11,6 +11,8 @@
# limitations under the License.
import datetime
+import git
+import importlib.metadata
import json
import os
import queue
@@ -42,7 +44,7 @@ PROJECT_ROOT = os.path.abspath(os.path.join(
class Image(object):
def __init__(self, name, canonical_name, path, parent_name='',
status=Status.UNPROCESSED, parent=None,
- source=None, logger=None, engine_client=None):
+ source=None, logger=None, engine_client=None, labels=None):
self.name = name
self.canonical_name = canonical_name
self.path = path
@@ -57,11 +59,12 @@ class Image(object):
self.plugins = []
self.additions = []
self.engine_client = engine_client
+ self.labels = labels or {}
def copy(self):
c = Image(self.name, self.canonical_name, self.path,
logger=self.logger, parent_name=self.parent_name,
- status=self.status, parent=self.parent)
+ status=self.status, parent=self.parent, labels=self.labels)
if self.source:
c.source = self.source.copy()
if self.children:
@@ -143,6 +146,9 @@ class KollaWorker(object):
self.image_statuses_allowed_to_fail = dict()
self.maintainer = conf.maintainer
self.patches_path = conf.patches_path
+ self.scm_labels = self._get_scm_labels()
+ self.build_created = (datetime.datetime.now(datetime.timezone.utc)
+ .strftime('%Y-%m-%dT%H:%M:%SZ'))
try:
self.engine_client = engine.getEngineClient(self.conf)
@@ -157,6 +163,53 @@ class KollaWorker(object):
LOG.info("Exception caught: {0}".format(e))
sys.exit(1)
+ def _get_scm_labels(self):
+ labels = {}
+
+ # Method 1: Install via PIP (direct_url.json)
+ try:
+ dist = importlib.metadata.distribution('kolla')
+ direct_url_file = [
+ p for p in dist.files if p.name == 'direct_url.json'
+ ]
+
+ if direct_url_file:
+ content = dist.read_text('direct_url.json')
+ if content:
+ data = json.loads(content)
+ if 'url' in data:
+ labels['org.opencontainers.image.source'] = data['url']
+ if 'vcs_info' in data and 'commit_id' in data['vcs_info']:
+ labels['org.opencontainers.image.revision'] = (
+ data['vcs_info']['commit_id'])
+ except Exception as e:
+ LOG.debug(f"Could not retrieve PIP direct_url info: {e}")
+
+ # Method 2: Fallback to Git (if PIP info is local or missing)
+ source = labels.get('org.opencontainers.image.source', '')
+ if not labels.get('org.opencontainers.image.revision') or \
+ source.startswith('file:'):
+ try:
+ repo = git.Repo(PROJECT_ROOT, search_parent_directories=True)
+
+ labels['org.opencontainers.image.revision'] = (
+ repo.head.object.hexsha)
+
+ if source.startswith('file:') or not source:
+ labels['org.opencontainers.image.source'] = (
+ 'https://opendev.org/openstack/kolla')
+
+ LOG.debug("Detected SCM info via Git fallback: %s", labels)
+ except Exception as e:
+ LOG.debug("Git fallback failed: %s", e)
+
+ source_url = labels.get('org.opencontainers.image.source', '')
+ if source_url.startswith('file:'):
+ labels['org.opencontainers.image.source'] = (
+ 'https://opendev.org/openstack/kolla')
+
+ return labels
+
def _get_images_dir(self):
possible_paths = (
PROJECT_ROOT,
@@ -694,10 +747,25 @@ class KollaWorker(object):
else:
parent_name = ''
del match
+
+ oci_labels = self.scm_labels.copy()
+ oci_labels.update({
+ "org.opencontainers.image.title": image_name,
+ "org.opencontainers.image.description": (
+ "OpenStack Kolla {} image".format(image_name)),
+ "org.opencontainers.image.version": self.tag,
+ "org.opencontainers.image.created": self.build_created,
+ "org.opencontainers.image.authors": self.maintainer,
+ "org.opencontainers.image.url": (
+ "https://opendev.org/openstack/kolla"),
+ "org.opencontainers.image.licenses": "Apache-2.0"
+ })
+
image = Image(image_name, canonical_name, path,
parent_name=parent_name,
logger=utils.make_a_logger(self.conf, image_name),
- engine_client=self.engine_client)
+ engine_client=self.engine_client,
+ labels=oci_labels)
# NOTE(jeffrey4l): register the opts if the section didn't
# register in the kolla/common/config.py file
diff --git a/kolla/image/tasks.py b/kolla/image/tasks.py
index 39d759390..6bee905f7 100644
--- a/kolla/image/tasks.py
+++ b/kolla/image/tasks.py
@@ -407,6 +407,9 @@ class BuildTask(EngineTask):
buildargs = self.update_buildargs()
kwargs = {}
+ if hasattr(image, 'labels') and image.labels:
+ kwargs['labels'] = image.labels
+
if self.conf.engine == engine.Engine.PODMAN.value:
# TODO(kevko): dockerfile path is a workaround,
# should be removed as soon as it will be fixed in podman-py
diff --git a/releasenotes/notes/add-oci-standard-labels-f68cc6eb3a4db7c7.yaml b/releasenotes/notes/add-oci-standard-labels-f68cc6eb3a4db7c7.yaml
new file mode 100644
index 000000000..e9ba30dfb
--- /dev/null
+++ b/releasenotes/notes/add-oci-standard-labels-f68cc6eb3a4db7c7.yaml
@@ -0,0 +1,10 @@
+---
+features:
+ - |
+ Implemented support for Open Container Initiative (OCI) standard labels
+ in generated container images.
+
+ Kolla images are now tagged with standard metadata to improve traceability
+ and observability. The build process automatically detects source
+ information and populates labels such as build creation time, version,
+ source URL, and commit revision.