From d8df7e7cd46584bc81c7d2096ae83fd2e4859b6e Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Fri, 24 Jan 2025 09:29:45 -0800 Subject: [PATCH] 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 --- cmd/osbuild-worker/jobimpl-search.go | 75 ++++++++++++++++++++++++++++ cmd/osbuild-worker/main.go | 6 ++- internal/worker/json.go | 19 +++++++ internal/worker/server.go | 1 + 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 cmd/osbuild-worker/jobimpl-search.go diff --git a/cmd/osbuild-worker/jobimpl-search.go b/cmd/osbuild-worker/jobimpl-search.go new file mode 100644 index 000000000..b7106a999 --- /dev/null +++ b/cmd/osbuild-worker/jobimpl-search.go @@ -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 +} diff --git a/cmd/osbuild-worker/main.go b/cmd/osbuild-worker/main.go index bd95e7115..e7ec1c8dc 100644 --- a/cmd/osbuild-worker/main.go +++ b/cmd/osbuild-worker/main.go @@ -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 { diff --git a/internal/worker/json.go b/internal/worker/json.go index 3bda6d056..37fd7aeca 100644 --- a/internal/worker/json.go +++ b/internal/worker/json.go @@ -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 diff --git a/internal/worker/server.go b/internal/worker/server.go index c8b47c652..30f840e8d 100644 --- a/internal/worker/server.go +++ b/internal/worker/server.go @@ -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"