buildpacks / lifecycle

Reference implementation of the Cloud Native Buildpacks lifecycle
https://buildpacks.io
Apache License 2.0
185 stars 103 forks source link

`[[targets.distros]]` in `buildpack.toml` is ignored if the run image distro name/version isn't available #1337

Closed edmorley closed 2 months ago

edmorley commented 2 months ago

Summary

The Buildpack API 0.10 spec says:

Metadata specified in [[targets]] is validated against the runtime and build-time base images.

  • A buildpack target satisfies a base image target when os, arch, and variant match and at least one distribution in distros (if provided) matches

(https://github.com/buildpacks/spec/blob/buildpack/v0.10/buildpack.md#targets)

As such, if a buildpack's buildpack.toml contains:

[[targets]]
os = "linux"
arch = "amd64"

[[targets.distros]]
name = "ubuntu"
version = "123"

...then I would expect the buildpack to only pass detection if the run image's distro name was "ubuntu" and version was "123".

However, it seems that if the distro name/version could not be determined by lifecycle (for example, the run image doesn't have the io.buildpacks.base.distro.* Docker labels set and the /etc/os-release fallback isn't available or is broken), then lifecycle ignores the [[targets.distros]] requirements and instead matches against any distro.

The cause of this appears to be the base.Distro == nil part of this conditional: https://github.com/buildpacks/lifecycle/blob/435d226f1ed54b0bec806716ba79e14a2a093736/platform/target_data.go#L94-L96


Reproduction

Steps
  1. pack buildpack new testcase-buildpack-targets --api 0.10 --targets "linux/amd64"
  2. echo -e '\n[[targets.distros]]\nname = "ubuntu"\nversion = "123"' >> testcase-buildpack-targets/buildpack.toml
  3. pack build --builder heroku/builder:22 --run-image heroku/heroku:22-cnb.v122 --buildpack testcase-buildpack-targets/ --path testcase-buildpack-targets/ testapp --verbose
Current behavior

Buildpack detection unexpectedly passes:

$ pack build --builder heroku/builder:22 --run-image heroku/heroku:22-cnb.v122 --buildpack testcase-buildpack-targets/ --path testcase-buildpack-targets/ testapp --verbose
...
===> ANALYZING
...
Run image info in analyzed metadata is: 
{"Reference":"6d5f868e91eba6a6ec22a9a9b9b31a2fd486a0f0f57082fd0864e0bf0b3e4395","Image":"heroku/heroku:22-cnb.v122","Extend":false,"target":{"os":"linux","arch":"amd64"}}
===> DETECTING
...
Checking for match against descriptor: {linux amd64  [{ubuntu 123}]}
======== Results ========
pass: testcase-buildpack-targets@1.0.0

...even though the buildpack declares that it only supports:

[[targets.distros]]
name = "ubuntu"
version = "123"

...and the run image's Ubuntu version is not "123".

Expected behavior

I would expect buildpack detection to fail, like how it fails if I use a newer version of our run image (by omitting the --run-image heroku/heroku:22-cnb.v122 argument) that has the relevant io.buildpacks.base.distro.* Docker labels set:

$ pack build --builder heroku/builder:22 --buildpack testcase-buildpack-targets/ --path testcase-b
uildpack-targets/ testapp --verbose
...
===> ANALYZING
...
Run image info in analyzed metadata is: 
{"Reference":"9e85c0884ff5a53485a1f53e4c3f958811ea755ddb24885e55b2bcdec2ddf7f1","Image":"heroku/heroku:22-cnb","Extend":false,"target":{"os":"linux","arch":"amd64","distro":{"name":"ubuntu","version":"22.04"}}}
===> DETECTING
...
Checking for match against descriptor: {linux amd64  [{ubuntu 123}]}
======== Error: testcase-buildpack-targets@1.0.0 ========
unable to satisfy target os/arch constraints; run image: {"os":"linux","arch":"amd64","distro":{"name":"ubuntu","version":"22.04"}}, buildpack: [{"os":"linux","arch":"amd64","distros":[{"name":"ubuntu","version":"123"}]}]
======== Results ========
err:  testcase-buildpack-targets@1.0.0

Context

lifecycle version

0.19.3

platform version(s)
$ pack report
Pack:
  Version:  0.33.2+git-f2cffc4.build-5562
  OS/Arch:  darwin/arm64

The build is using Platform API 0.12 and Buildpack API 0.10.

natalieparellano commented 2 months ago

@edmorley if we fix https://github.com/buildpacks/lifecycle/issues/1336 should we not expect that the base distro is never (or rarely) nil? (I am not sure that we want to fail for mismatched distros if one isn't specified)

edmorley commented 2 months ago

@natalieparellano Yeah once #1336 is fixed this issue should only affect:

  1. Windows
  2. Linux distros that don't ship with systemd (and don't otherwise add their own version of the file) - xref: https://unix.stackexchange.com/questions/351557/on-what-linux-distributions-can-i-rely-on-the-presence-of-etc-os-release
edmorley commented 2 months ago

(I am not sure that we want to fail for mismatched distros if one isn't specified)

So I think if the buildpack says "I'm only supported on X", then lifecycle shouldn't guess and pass detection if it can't figure out the distro name/version.

Ultimately if the buildpack author wanted to match against anything, then it feels like they should/would omit the distro name/version?