worker: Add search job implementation to worker client

This is similar to the depsolve job, and it shares the solver (which
supports locking, as does DNF itself). This will allow searching for
specific package names, names with globs, or names as substrings of
other names using * as the wildcard.

Related: RHEL-60136
This commit is contained in:
Brian C. Lane 2025-01-24 09:29:45 -08:00 committed by Tomáš Hozza
parent 84c0f79286
commit d8df7e7cd4
4 changed files with 100 additions and 1 deletions

View file

@ -0,0 +1,75 @@
package main
import (
"github.com/osbuild/images/pkg/dnfjson"
"github.com/osbuild/images/pkg/rpmmd"
"github.com/osbuild/osbuild-composer/internal/worker"
"github.com/osbuild/osbuild-composer/internal/worker/clienterrors"
"github.com/sirupsen/logrus"
)
// SearchPackagesJobImpl shares the solver with the depsolve job.
type SearchPackagesJobImpl struct {
Solver *dnfjson.BaseSolver
RepositoryMTLSConfig *RepositoryMTLSConfig
}
func (impl *SearchPackagesJobImpl) search(repos []rpmmd.RepoConfig, modulePlatformID, arch, releasever string, packages []string) (rpmmd.PackageList, error) {
solver := impl.Solver.NewWithConfig(modulePlatformID, releasever, arch, "")
if impl.RepositoryMTLSConfig != nil && impl.RepositoryMTLSConfig.Proxy != nil {
err := solver.SetProxy(impl.RepositoryMTLSConfig.Proxy.String())
if err != nil {
return nil, err
}
}
return solver.SearchMetadata(repos, packages)
}
// Run executes the search and returns the results
func (impl *SearchPackagesJobImpl) Run(job worker.Job) error {
logWithId := logrus.WithField("jobId", job.Id())
var result worker.SearchPackagesJobResult
// ALWAYS return a result
defer func() {
err := job.Update(&result)
if err != nil {
logWithId.Errorf("Error reporting job result: %v", err)
}
}()
var args worker.SearchPackagesJob
err := job.Args(&args)
if err != nil {
return err
}
if impl.RepositoryMTLSConfig != nil {
for repoi, repo := range args.Repositories {
for _, baseurlstr := range repo.BaseURLs {
match, err := impl.RepositoryMTLSConfig.CompareBaseURL(baseurlstr)
if err != nil {
result.JobError = clienterrors.New(clienterrors.ErrorInvalidRepositoryURL, "Repository URL is malformed", err.Error())
return err
}
if match {
impl.RepositoryMTLSConfig.SetupRepoSSL(&args.Repositories[repoi])
}
}
}
}
result.Packages, err = impl.search(args.Repositories, args.ModulePlatformID, args.Arch, args.Releasever, args.Packages)
if err != nil {
result.JobError = workerClientErrorFrom(err, logWithId)
}
if err := impl.Solver.CleanCache(); err != nil {
// log and ignore
logWithId.Errorf("Error during rpm repo cache cleanup: %s", err.Error())
}
// NOTE: result is returned by deferred function above
return nil
}

View file

@ -427,7 +427,7 @@ var run = func() {
}
}
// depsolve jobs can be done during other jobs
// depsolve and search jobs can be done during other jobs
depsolveCtx, depsolveCtxCancel := context.WithCancel(context.Background())
solver := dnfjson.NewBaseSolver(rpmmd_cache)
if config.DNFJson != "" {
@ -440,6 +440,10 @@ var run = func() {
Solver: solver,
RepositoryMTLSConfig: repositoryMTLSConfig,
},
worker.JobTypeSearchPackages: &SearchPackagesJobImpl{
Solver: solver,
RepositoryMTLSConfig: repositoryMTLSConfig,
},
}
acceptedJobTypes := []string{}
for jt := range jobImpls {

View file

@ -217,6 +217,25 @@ type DepsolveJobResult struct {
JobResult
}
// SearchPackagesJob defines the parameters for a dnf metadata search
// It will search the included repositories for packages matching the
// package strings
// Package names support globs using '*' and will search for a substring
// match if '*foopkg*' is used.
type SearchPackagesJob struct {
Packages []string `json:"packages"`
Repositories []rpmmd.RepoConfig `json:"repos"`
ModulePlatformID string `json:"module_platform_id"`
Arch string `json:"arch"`
Releasever string `json:"releasever"`
}
// SearchPackagesJobResult returns the details of the search packages
type SearchPackagesJobResult struct {
Packages rpmmd.PackageList `json:"packages"`
JobResult
}
type ManifestJobByID struct{}
// OSBuildComposerDepModule contains information about a module used by

View file

@ -33,6 +33,7 @@ const (
JobTypeKojiInit string = "koji-init"
JobTypeKojiFinalize string = "koji-finalize"
JobTypeDepsolve string = "depsolve"
JobTypeSearchPackages string = "search-packages"
JobTypeManifestIDOnly string = "manifest-id-only"
JobTypeContainerResolve string = "container-resolve"
JobTypeFileResolve string = "file-resolve"