Skip to content

Commit

Permalink
apko_tags: handle provides better (#293)
Browse files Browse the repository at this point in the history
Today sometimes configs request some package, say, `nodejs`, which gets
provided by a package named `nodejs-21`. When it comes time to get the
tags for this config, we can't pass `nodejs` today because the resulting
config has no package with that name. And callers don't necessarily know
it's called `nodejs-21`, or else they would have requested that.

This makes `apko_tags` aware of this scenario and slightly less dumb,
and if it can't find a package named `nodejs`, will look for a package
named `nodejs-*` and assume that's the desired package.

---------

Signed-off-by: Jason Hall <jason@chainguard.dev>
Signed-off-by: James Petersen <jpetersenames@gmail.com>
Co-authored-by: James Petersen <jpetersenames@gmail.com>
  • Loading branch information
imjasonh and found-it committed May 3, 2024
1 parent 28623de commit fbb2c09
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 10 deletions.
44 changes: 34 additions & 10 deletions internal/provider/tags_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,46 @@ func (d *TagsDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
return
}

found := false
pkgs := map[string]string{}
var found string
for _, pkg := range ic.Contents.Packages {
if strings.HasPrefix(pkg, data.TargetPackage.ValueString()+"=") {
fullVersion := strings.TrimPrefix(pkg, data.TargetPackage.ValueString()+"=")
data.Tags = getStemmedVersionTags(fullVersion)
data.Tags = append(data.Tags, fullVersion)
sort.Strings(data.Tags)
found = true
break
pkg, version, ok := strings.Cut(pkg, "=")
if !ok {
resp.Diagnostics.AddError("Invalid package", fmt.Sprintf("Invalid package: %s", pkg))
return
}
pkgs[pkg] = version
}
if !found {
resp.Diagnostics.AddError(fmt.Sprintf("Unable to find package: %s...", data.TargetPackage.ValueString()), fmt.Sprintf("...in package list:\n\t%s", strings.Join(ic.Contents.Packages, "\n\t")))
if _, ok := pkgs[data.TargetPackage.ValueString()]; ok {
found = data.TargetPackage.ValueString()
} else {
var foundver string
for pkg, ver := range pkgs {
// If the package name didn't match exactly, see if we have a package that starts with the target package name.
// This is to handle the common case where a package named "foo" might be provided by a package named "foo-1.23".
// In case there are multiple packages that match that provide different versions, we'll error out.
if strings.HasPrefix(pkg, data.TargetPackage.ValueString()+"-") {
if found != "" && foundver != ver {
resp.Diagnostics.AddError("Multiple packages match", fmt.Sprintf("Multiple packages match with different versions: %s (%s) and %s (%s)", found, foundver, pkg, ver))
return
}

found = pkg
foundver = ver
// Don't stop; keep looking in case there are multiple matches!
}
}
}

if found == "" {
resp.Diagnostics.AddError(fmt.Sprintf("Unable to find package: %s...", data.TargetPackage.ValueString()), fmt.Sprintf("...in package list:\n\t%s", strings.Join(ic.Contents.Packages, "\n\t")))
return
}

data.Tags = getStemmedVersionTags(pkgs[found])
data.Tags = append(data.Tags, pkgs[found])
sort.Strings(data.Tags)

data.Id = types.StringValue(strings.Join(data.Tags, ","))

tflog.Trace(ctx, "read a data source")
Expand Down
28 changes: 28 additions & 0 deletions internal/provider/tags_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ contents:
- ca-certificates-bundle=20230506-r0
- glibc-locale-posix=2.37-r6
- ko=0.13.0-r3
- nodejs=21.7.3-r1 # Initial request will be satisfied by 'provides'
EOF
extra_packages = ["tzdata=2023c-r0"]
}
Expand Down Expand Up @@ -56,6 +57,16 @@ data "apko_tags" "ko" {
config = data.apko_config.this.config
target_package = "ko"
}
data "apko_tags" "nodejs" {
config = data.apko_config.this.config
target_package = "nodejs" # Tags can be inferred from 'provides'
}
data "apko_tags" "nodejs-21" {
config = data.apko_config.this.config
target_package = "nodejs-21"
}
`,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.apko_tags.glibc", "tags.#", "3"),
Expand Down Expand Up @@ -85,6 +96,22 @@ data "apko_tags" "ko" {
resource.TestCheckResourceAttr("data.apko_tags.ko", "tags.2", "0.13.0"),
resource.TestCheckResourceAttr("data.apko_tags.ko", "tags.3", "0.13.0-r3"),
resource.TestCheckResourceAttr("data.apko_tags.ko", "id", "0,0.13,0.13.0,0.13.0-r3"),

resource.TestCheckResourceAttr("data.apko_tags.nodejs", "tags.#", "4"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs", "tags.0", "21"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs", "tags.1", "21.7"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs", "tags.2", "21.7.3"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs", "tags.3", "21.7.3-r1"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs", "id", "21,21.7,21.7.3,21.7.3-r1"),

resource.TestCheckResourceAttr("data.apko_tags.nodejs-21", "tags.#", "4"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs-21", "tags.0", "21"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs-21", "tags.1", "21.7"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs-21", "tags.2", "21.7.3"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs-21", "tags.3", "21.7.3-r1"),
resource.TestCheckResourceAttr("data.apko_tags.nodejs-21", "id", "21,21.7,21.7.3,21.7.3-r1"),

//21.7.3-r1.apk
),
}},
})
Expand Down Expand Up @@ -112,6 +139,7 @@ contents:
- ca-certificates-bundle=20230506-r0
- glibc-locale-posix=2.37-r6
- ko=0.13.0-r3
- nodejs=21.7.3-r1
EOF
extra_packages = ["tzdata=2023c-r0"]
}
Expand Down

0 comments on commit fbb2c09

Please sign in to comment.