rules_docker icon indicating copy to clipboard operation
rules_docker copied to clipboard

Different 'base' argument type excepted between the container_image rule and its implementation function

Open lbcjbb opened this issue 3 years ago • 0 comments

🐞 bug report

Affected Rule

The only rule affected is the container_image rule, and more specifically its implementation function _impl().

Is this a regression?

No.

Description

Depending if the base argument is directly given to the implementation function, or if this argument is given through the attribute of the rule ctx.attr.base, the process of this argument is different.

This difference of behaviour is introduced in the get_from_target() function in the file container/layer_tools.bzl.

def get_from_target(ctx, name, attr_target, file_target = None):
    """Gets all layers from the given target.

    Args:
       ctx: The context
       name: The name of the target
       attr_target: The attribute to get layers from
       file_target: If not None, layers are extracted from this target

    Returns:
       The extracted layers
    """
    if file_target:
        return _extract_layers(ctx, name, file_target)
    elif attr_target and ImageInfo in attr_target:
        return attr_target[ImageInfo].container_parts
    elif attr_target and ImportInfo in attr_target:
        return attr_target[ImportInfo].container_parts
    else:
        if not hasattr(attr_target, "files"):
            return {}
        target = attr_target.files.to_list()[0]
        return _extract_layers(ctx, name, target)

Where we give the value of ctx.attr.base to attr_target, and the value of the base argument to file_target. On the one hand we call _extract_layers() with an argument of type File, and on the other hand we call directly this function with an argument of type Target.

🔬 Minimal Reproduction

load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("@io_bazel_rules_docker//container:container.bzl", _container = "container")
load("//skylib:filetype.bzl", container_filetype = "container")

def _my_container_image_impl(ctx):
    return _container.image.implementation(ctx, base = ctx.attr.mybase)

my_container_image = rule(
    implementation = _my_container_image_impl,
    attrs = dicts.add(_container.image.attrs, {
        "mybase": attr.label(allow_files = container_filetype), // Same definition of the 'base' attribute.
    },
    outputs = _container.image.outputs,
    cfg = _container.image.cfg,
    toolchains = [
        "@io_bazel_rules_docker//toolchains/docker:toolchain_type",
    ],
)

🔥 Exception or Error

Traceback (most recent call last):
...
File ".../io_bazel_rules_docker/container/image.bzl", line 429, column 31, in _impl
	parent_parts = _get_layers(ctx, name, ctx.attr.base, base)
File ".../io_bazel_rules_docker/container/layer_tools.bzl", line 119, column 31, in get_from_target
	return _extract_layers(ctx, name, file_target)
File ".../io_bazel_rules_docker/container/layer_tools.bzl", line 31, column 65, in _extract_layers
	config_file = ctx.actions.declare_file(name + "." + artifact.basename + ".config")
Error: <target @debian_image_base_amd64//image:image> (rule 'container_import') doesn't have provider 'basename'

🌍 Your Environment

Operating System:

linux / amd64

Output of bazel version:

4.2.2 / 5.0.0 / 5.1.1

Rules_docker version:

v0.23.0 / v0.24.0 / master (0768e1b7f6aa973f9879ac5b8f622dd2f3d88f1d)

lbcjbb avatar May 08 '22 21:05 lbcjbb