Skip to content

Commit

Permalink
RHINENG-10940: block bootc systems from templates
Browse files Browse the repository at this point in the history
  • Loading branch information
psegedy committed Jul 12, 2024
1 parent 087a68e commit aba05cd
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 58 deletions.
11 changes: 11 additions & 0 deletions base/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package base

import (
"errors"
)

var (
ErrDatabase = errors.New("database error")
ErrBadRequest = errors.New("bad request")
ErrNotFound = errors.New("not found")
)
58 changes: 39 additions & 19 deletions manager/controllers/baseline_create.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package controllers

import (
"app/base"
"app/base/database"
"app/base/models"
"app/base/utils"
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -152,22 +154,27 @@ 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))
for _, containingSystem := range containingSystems {
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)
}
}

Expand All @@ -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
}
28 changes: 13 additions & 15 deletions manager/controllers/baseline_update.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion manager/controllers/baseline_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
28 changes: 14 additions & 14 deletions manager/controllers/template_systems_update.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
34 changes: 25 additions & 9 deletions manager/controllers/template_systems_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"app/base/models"
"app/base/utils"
"bytes"
"fmt"
"net/http"
"testing"

Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
Expand All @@ -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)
})
}
}

0 comments on commit aba05cd

Please sign in to comment.