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"