diff --git a/colin/checks/labels.py b/colin/checks/labels.py index 1075699e..a0d5c4c1 100644 --- a/colin/checks/labels.py +++ b/colin/checks/labels.py @@ -14,6 +14,7 @@ # along with this program. If not, see . # +from colin.core.checks.abstract_check import ImageDockerfileAbstractCheck from colin.core.checks.labels import LabelAbstractCheck from colin.core.checks.fmf_check import FMFAbstractCheck @@ -106,3 +107,10 @@ class VendorLabelCheck(FMFAbstractCheck, LabelAbstractCheck): class VersionLabelCheck(FMFAbstractCheck, LabelAbstractCheck): name = "version_label" + + +class InheritedOptionalLabelCheck(ImageDockerfileAbstractCheck): + name = "inherited_labels" + # TODO: Compare image labels and labels declared in Dockerfile + # to compute inherited labels; filter by labels which are optional; + # the remaining set should be empty. diff --git a/colin/cli/colin.py b/colin/cli/colin.py index 1f181070..69154724 100644 --- a/colin/cli/colin.py +++ b/colin/cli/colin.py @@ -50,6 +50,9 @@ def cli(): @click.command(name="check", context_settings=CONTEXT_SETTINGS) @click.argument('target', type=click.STRING) +@click.option('--supplementary-target', type=click.STRING, + help="Additional target. For image+dockerfile target type " + "this is the Dockerfile.") @click.option('--ruleset', '-r', type=click.STRING, envvar='COLIN_RULESET', help="Select a predefined ruleset (e.g. fedora).") @click.option('--ruleset-file', '-f', type=click.File(mode='r'), @@ -75,13 +78,15 @@ def cli(): help="Pull the image from registry.") @click.option('--target-type', type=click.STRING, default="image", help="Type of selected target (one of image, dockerfile, " - "ostree). For ostree, please specify image name and path like this: image@path") + "image+dockerflie, ostree). For ostree, please specify " + "image name and path like this: image@path") @click.option('--timeout', type=click.INT, help="Timeout for each check in seconds. (default=600)") @click.option('--insecure', is_flag=True, default=False, help="Pull from an insecure registry (HTTP or invalid TLS).") -def check(target, ruleset, ruleset_file, debug, json, stat, skip, tag, verbose, - checks_paths, target_type, timeout, pull, insecure): +def check(target, supplementary_target, ruleset, ruleset_file, debug, json, + stat, skip, tag, verbose, checks_paths, target_type, timeout, pull, + insecure): """ Check the image/dockerfile (default). """ @@ -101,6 +106,7 @@ def check(target, ruleset, ruleset_file, debug, json, stat, skip, tag, verbose, verbose=verbose) results = run( target=target, + supplementary_target=supplementary_target, ruleset_name=ruleset, ruleset_file=ruleset_file, logging_level=log_level, diff --git a/colin/core/checks/abstract_check.py b/colin/core/checks/abstract_check.py index 05a6d435..d489d7ae 100644 --- a/colin/core/checks/abstract_check.py +++ b/colin/core/checks/abstract_check.py @@ -85,5 +85,10 @@ class ImageAbstractCheck(AbstractCheck): check_type = "image" +class ImageDockerfileAbstractCheck(DockerfileAbstractCheck, + ImageAbstractCheck): + check_type = "image+dockerfile" + + class FilesystemAbstractCheck(AbstractCheck): pass diff --git a/colin/core/colin.py b/colin/core/colin.py index f57b0333..86f3de5f 100644 --- a/colin/core/colin.py +++ b/colin/core/colin.py @@ -36,6 +36,7 @@ def run( insecure=False, skips=None, timeout=None, + supplementary_target=None, ): """ Runs the sanity checks for the target. @@ -54,12 +55,14 @@ def run( :param checks_paths: list of str, directories where the checks are present :param pull: bool, pull the image from registry :param insecure: bool, pull from an insecure registry (HTTP/invalid TLS) + :param supplementary_target: str, additional target (for image+dockerfile) :return: Results instance """ _set_logging(level=logging_level) logger.debug("Checking started.") target = Target.get_instance( target=target, + supplementary_target=supplementary_target, logging_level=logging_level, pull=pull, target_type=target_type, diff --git a/colin/core/target.py b/colin/core/target.py index 923fbea7..956ac35f 100644 --- a/colin/core/target.py +++ b/colin/core/target.py @@ -24,7 +24,9 @@ from dockerfile_parse import DockerfileParser -from .checks.abstract_check import ImageAbstractCheck, DockerfileAbstractCheck +from .checks.abstract_check import (ImageAbstractCheck, + DockerfileAbstractCheck, + ImageDockerfileAbstractCheck) from ..core.exceptions import ColinException from ..utils.cont import ImageName @@ -313,6 +315,24 @@ def get_output(self, cmd): raise NotImplementedError("Unsupported right now.") +class ImageWithDockerfileTarget(ImageTarget, DockerfileTarget): + """ + Represents the podman image, along with the Dockerfile it was + built from, as a target. + """ + target_type = "image+dockerfile" + + def __init__(self, target, pull, supplementary_target, insecure=False, + **kwargs): + super(ImageTarget, self).__init__(target, pull, insecure=insecure, + **kwargs) + super(DockerfileTarget, self).__init__(supplementary_target) + + @classmethod + def get_compatible_check_class(cls): + return ImageDockerfileAbstractCheck + + class OstreeTarget(AbstractImageTarget): """ Represents the ostree repository as an image target. @@ -430,5 +450,6 @@ def get_output(self, cmd): TARGET_TYPES = { "image": ImageTarget, "dockerfile": DockerfileTarget, + "image+dockerfile": ImageWithDockerfileTarget, "ostree": OstreeTarget }