From 36ccb110b3263928ad896dd125183129076a938e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Budai?= Date: Tue, 12 Nov 2019 20:26:25 +0100 Subject: [PATCH] api: add support for /projects/depsolve --- dnf-json | 13 ++++----- internal/mocks/rpmmd/fixtures.go | 49 ++++++++++++++++++++++++++++---- internal/weldr/api.go | 25 ++++++++++++++++ internal/weldr/api_test.go | 18 ++++++++++++ 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/dnf-json b/dnf-json index 3f649119b..c0f0c103e 100644 --- a/dnf-json +++ b/dnf-json @@ -71,14 +71,11 @@ if command == "dump": elif command == "depsolve": base = create_base(arguments.get("repos", {})) errors = [] - for pkgspec in arguments["package-specs"]: - try: - base.install_specs([pkgspec]) - except dnf.exceptions.MarkingError as e: - errors.append((pkgspec, str(e))) - if errors: - formatted_errors = ", ".join((f"{package} ({err})" for package, err in errors)) - exit_with_dnf_error("MarkingError", f"The following package(s) had problems: {formatted_errors}") + + try: + base.install_specs(arguments["package-specs"]) + except dnf.exceptions.MarkingErrors as e: + exit_with_dnf_error("MarkingErrors", f"Error occurred when marking packages for installation: {e}") try: base.resolve() diff --git a/internal/mocks/rpmmd/fixtures.go b/internal/mocks/rpmmd/fixtures.go index 3378da9f6..706db07d7 100644 --- a/internal/mocks/rpmmd/fixtures.go +++ b/internal/mocks/rpmmd/fixtures.go @@ -4,16 +4,55 @@ import ( "github.com/osbuild/osbuild-composer/internal/rpmmd" ) +var basePackageList = fetchPackageList{ + rpmmd.PackageList{ + {Name: "package1"}, + {Name: "package2"}, + }, + nil, +} + var BaseFixture = Fixture{ - fetchPackageList{ - rpmmd.PackageList{ - {Name: "package1"}, - {Name: "package2"}, + basePackageList, + depsolve{ + []rpmmd.PackageSpec{ + { + Name: "libgpg-error", + Epoch: 0, + Version: "1.33", + Release: "2.fc30", + Arch: "x86_64", + }, + { + Name: "libsemanage", + Epoch: 0, + Version: "2.9", + Release: "1.fc30", + Arch: "x86_64", + }, }, nil, }, +} + +var NonExistingPackage = Fixture{ + basePackageList, depsolve{ nil, - nil, + &rpmmd.DNFError{ + Kind: "MarkingErrors", + Reason: "Error occurred when marking packages for installation: Problems in request:\nmissing packages: fash", + }, + }, +} + +var BadDepsolve = Fixture{ + basePackageList, + depsolve{ + nil, + &rpmmd.DNFError{ + Kind: "DepsolveError", + Reason: "There was a problem depsolving ['go2rpm']: \n Problem: conflicting requests\n - nothing provides askalono-cli needed by go2rpm-1-4.fc31.noarch", + }, }, } diff --git a/internal/weldr/api.go b/internal/weldr/api.go index 9fa622053..82551a99f 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -55,6 +55,8 @@ func New(rpmmd rpmmd.RPMMD, repo rpmmd.RepoConfig, packages rpmmd.PackageList, l api.router.POST("/api/v0/projects/source/new", api.sourceNewHandler) api.router.DELETE("/api/v0/projects/source/delete/*source", api.sourceDeleteHandler) + api.router.GET("/api/v0/projects/depsolve/:projects", api.projectsDepsolveHandler) + api.router.GET("/api/v0/modules/list", api.modulesListAllHandler) api.router.GET("/api/v0/modules/list/:modules", api.modulesListHandler) @@ -482,6 +484,29 @@ func (api *API) modulesInfoHandler(writer http.ResponseWriter, request *http.Req } } +func (api *API) projectsDepsolveHandler(writer http.ResponseWriter, request *http.Request, params httprouter.Params) { + type reply struct { + Projects []rpmmd.PackageSpec `json:"projects"` + } + + names := strings.Split(params.ByName("projects"), ",") + + packages, err := api.rpmmd.Depsolve(names, []rpmmd.RepoConfig{api.repo}) + + if err != nil { + errors := responseError{ + ID: "PROJECTS_ERROR", + Msg: fmt.Sprintf("BadRequest: %s", err.Error()), + } + statusResponseError(writer, http.StatusBadRequest, errors) + return + } + + json.NewEncoder(writer).Encode(reply{ + Projects: packages, + }) +} + func (api *API) blueprintsListHandler(writer http.ResponseWriter, request *http.Request, _ httprouter.Params) { type reply struct { Total uint `json:"total"` diff --git a/internal/weldr/api_test.go b/internal/weldr/api_test.go index 3edf21e0b..bcd28d832 100644 --- a/internal/weldr/api_test.go +++ b/internal/weldr/api_test.go @@ -422,3 +422,21 @@ func TestSourcesDelete(t *testing.T) { sendHTTP(api, true, "DELETE", "/api/v0/projects/source/delete/fish", ``) } } + +func TestProjectsDepsolve(t *testing.T) { + var cases = []struct { + Fixture rpmmd_mock.Fixture + Path string + ExpectedStatus int + ExpectedJSON string + }{ + {rpmmd_mock.NonExistingPackage, "/api/v0/projects/depsolve/fash", http.StatusBadRequest, `{"status":false,"errors":[{"id":"PROJECTS_ERROR","msg":"BadRequest: DNF error occured: MarkingErrors: Error occurred when marking packages for installation: Problems in request:\nmissing packages: fash"}]}`}, + {rpmmd_mock.BaseFixture, "/api/v0/projects/depsolve/fish", http.StatusOK, `{"projects":[{"name":"libgpg-error","epoch":0,"version":"1.33","release":"2.fc30","arch":"x86_64"},{"name":"libsemanage","epoch":0,"version":"2.9","release":"1.fc30","arch":"x86_64"}]}`}, + {rpmmd_mock.BadDepsolve, "/api/v0/projects/depsolve/go2rpm", http.StatusBadRequest, `{"status":false,"errors":[{"id":"PROJECTS_ERROR","msg":"BadRequest: DNF error occured: DepsolveError: There was a problem depsolving ['go2rpm']: \n Problem: conflicting requests\n - nothing provides askalono-cli needed by go2rpm-1-4.fc31.noarch"}]}`}, + } + + for _, c := range cases { + api, _ := createWeldrAPI(c.Fixture) + testRoute(t, api, true, "GET", c.Path, ``, c.ExpectedStatus, c.ExpectedJSON) + } +}