diff --git a/base/errors.go b/base/errors.go new file mode 100644 index 000000000..8cb6f1430 --- /dev/null +++ b/base/errors.go @@ -0,0 +1,11 @@ +package base + +import ( + "errors" +) + +var ( + ErrDatabase = errors.New("database error") + ErrBadRequest = errors.New("bad request") + ErrNotFound = errors.New("not found") +) diff --git a/manager/controllers/baseline_create.go b/manager/controllers/baseline_create.go index b94e465f2..a6bd27e6c 100644 --- a/manager/controllers/baseline_create.go +++ b/manager/controllers/baseline_create.go @@ -1,6 +1,7 @@ package controllers import ( + "app/base" "app/base/database" "app/base/models" "app/base/utils" @@ -42,6 +43,7 @@ type CreateBaselineResponse struct { type SystemBaselineDBLookup struct { InventoryID string `query:"sp.inventory_id"` SatelliteManaged bool `query:"sp.satellite_managed"` + Bootc bool `query:"sp.bootc"` } // @Summary Create a baseline for my set of systems @@ -56,6 +58,7 @@ type SystemBaselineDBLookup struct { // @Failure 404 {object} utils.ErrorResponse // @Failure 500 {object} utils.ErrorResponse // @Router /baselines [put] +// nolint: funlen func CreateBaselineHandler(c *gin.Context) { accountID := c.GetInt(utils.KeyAccount) creator := c.GetString(utils.KeyUser) @@ -81,20 +84,19 @@ func CreateBaselineHandler(c *gin.Context) { request.Description = utils.EmptyToNil(request.Description) db := middlewares.DBFromContext(c) - missingIDs, satelliteManagedIDs, err := checkInventoryIDs(db, accountID, request.InventoryIDs, groups) + err := checkInventoryIDs(db, accountID, request.InventoryIDs, groups) if err != nil { - LogAndRespError(c, err, "Database error") - return - } - - if config.EnableSatelliteFunctionality && len(satelliteManagedIDs) > 0 { - msg := fmt.Sprintf("Attempting to add satellite managed systems to baseline: %v", satelliteManagedIDs) - LogAndRespBadRequest(c, errors.New(msg), msg) - return - } else if len(missingIDs) > 0 { - msg := fmt.Sprintf("Missing inventory_ids: %v", missingIDs) - LogAndRespNotFound(c, errors.New(msg), msg) - return + switch { + case errors.Is(err, base.ErrBadRequest): + LogAndRespBadRequest(c, err, err.Error()) + return + case errors.Is(err, base.ErrNotFound): + LogAndRespNotFound(c, err, err.Error()) + return + default: + LogAndRespError(c, err, "Database error") + return + } } baselineID, err := buildCreateBaselineQuery(db, request, accountID) @@ -152,14 +154,16 @@ func buildCreateBaselineQuery(db *gorm.DB, request CreateBaselineRequest, accoun return baseline.ID, err } -func checkInventoryIDs(db *gorm.DB, accountID int, inventoryIDs []string, groups map[string]string, -) (missingIDs, satelliteManagedIDs []string, err error) { +func checkInventoryIDs(db *gorm.DB, accountID int, inventoryIDs []string, groups map[string]string) (err error) { var containingSystems []SystemBaselineDBLookup + var missingIDs []string + var satelliteIDs []string + var bootcIDs []string err = database.Systems(db, accountID, groups). Where("inventory_id::text IN (?)", inventoryIDs). Scan(&containingSystems).Error if err != nil { - return nil, nil, err + return errors.Join(base.ErrDatabase, err) } containingIDsMap := make(map[string]bool, len(containingSystems)) @@ -167,7 +171,10 @@ func checkInventoryIDs(db *gorm.DB, accountID int, inventoryIDs []string, groups containingIDsMap[containingSystem.InventoryID] = true if containingSystem.SatelliteManaged { - satelliteManagedIDs = append(satelliteManagedIDs, containingSystem.InventoryID) + satelliteIDs = append(satelliteIDs, containingSystem.InventoryID) + } + if containingSystem.Bootc { + bootcIDs = append(bootcIDs, containingSystem.InventoryID) } } @@ -178,7 +185,20 @@ func checkInventoryIDs(db *gorm.DB, accountID int, inventoryIDs []string, groups } sort.Strings(missingIDs) - sort.Strings(satelliteManagedIDs) + sort.Strings(satelliteIDs) + sort.Strings(bootcIDs) + + switch { + case config.EnableSatelliteFunctionality && len(satelliteIDs) > 0: + errIDs := fmt.Errorf("template can not contain satellite managed systems: %v", satelliteIDs) + err = errors.Join(err, base.ErrBadRequest, errIDs) + case len(bootcIDs) > 0: + errIDs := fmt.Errorf("template can not contain bootc systems: %v", bootcIDs) + err = errors.Join(err, base.ErrBadRequest, errIDs) + case len(missingIDs) > 0: + errIDs := fmt.Errorf("unknown inventory_ids: %v", missingIDs) + err = errors.Join(err, base.ErrNotFound, errIDs) + } - return missingIDs, satelliteManagedIDs, nil + return err } diff --git a/manager/controllers/baseline_update.go b/manager/controllers/baseline_update.go index 499fb61b6..2470d7d83 100644 --- a/manager/controllers/baseline_update.go +++ b/manager/controllers/baseline_update.go @@ -1,14 +1,13 @@ package controllers import ( + "app/base" "app/base/database" "app/base/models" "app/base/utils" - "app/manager/config" "app/manager/kafka" "app/manager/middlewares" "encoding/json" - "fmt" "net/http" "strconv" "time" @@ -92,20 +91,19 @@ func BaselineUpdateHandler(c *gin.Context) { } inventoryIDsList := map2list(req.InventoryIDs) - missingIDs, satelliteManagedIDs, err := checkInventoryIDs(db, account, inventoryIDsList, groups) + err = checkInventoryIDs(db, account, inventoryIDsList, groups) if err != nil { - LogAndRespError(c, err, "Database error") - return - } - - if config.EnableSatelliteFunctionality && len(satelliteManagedIDs) > 0 { - msg := fmt.Sprintf("Attempting to add satellite managed systems to baseline: %v", satelliteManagedIDs) - LogAndRespBadRequest(c, errors.New(msg), msg) - return - } else if len(missingIDs) > 0 { - msg := fmt.Sprintf("Missing inventory_ids: %v", missingIDs) - LogAndRespNotFound(c, errors.New(msg), msg) - return + switch { + case errors.Is(err, base.ErrBadRequest): + LogAndRespBadRequest(c, err, err.Error()) + return + case errors.Is(err, base.ErrNotFound): + LogAndRespNotFound(c, err, err.Error()) + return + default: + LogAndRespError(c, err, "Database error") + return + } } newAssociations, obsoleteAssociations := sortInventoryIDs(req.InventoryIDs) diff --git a/manager/controllers/baseline_update_test.go b/manager/controllers/baseline_update_test.go index 376e9c409..a160ff439 100644 --- a/manager/controllers/baseline_update_test.go +++ b/manager/controllers/baseline_update_test.go @@ -121,7 +121,7 @@ func TestUpdateBaselineInvalidSystem(t *testing.T) { var errResp utils.ErrorResponse CheckResponse(t, w, http.StatusNotFound, &errResp) - assert.Equal(t, "Missing inventory_ids: [00000000-0000-0000-0000-000000000009 incorrect_id]", + assert.Equal(t, "not found\nunknown inventory_ids: [00000000-0000-0000-0000-000000000009 incorrect_id]", errResp.Error) database.DeleteBaseline(t, baselineID) } diff --git a/manager/controllers/template_systems_update.go b/manager/controllers/template_systems_update.go index f42838b66..0f5408924 100644 --- a/manager/controllers/template_systems_update.go +++ b/manager/controllers/template_systems_update.go @@ -1,10 +1,10 @@ package controllers import ( + "app/base" "app/base/database" "app/base/models" "app/base/utils" - "app/manager/config" "app/manager/middlewares" "fmt" "net/http" @@ -65,6 +65,7 @@ func TemplateSystemsUpdateHandler(c *gin.Context) { c.Status(http.StatusOK) } +// nolint:funlen func assignTemplateSystems(c *gin.Context, db *gorm.DB, accountID int, template *models.Template, inventoryIDs []string, groups map[string]string) error { if len(inventoryIDs) == 0 { @@ -75,20 +76,19 @@ func assignTemplateSystems(c *gin.Context, db *gorm.DB, accountID int, template tx := db.Begin() defer tx.Rollback() - missingIDs, satelliteManagedIDs, err := checkInventoryIDs(db, accountID, inventoryIDs, groups) + err := checkInventoryIDs(db, accountID, inventoryIDs, groups) if err != nil { - LogAndRespError(c, err, "Database error") - return err - } - - if config.EnableSatelliteFunctionality && len(satelliteManagedIDs) > 0 { - msg := fmt.Sprintf("Template can not contain satellite managed systems: %v", satelliteManagedIDs) - LogAndRespBadRequest(c, errors.New(msg), msg) - return err - } else if len(missingIDs) > 0 { - msg := fmt.Sprintf("Unknown inventory_ids: %v", missingIDs) - LogAndRespNotFound(c, errors.New(msg), msg) - return err + switch { + case errors.Is(err, base.ErrBadRequest): + LogAndRespBadRequest(c, err, err.Error()) + return err + case errors.Is(err, base.ErrNotFound): + LogAndRespNotFound(c, err, err.Error()) + return err + default: + LogAndRespError(c, err, "Database error") + return err + } } if err := templateArchVersionMatch(db, inventoryIDs, template, accountID, groups); err != nil { diff --git a/manager/controllers/template_systems_update_test.go b/manager/controllers/template_systems_update_test.go index 132ba0699..306db840e 100644 --- a/manager/controllers/template_systems_update_test.go +++ b/manager/controllers/template_systems_update_test.go @@ -6,6 +6,7 @@ import ( "app/base/models" "app/base/utils" "bytes" + "fmt" "net/http" "testing" @@ -82,7 +83,7 @@ func TestUpdateTemplateInvalidSystem(t *testing.T) { CheckResponse(t, w, http.StatusNotFound, &errResp) // 00000000-0000-0000-0000-000000000009 is from different account and should not be added // this-is-not-a-uuid is not a valid uuid - assert.Equal(t, "Unknown inventory_ids: [00000000-0000-0000-0000-000000000009 this-is-not-a-uuid]", + assert.Equal(t, "not found\nunknown inventory_ids: [00000000-0000-0000-0000-000000000009 this-is-not-a-uuid]", errResp.Error) database.DeleteTemplate(t, templateAccount, templateUUID) } @@ -143,19 +144,12 @@ func TestReassignTemplateSystems2(t *testing.T) { database.DeleteTemplate(t, templateAccount, template2) } -func TestUpdateTemplateSatelliteSystem(t *testing.T) { +func testUpdateTemplateBadRequest(t *testing.T, system models.SystemPlatform) { core.SetupTestEnvironment() database.CreateTemplate(t, templateAccount, templateUUID, templateSystems) defer database.DeleteTemplate(t, templateAccount, templateUUID) - system := models.SystemPlatform{ - InventoryID: "99999999-0000-0000-0000-000000000015", - DisplayName: "satellite_system_test", - RhAccountID: templateAccount, - BuiltPkgcache: true, - SatelliteManaged: true, - } tx := database.DB.Create(&system) assert.Nil(t, tx.Error) defer database.DB.Delete(system) @@ -172,3 +166,25 @@ func TestUpdateTemplateSatelliteSystem(t *testing.T) { var err utils.ErrorResponse CheckResponse(t, w, http.StatusBadRequest, &err) } + +func TestUpdateTemplateBadRequest(t *testing.T) { + system := models.SystemPlatform{ + InventoryID: "99999999-0000-0000-0000-000000000015", + RhAccountID: templateAccount, + BuiltPkgcache: true, + } + satelliteSystem := system + satelliteSystem.DisplayName = "satellite_system_test" + satelliteSystem.SatelliteManaged = true + + bootcSystem := system + bootcSystem.DisplayName = "bootc_system_test" + bootcSystem.Bootc = true + + systems := []models.SystemPlatform{satelliteSystem, bootcSystem} + for _, system := range systems { + t.Run(fmt.Sprint(system.DisplayName), func(t *testing.T) { + testUpdateTemplateBadRequest(t, system) + }) + } +}