From a39ac200f757b921df6a2241fb5faacad4c99640 Mon Sep 17 00:00:00 2001 From: Patrik Segedy Date: Wed, 12 Jun 2024 17:08:52 +0200 Subject: [PATCH] RHINENG-10240: check compatiblity of template and system rhel version --- manager/controllers/template_systems.go | 21 +++++----- .../controllers/template_systems_update.go | 41 +++++++++++++++++-- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/manager/controllers/template_systems.go b/manager/controllers/template_systems.go index 223527a24..d1b004f96 100644 --- a/manager/controllers/template_systems.go +++ b/manager/controllers/template_systems.go @@ -53,42 +53,41 @@ type TemplateSystemsResponse struct { Meta ListMeta `json:"meta"` } -func getTemplateID(c *gin.Context, tx *gorm.DB, account int, uuid string) (int64, error) { - var id int64 +func getTemplate(c *gin.Context, tx *gorm.DB, account int, uuid string) (*models.Template, error) { + var template models.Template if !utils.IsValidUUID(uuid) { err := errors.Errorf("Invalid template uuid: %s", uuid) LogAndRespNotFound(c, err, err.Error()) - return 0, err + return &template, err } err := tx.Model(&models.Template{}). - Select("id"). Where("rh_account_id = ? AND uuid = ?::uuid ", account, uuid). // use Find() not First() otherwise it returns error "no rows found" if uuid is not present - Find(&id).Error + Find(&template).Error if err != nil { LogAndRespError(c, err, "database error") - return 0, err + return &template, err } - if id == 0 { + if template.ID == 0 { err := errors.New("Template not found") LogAndRespNotFound(c, err, err.Error()) - return 0, err + return &template, err } - return id, nil + return &template, nil } func templateSystemsQuery(c *gin.Context, account int, groups map[string]string) (*gorm.DB, Filters, error) { templateUUID := c.Param("template_id") db := middlewares.DBFromContext(c) - templateID, err := getTemplateID(c, db, account, templateUUID) + template, err := getTemplate(c, db, account, templateUUID) if err != nil { // respose set in getTemplateID() return nil, nil, err } query := database.Systems(db, account, groups). - Where("sp.template_id = ?", templateID). + Where("sp.template_id = ?", template.ID). Select(templateSystemSelect) filters, err := ParseAllFilters(c, TemplateSystemOpts) diff --git a/manager/controllers/template_systems_update.go b/manager/controllers/template_systems_update.go index 02618cdb7..a35bb851a 100644 --- a/manager/controllers/template_systems_update.go +++ b/manager/controllers/template_systems_update.go @@ -8,6 +8,8 @@ import ( "fmt" "net/http" + errors2 "errors" + "github.com/pkg/errors" "gorm.io/gorm" @@ -44,13 +46,13 @@ func TemplateSystemsUpdateHandler(c *gin.Context) { } db := middlewares.DBFromContext(c) - templateID, err := getTemplateID(c, db, account, templateUUID) + template, err := getTemplate(c, db, account, templateUUID) if err != nil { // respose set in getTemplateID() return } - err = assignTemplateSystems(c, db, account, &templateID, req.Systems, groups) + err = assignTemplateSystems(c, db, account, template, req.Systems, groups) if err != nil { return } @@ -62,7 +64,7 @@ func TemplateSystemsUpdateHandler(c *gin.Context) { c.Status(http.StatusOK) } -func assignTemplateSystems(c *gin.Context, db *gorm.DB, accountID int, templateID *int64, +func assignTemplateSystems(c *gin.Context, db *gorm.DB, accountID int, template *models.Template, inventoryIDs []string, groups map[string]string) error { if len(inventoryIDs) == 0 { err := errors.New(InvalidInventoryIDsErr) @@ -88,10 +90,16 @@ func assignTemplateSystems(c *gin.Context, db *gorm.DB, accountID int, templateI return err } + if err := templateArchVersionMatch(db, inventoryIDs, template); err != nil { + msg := fmt.Sprintf("Incompatible template and system version or architecture: %s", err.Error()) + LogAndRespBadRequest(c, err, msg) + return err + } + tx = tx.Model(models.SystemPlatform{}). Where("rh_account_id = ? AND inventory_id IN (?::uuid)", accountID, inventoryIDs). - Update("template_id", templateID) + Update("template_id", template.ID) if e := tx.Error; e != nil { LogAndRespError(c, err, "Database error") return e @@ -109,3 +117,28 @@ func assignTemplateSystems(c *gin.Context, db *gorm.DB, accountID int, templateI } return nil } + +func templateArchVersionMatch(db *gorm.DB, inventoryIDs []string, template *models.Template) error { + var archVersions = []struct { + InventoryID string + Arch string + Version string + }{} + var err error + db.Table("inventory.hosts"). + // TODO: we need also ARCH but it is missing in system_profile + Select("id as inventory_id, system_profile->'operating_system'->>'major' as version"). + Where("id in (?)", inventoryIDs).Find(&archVersions) + + for _, av := range archVersions { + if av.Version != template.Version { + // TODO: check arch + if err == nil { + err = fmt.Errorf("template arch: %s, version: %s", template.Arch, template.Version) + } + systemErr := fmt.Errorf("system uuid: %s, arch: %s, version: %s", av.InventoryID, av.Arch, av.Version) + err = errors2.Join(err, systemErr) + } + } + return err +}