From 453d2dfd5f538a3c2028ae3ed5fe0d6a63fe1df5 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 19 May 2021 14:38:06 -0700 Subject: [PATCH] weldr: Select the distribution specific ImageType This uses the image type based on the distribution selected by the blueprint, or the host distro if none is present. This enables compose to build images for the selected distribution. It adds a helper, getImageType(), to return the ImageType based on the distro name and compose type. --- internal/weldr/api.go | 82 ++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/internal/weldr/api.go b/internal/weldr/api.go index ba2534a12..bac474cbd 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -355,6 +355,21 @@ func (api *API) openImageFile(composeId uuid.UUID, compose store.Compose) (io.Re return reader, size, nil } +// getImageType returns the ImageType for the selected distro +// This is necessary because different distros support different image types, and the image +// type may have a different package set than other distros. +func (api *API) getImageType(distroName, imageType string) (distro.ImageType, error) { + distro := api.distros.GetDistro(distroName) + if distro == nil { + return nil, fmt.Errorf("GetDistro - unknown distribution: %s", distroName) + } + arch, err := distro.GetArch(api.arch.Name()) + if err != nil { + return nil, err + } + return arch.GetImageType(imageType) +} + func verifyRequestVersion(writer http.ResponseWriter, params httprouter.Params, minVersion uint) bool { versionString := params.ByName("version") @@ -1901,12 +1916,18 @@ func (api *API) blueprintsTagHandler(writer http.ResponseWriter, request *http.R statusResponseOK(writer) } +// depsolveBlueprintForImageType handles depsolving the blueprint package list and +// the packages required for the image type. +// NOTE: The imageType *must* be from the same distribution as the blueprint. func (api *API) depsolveBlueprintForImageType(bp blueprint.Blueprint, imageType distro.ImageType) (map[string][]rpmmd.PackageSpec, error) { // Depsolve using the host distro if none has been specified if bp.Distro == "" { bp.Distro = api.hostDistroName } + if bp.Distro != imageType.Arch().Distro().Name() { + return nil, fmt.Errorf("Blueprint distro %s does not match imageType distro %s", bp.Distro, imageType.Arch().Distro().Name()) + } packageSets := imageType.PackageSets(bp) packageSpecSets := make(map[string][]rpmmd.PackageSpec) @@ -1914,9 +1935,12 @@ func (api *API) depsolveBlueprintForImageType(bp blueprint.Blueprint, imageType if err != nil { return nil, err } - + platformID := imageType.Arch().Distro().ModulePlatformID() for name, packageSet := range packageSets { - packageSpecs, _, err := api.rpmmd.Depsolve(packageSet, imageTypeRepos, api.distro.ModulePlatformID(), api.arch.Name()) + packageSpecs, _, err := api.rpmmd.Depsolve(packageSet, + imageTypeRepos, + platformID, + api.arch.Name()) if err != nil { return nil, err } @@ -1968,7 +1992,35 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request return } - imageType, err := api.arch.GetImageType(cr.ComposeType) + if !verifyStringsWithRegex(writer, []string{cr.BlueprintName}, ValidBlueprintName) { + return + } + + bp := api.store.GetBlueprintCommitted(cr.BlueprintName) + if bp == nil { + errors := responseError{ + ID: "UnknownBlueprint", + Msg: fmt.Sprintf("Unknown blueprint name: %s", cr.BlueprintName), + } + statusResponseError(writer, http.StatusBadRequest, errors) + return + } + + distroName := bp.Distro + if distroName == "" { + distroName = api.hostDistroName + } + if api.distros.GetDistro(distroName) == nil { + errors := responseError{ + ID: "DistroError", + Msg: fmt.Sprintf("Unknown distribution: %s", distroName), + } + statusResponseError(writer, http.StatusBadRequest, errors) + return + } + + // Get the imageType that corresponds to the distribution selected by the blueprint + imageType, err := api.getImageType(distroName, cr.ComposeType) if err != nil { errors := responseError{ ID: "UnknownComposeType", @@ -1990,10 +2042,6 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request return } - if !verifyStringsWithRegex(writer, []string{cr.BlueprintName}, ValidBlueprintName) { - return - } - composeID := uuid.New() var targets []*target.Target @@ -2002,16 +2050,6 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request targets = append(targets, t) } - bp := api.store.GetBlueprintCommitted(cr.BlueprintName) - if bp == nil { - errors := responseError{ - ID: "UnknownBlueprint", - Msg: fmt.Sprintf("Unknown blueprint name: %s", cr.BlueprintName), - } - statusResponseError(writer, http.StatusBadRequest, errors) - return - } - // Check for test parameter q, err := url.ParseQuery(request.URL.RawQuery) if err != nil { @@ -2075,7 +2113,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request seed := bigSeed.Int64() imageRepos, err := api.allRepositoriesByImageType(imageType) - // this shoudl not happen if the api.depsolveBlueprintForImageType() call above worked + // this should not happen if the api.depsolveBlueprintForImageType() call above worked if err != nil { errors := responseError{ ID: "InternalError", @@ -2854,7 +2892,7 @@ func (api *API) fetchPackageList(distroName string) (rpmmd.PackageList, error) { // Returns all configured repositories (base, depending on the image type + sources) as rpmmd.RepoConfig // The difference from allRepositories() is that this method may return additional repositories, // which are needed to build the specific image type. The allRepositories() can't do this, because -// it is used in paces where image types are not considered. +// it is used in places where image types are not considered. func (api *API) allRepositoriesByImageType(imageType distro.ImageType) ([]rpmmd.RepoConfig, error) { imageTypeRepos, err := api.repoRegistry.ReposByImageType(imageType) if err != nil { @@ -2890,12 +2928,16 @@ func (api *API) depsolveBlueprint(bp blueprint.Blueprint) ([]rpmmd.PackageSpec, bp.Distro = api.hostDistroName } + d := api.distros.GetDistro(bp.Distro) + if d == nil { + return nil, fmt.Errorf("GetDistro - unknown distribution: %s", bp.Distro) + } repos, err := api.allRepositories(bp.Distro) if err != nil { return nil, err } - packages, _, err := api.rpmmd.Depsolve(rpmmd.PackageSet{Include: bp.GetPackages()}, repos, api.distro.ModulePlatformID(), api.arch.Name()) + packages, _, err := api.rpmmd.Depsolve(rpmmd.PackageSet{Include: bp.GetPackages()}, repos, d.ModulePlatformID(), api.arch.Name()) if err != nil { return nil, err }