Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/packagedcode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from packagedcode import debian
from packagedcode import debian_copyright
from packagedcode import distro
from packagedcode import dockerfile
from packagedcode import conda
from packagedcode import conan
from packagedcode import cocoapods
Expand Down Expand Up @@ -95,6 +96,7 @@
debian.DebianSourcePackageTarballHandler,

distro.EtcOsReleaseHandler,
dockerfile.DockerfileHandler,

freebsd.CompactManifestHandler,

Expand Down
52 changes: 52 additions & 0 deletions src/packagedcode/dockerfile_ocilabels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/scancode-toolkit for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#



import io
from pathlib import Path
from dockerfile_parse import DockerfileParser
from packagedcode import models
from packagedcode import utils
from packagedcode.models import NonAssemblableDatafileHandler
import fnmatch


class DockerOCILabelsHandler(NonAssemblableDatafileHandler):
datasource_id = 'dockerfile_oci_labels'
path_patterns = ('Dockerfile', 'containerfile', '*.dockerfile')

@classmethod
def parse(cls, location, package_only=False):
"""
Parse a Dockerfile and yield one or more PackageData objects with OCI labels and metadata.
"""
labels = cls.extract_oci_labels_from_dockerfile(location)
package_data = {
'datasource_id': cls.datasource_id,
'type': cls.default_package_type,
'name': labels.get('name', 'None'),
'version': labels.get('version', 'None'),
'license_expression': labels.get('license'),
'labels': labels,
}

yield models.PackageData.from_data(package_data, package_only)

@classmethod
def extract_oci_labels_from_dockerfile(cls, dockerfile_path):
"""
Extract OCI labels from the Dockerfile using DockerfileParser.
"""
labels = {}
parser = DockerfileParser()
with open(dockerfile_path, 'r') as dockerfile:
parser.content = dockerfile.read()
labels = parser.labels
return labels
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#Copied from https://github.com/kubernetes-sigs/blixt/blob

FROM alpine

WORKDIR /opt/blixt/

LABEL org.opencontainers.image.source=https://github.com/kubernetes-sigs/blixt
LABEL org.opencontainers.image.licenses=GPL-2.0-only,BSD-2-Clause

COPY dataplane/LICENSE.GPL-2.0 /opt/blixt/LICENSE.GPL-2.0
COPY dataplane/LICENSE.BSD-2-Clause /opt/blixt/LICENSE.BSD-2-Clause
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[
{
"datasource_id": "dockerfile_oci_labels",
"type": "default",
"name": "Unknown",
"version": "Unknown",
"license_expression": "GPL-2.0-only AND BSD-2-Clause",
"labels": {
"source": "https://github.com/kubernetes-sigs/blixt",
"licenses": "GPL-2.0-only,BSD-2-Clause"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"datasource_id": "docker_oci_labels",
"labels": {
"org.opencontainers.image.source": "https://github.com/kubernetes-sigs/blixt",
"org.opencontainers.image.licenses": "GPL-2.0-only,BSD-2-Clause"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"datasource_id": "docker_oci_labels",
"labels": {
"org.opencontainers.image.source": "https://github.com/kubernetes-sigs/blixt",
"org.opencontainers.image.licenses": "GPL-2.0-only,BSD-2-Clause"
}
}
21 changes: 21 additions & 0 deletions tests/packagedcode/data/docker/test-dockerfile/test.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#Copied from https://github.com/kanboard/kanboard

FROM alpine:3.21
LABEL org.opencontainers.image.source=https://github.com/kanboard/kanboard
LABEL org.opencontainers.image.title=Kanboard
LABEL org.opencontainers.image.description="Kanboard is project management software that focuses on the Kanban methodology"
LABEL org.opencontainers.image.vendor=Kanboard
LABEL org.opencontainers.image.licenses=MIT
LABEL org.opencontainers.image.url=https://kanboard.org
LABEL org.opencontainers.image.documentation=https://docs.kanboard.org
VOLUME /var/www/app/data
VOLUME /var/www/app/plugins
VOLUME /etc/nginx/ssl
EXPOSE 80 443
ARG VERSION
RUN apk --no-cache --update add ...
ADD . /var/www/app
ADD docker/ /
RUN rm -rf /var/www/app/docker && echo $VERSION > /var/www/app/app/version.txt
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD []
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"org.opencontainers.image.source": "https://github.com/kanboard/kanboard",
"org.opencontainers.image.title": "Kanboard",
"org.opencontainers.image.description": "Kanboard is project management software that focuses on the Kanban methodology",
"org.opencontainers.image.vendor": "Kanboard",
"org.opencontainers.image.licenses": "MIT",
"org.opencontainers.image.url": "https://kanboard.org",
"org.opencontainers.image.documentation": "https://docs.kanboard.org"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"datasource_id": "docker_oci_labels",
"type": "default",
"name": "Kanboard",
"version": "1.2.42",
"license_expression": "MIT",
"labels": {
"org.opencontainers.image.source": "https://github.com/kanboard/kanboard",
"org.opencontainers.image.title": "Kanboard",
"org.opencontainers.image.description": "Kanboard is project management software that focuses on the Kanban methodology",
"org.opencontainers.image.vendor": "Kanboard",
"org.opencontainers.image.licenses": "MIT",
"org.opencontainers.image.url": "https://kanboard.org",
"org.opencontainers.image.documentation": "https://docs.kanboard.org"
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"datasource_id": "docker_oci_labels",
"type": "default",
"name": "Kanboard",
"version": "1.2.42",
"license_expression": "MIT",
"labels": {
"org.opencontainers.image.source": "https://github.com/kanboard/kanboard",
"org.opencontainers.image.title": "Kanboard",
"org.opencontainers.image.description": "Kanboard is project management software that focuses on the Kanban methodology",
"org.opencontainers.image.vendor": "Kanboard",
"org.opencontainers.image.licenses": "MIT",
"org.opencontainers.image.url": "https://kanboard.org",
"org.opencontainers.image.documentation": "https://docs.kanboard.org"
}
}
]
66 changes: 66 additions & 0 deletions tests/packagedcode/test_dockerfile_ocilabels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/scancode-toolkit for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#

import pytest
import json
from commoncode.testcase import FileDrivenTesting
from scancode.cli_test_utils import run_scan_click
from packagedcode.models import DockerOCILabelsHandler

class TestDockerOCILabelsHandler(FileDrivenTesting):

@pytest.mark.parametrize('test_file, expected', [
('docker/test.dockerfile', True),
('docker/test.containerfile', True),
])
def test_is_datafile(self, test_file, expected):
test_file_path = self.get_test_loc(test_file)
assert DockerOCILabelsHandler.is_datafile(test_file_path) == expected

def test_parse_dockerfile(self):
test_files = [
('test.dockerfile', 'test.dockerfile-package.expected.json'),
('test.containerfile', 'test.containerfile-package.expected.json'),
]
for dockerfile, expected in test_files:
test_file = self.get_test_loc(f'docker/{dockerfile}')
expected_loc = self.get_test_loc(f'docker/{expected}')
packages = list(DockerOCILabelsHandler.parse(test_file))
expected_packages = self.load_expected(expected_loc)
assert packages == expected_packages

def test_extract_oci_labels_from_dockerfile(self):
test_files = [
('test.dockerfile', 'test.dockerfile-expected.json'),
('test.containerfile', 'test.containerfile-expected.json'),
]
for dockerfile, expected in test_files:
dockerfile_path = self.get_test_loc(f'docker/{dockerfile}')
labels = DockerOCILabelsHandler.extract_oci_labels_from_dockerfile(dockerfile_path)
expected_loc = self.get_test_loc(f'docker/{expected}')
expected_labels = self.load_expected(expected_loc)
assert labels == expected_labels

def test_full_scan_docker_oci_labels_containerfile(self):
test_file = self.get_test_loc('docker/test.containerfile')
result_file = self.get_temp_file('json')
run_scan_click(['--package', test_file, '--json-pp', result_file])
result = json.load(open(result_file))
package_data = result.get('package_data', [])
assert len(package_data) == 1
package = package_data[0]
assert package['datasource_id'] == 'docker_oci_labels'
assert package['labels'] == {
'org.opencontainers.image.source': 'https://github.com/kubernetes-sigs/blixt',
'org.opencontainers.image.licenses': 'GPL-2.0-only,BSD-2-Clause'
}

def load_expected(self, expected_file):
with open(expected_file) as f:
return json.load(f)
Loading