From b477e4cd1159ab63c04c7dfe8e037e0c50430160 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Mon, 22 Apr 2024 13:54:05 +0200 Subject: [PATCH 1/9] RHINENG-9505: create candlepin mock --- platform/candlepin.go | 39 +++++++++++++++++++++++++++++++++++++++ platform/platform.go | 1 + 2 files changed, 40 insertions(+) create mode 100644 platform/candlepin.go diff --git a/platform/candlepin.go b/platform/candlepin.go new file mode 100644 index 000000000..b941dd911 --- /dev/null +++ b/platform/candlepin.go @@ -0,0 +1,39 @@ +package platform + +import ( + "app/base/utils" + "fmt" + "io" + "net/http" + + "github.com/gin-gonic/gin" +) + +func candlepinEnvHandler(c *gin.Context) { + envID := c.Param("envid") + /* + jsonData, _ := io.ReadAll(c.Request.Body) + json.Unmarshal(jsonData, &body) // nolint:errcheck + if body.ReturnStatus > 200 { + c.AbortWithStatus(body.ReturnStatus) + return + } + */ + data := fmt.Sprintf(`{ + "environment": "%s" + }`, envID) + utils.LogInfo(data) + c.Data(http.StatusOK, gin.MIMEJSON, []byte(data)) +} + +func candlepinConsumersHandler(c *gin.Context) { + consumer := c.Param("consumer") + jsonData, _ := io.ReadAll(c.Request.Body) + utils.LogInfo("consumer", consumer, "body", string(jsonData)) + c.Data(http.StatusOK, gin.MIMEJSON, []byte{}) +} + +func initCandlepin(app *gin.Engine) { + app.POST("/candlepin/environments/:envid/consumers", candlepinEnvHandler) + app.PUT("/candlepin/consumers/:consumer", candlepinConsumersHandler) +} diff --git a/platform/platform.go b/platform/platform.go index b351e8fb1..9cb57a695 100644 --- a/platform/platform.go +++ b/platform/platform.go @@ -184,6 +184,7 @@ func platformMock() { app.Use(middlewares.RequestResponseLogger()) initVMaaS(app) initRbac(app) + initCandlepin(app) // Control endpoint handler app.POST("/control/upload", mockUploadHandler) From e7e2242118eb65aa7370f2f1c3c6eb9c0db2baa3 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Tue, 23 Apr 2024 15:11:48 +0200 Subject: [PATCH 2/9] RHINENG-9505: add call to candlepin into /templates/update --- base/candlepin/candlepin.go | 13 ++++ base/utils/config.go | 2 + conf/common.env | 2 + conf/local.env | 1 + docker-compose.test.yml | 1 + manager/config/config.go | 7 ++ manager/controllers/template_systems.go | 3 +- .../controllers/template_systems_update.go | 71 +++++++++++++++++++ manager/manager.go | 3 + 9 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 base/candlepin/candlepin.go diff --git a/base/candlepin/candlepin.go b/base/candlepin/candlepin.go new file mode 100644 index 000000000..39083114d --- /dev/null +++ b/base/candlepin/candlepin.go @@ -0,0 +1,13 @@ +package candlepin + +type ConsumersUpdateRequest struct { + Environments []ConsumersUpdateEnvironment +} + +type ConsumersUpdateEnvironment struct { + ID string +} + +type ConsumersUpdateResponse struct { + Message string `json:"displayMessage"` +} diff --git a/base/utils/config.go b/base/utils/config.go index da29bd38b..4e996cd83 100644 --- a/base/utils/config.go +++ b/base/utils/config.go @@ -70,6 +70,7 @@ type coreConfig struct { // services VmaasAddress string RbacAddress string + CandlepinAddress string ManagerPrivateAddress string ListenerPrivateAddress string EvaluatorUploadPrivateAddress string @@ -154,6 +155,7 @@ func initTopicsFromEnv() { func initServicesFromEnv() { CoreCfg.VmaasAddress = Getenv("VMAAS_ADDRESS", CoreCfg.VmaasAddress) CoreCfg.RbacAddress = Getenv("RBAC_ADDRESS", CoreCfg.RbacAddress) + CoreCfg.CandlepinAddress = Getenv("CANDLEPIN_ADDRESS", CoreCfg.CandlepinAddress) } func initDBFromClowder() { diff --git a/conf/common.env b/conf/common.env index 3f9177640..160626276 100644 --- a/conf/common.env +++ b/conf/common.env @@ -21,3 +21,5 @@ TEMPLATE_TOPIC=platform.content-sources.template # If vmaas is running locally, its available here #VMAAS_ADDRESS=http://vmaas_webapp:8080 ENABLE_PROFILER=true + +CANDLEPIN_ADDRESS=http://platform:9001/candlepin diff --git a/conf/local.env b/conf/local.env index 6d309e442..26768ccdb 100644 --- a/conf/local.env +++ b/conf/local.env @@ -14,6 +14,7 @@ DB_SSLMODE=verify-full DB_SSLROOTCERT=dev/database/secrets/pgca.crt VMAAS_ADDRESS=http://localhost:9001 +CANDLEPIN_ADDRESS=http://localhost:9001/candlepin #KAFKA_ADDRESS=localhost:29092 KAFKA_GROUP=patchman diff --git a/docker-compose.test.yml b/docker-compose.test.yml index c34efae87..3bfa68f6f 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -43,6 +43,7 @@ services: target: buildimg image: patchman-engine-app env_file: + - ./conf/common.env - ./conf/platform.env command: ./dev/scripts/docker-compose-entrypoint.sh platform restart: unless-stopped diff --git a/manager/config/config.go b/manager/config/config.go index 4d2ba424d..e4a0ac2e1 100644 --- a/manager/config/config.go +++ b/manager/config/config.go @@ -33,5 +33,12 @@ var ( // Expose templates API (feature flag) EnableTemplates = utils.PodConfig.GetBool("templates_api", true) + // Toggle compression when calling Candlepi API + CandlepinCallCmp = utils.PodConfig.GetBool("candlepin_call_compression", true) + // Number of retries on Candlepin API + CandlepinRetries = utils.PodConfig.GetInt("candlepin_retries", 5) + // Toggle exponential retries on Candlepin API + CandlepinExpRetries = utils.PodConfig.GetBool("candlepin_exp_retries", true) + // Debug flag for API calls DebugRequest = log.IsLevelEnabled(log.TraceLevel) ) diff --git a/manager/controllers/template_systems.go b/manager/controllers/template_systems.go index a388a8971..557e24a6d 100644 --- a/manager/controllers/template_systems.go +++ b/manager/controllers/template_systems.go @@ -60,8 +60,7 @@ func getTemplate(c *gin.Context, tx *gorm.DB, account int, uuid string) (*models LogAndRespNotFound(c, err, err.Error()) return &template, err } - err := tx.Model(&models.Template{}). - Where("rh_account_id = ? AND uuid = ?::uuid ", account, uuid). + err := tx.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(&template).Error if err != nil { diff --git a/manager/controllers/template_systems_update.go b/manager/controllers/template_systems_update.go index 0f5408924..71bb0e7d3 100644 --- a/manager/controllers/template_systems_update.go +++ b/manager/controllers/template_systems_update.go @@ -2,10 +2,14 @@ package controllers import ( "app/base" + "app/base/api" + "app/base/candlepin" "app/base/database" "app/base/models" "app/base/utils" + "app/manager/config" "app/manager/middlewares" + "context" "fmt" "net/http" @@ -17,6 +21,12 @@ import ( "github.com/gin-gonic/gin" ) +var errCandlepin = errors.New("candlepin error") +var candlepinClient = api.Client{ + HTTPClient: &http.Client{Transport: &http.Transport{DisableCompression: !config.CandlepinCallCmp}}, + Debug: config.DebugRequest, +} + type TemplateSystemsUpdateRequest struct { // List of inventory IDs to have templates removed Systems []string `json:"systems" example:"system1-uuid, system2-uuid, ..."` @@ -58,6 +68,11 @@ func TemplateSystemsUpdateHandler(c *gin.Context) { return } + err = assignCandlepinEnvironment(c, db, account, template.EnvironmentID, req.Systems, groups) + if err != nil { + return + } + // TODO: re-evaluate systems added/removed from templates // inventoryAIDs := kafka.InventoryIDs2InventoryAIDs(account, req.InventoryIDs) // kafka.EvaluateBaselineSystems(inventoryAIDs) @@ -155,3 +170,59 @@ func templateArchVersionMatch( } return err } + +func callCandlepin(ctx context.Context, consumer string, request *candlepin.ConsumersUpdateRequest) ( + *candlepin.ConsumersUpdateResponse, error) { + candlepinEnvConsumersURL := utils.CoreCfg.CandlepinAddress + "/consumers/" + consumer + candlepinFunc := func() (interface{}, *http.Response, error) { + utils.LogTrace("request", *request, "candlepin /consumers request") + candlepinResp := candlepin.ConsumersUpdateResponse{} + resp, err := candlepinClient.Request(&ctx, http.MethodPut, candlepinEnvConsumersURL, request, &candlepinResp) + statusCode := utils.TryGetStatusCode(resp) + utils.LogDebug("status_code", statusCode, "candlepin /consumers call") + utils.LogTrace("response", resp, "candlepin /consumers response") + if err != nil && statusCode == 400 { + err = errors.Wrap(errCandlepin, err.Error()) + } + return &candlepinResp, resp, err + } + + candlepinRespPtr, err := utils.HTTPCallRetry(base.Context, candlepinFunc, config.CandlepinExpRetries, + config.CandlepinRetries, http.StatusServiceUnavailable) + if err != nil { + return nil, errors.Wrap(err, "candlepin /consumers call failed") + } + return candlepinRespPtr.(*candlepin.ConsumersUpdateResponse), nil +} + +func assignCandlepinEnvironment(c context.Context, db *gorm.DB, accountID int, env string, inventoryIDs []string, + groups map[string]string) error { + var consumers = []struct { + InventoryID string + Consumer *string + }{} + + err := database.Systems(db, accountID, groups). + Select("ih.id as inventory_id, ih.system_profile->>'owner_id' as consumer"). + Where("ih.id in (?)", inventoryIDs).Find(&consumers).Error + if err != nil { + return err + } + + updateReq := candlepin.ConsumersUpdateRequest{ + Environments: []candlepin.ConsumersUpdateEnvironment{{ID: env}}, + } + for _, consumer := range consumers { + if consumer.Consumer == nil { + err = errors2.Join(err, errors.Errorf("Missing owner_id for '%s'", consumer.InventoryID)) + continue + } + resp, apiErr := callCandlepin(c, *consumer.Consumer, &updateReq) + // check response + if err != nil { + err = errors2.Join(err, apiErr, errors.New(resp.Message)) + } + } + + return err +} diff --git a/manager/manager.go b/manager/manager.go index 84f45521b..67b720fbd 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -2,6 +2,7 @@ package manager import ( "app/base" + "app/base/candlepin" "app/base/core" "app/base/mqueue" "app/base/utils" @@ -35,6 +36,8 @@ var basepaths = []string{"/api/patch/v3"} // @BasePath /api/patch/v3 func RunManager() { core.ConfigureApp() + config.CandlepinEnvURL = utils.FailIfEmpty(utils.CoreCfg.CandlepinAddress, "CANDLEPIN_ADDRESS") + + candlepin.APIPrefix + "/environments/" port := utils.CoreCfg.PublicPort utils.LogInfo("port", port, "Manager starting at port") From 638bd3359df2944e1899bbbff841baa853073495 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Wed, 24 Apr 2024 16:07:33 +0200 Subject: [PATCH 3/9] RHINENG-9505: template update and delete need write permission --- manager/middlewares/rbac.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manager/middlewares/rbac.go b/manager/middlewares/rbac.go index a7bde75aa..e809143b7 100644 --- a/manager/middlewares/rbac.go +++ b/manager/middlewares/rbac.go @@ -32,6 +32,8 @@ var granularPerms = map[string]string{ "BaselineUpdateHandler": "patch:template:write", "BaselineDeleteHandler": "patch:template:write", "BaselineSystemsRemoveHandler": "patch:template:write", + "TemplateSystemsUpdateHandler": "patch:template:write", + "TemplateSystemsDeleteHandler": "patch:template:write", "SystemDeleteHandler": "patch:system:write", } From ac43268a6033ecccb5e303c5375acf9e60b1a805 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Tue, 2 Jul 2024 14:06:21 +0200 Subject: [PATCH 4/9] RHINENG-9505: use client cert to access candlepin --- base/utils/config.go | 4 ++ manager/config/config.go | 40 +++++++++++++++++++ .../controllers/template_systems_delete.go | 5 +++ .../controllers/template_systems_update.go | 16 ++++---- manager/manager.go | 3 -- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/base/utils/config.go b/base/utils/config.go index 4e996cd83..ba8d97bb6 100644 --- a/base/utils/config.go +++ b/base/utils/config.go @@ -71,6 +71,8 @@ type coreConfig struct { VmaasAddress string RbacAddress string CandlepinAddress string + CandlepinCert string + CandlepinKey string ManagerPrivateAddress string ListenerPrivateAddress string EvaluatorUploadPrivateAddress string @@ -156,6 +158,8 @@ func initServicesFromEnv() { CoreCfg.VmaasAddress = Getenv("VMAAS_ADDRESS", CoreCfg.VmaasAddress) CoreCfg.RbacAddress = Getenv("RBAC_ADDRESS", CoreCfg.RbacAddress) CoreCfg.CandlepinAddress = Getenv("CANDLEPIN_ADDRESS", CoreCfg.CandlepinAddress) + CoreCfg.CandlepinCert = Getenv("CANDLEPIN_CERT", CoreCfg.CandlepinCert) + CoreCfg.CandlepinKey = Getenv("CANDLEPIN_KEY", CoreCfg.CandlepinKey) } func initDBFromClowder() { diff --git a/manager/config/config.go b/manager/config/config.go index e4a0ac2e1..0c38d97cc 100644 --- a/manager/config/config.go +++ b/manager/config/config.go @@ -1,7 +1,11 @@ package config import ( + "app/base/api" "app/base/utils" + "crypto/tls" + "crypto/x509" + "net/http" log "github.com/sirupsen/logrus" ) @@ -42,3 +46,39 @@ var ( // Debug flag for API calls DebugRequest = log.IsLevelEnabled(log.TraceLevel) ) + +func CreateCandlepinClient() api.Client { + getTLSConfig := func() (*tls.Config, error) { + var tlsConfig *tls.Config + if utils.CoreCfg.CandlepinCert != "" && utils.CoreCfg.CandlepinKey != "" { + clientCert, err := tls.X509KeyPair([]byte(utils.CoreCfg.CandlepinCert), []byte(utils.CoreCfg.CandlepinKey)) + if err != nil { + return nil, err + } + certPool, err := x509.SystemCertPool() + if err != nil { + return nil, err + } + tlsConfig = &tls.Config{ + Certificates: []tls.Certificate{clientCert}, + RootCAs: certPool, + MinVersion: tls.VersionTLS12, + } + utils.LogInfo("using cert to access candlepin") + } + return tlsConfig, nil + } + + tlsConfig, err := getTLSConfig() + if err != nil { + utils.LogError("err", err, "parsing candlepin cert") + } + + return api.Client{ + HTTPClient: &http.Client{Transport: &http.Transport{ + DisableCompression: !CandlepinCallCmp, + TLSClientConfig: tlsConfig, + }}, + Debug: DebugRequest, + } +} diff --git a/manager/controllers/template_systems_delete.go b/manager/controllers/template_systems_delete.go index 9dd0a4989..f7622c3ad 100644 --- a/manager/controllers/template_systems_delete.go +++ b/manager/controllers/template_systems_delete.go @@ -38,6 +38,11 @@ func TemplateSystemsDeleteHandler(c *gin.Context) { return } + err = assignCandlepinEnvironment(c, db, account, nil, req.Systems, groups) + if err != nil { + return + } + // TODO: re-evaluate systems removed from templates // inventoryAIDs := kafka.InventoryIDs2InventoryAIDs(account, req.Systems) // kafka.EvaluateBaselineSystems(inventoryAIDs) diff --git a/manager/controllers/template_systems_update.go b/manager/controllers/template_systems_update.go index 71bb0e7d3..f2f940000 100644 --- a/manager/controllers/template_systems_update.go +++ b/manager/controllers/template_systems_update.go @@ -2,7 +2,6 @@ package controllers import ( "app/base" - "app/base/api" "app/base/candlepin" "app/base/database" "app/base/models" @@ -22,10 +21,7 @@ import ( ) var errCandlepin = errors.New("candlepin error") -var candlepinClient = api.Client{ - HTTPClient: &http.Client{Transport: &http.Transport{DisableCompression: !config.CandlepinCallCmp}}, - Debug: config.DebugRequest, -} +var candlepinClient = config.CreateCandlepinClient() type TemplateSystemsUpdateRequest struct { // List of inventory IDs to have templates removed @@ -68,7 +64,7 @@ func TemplateSystemsUpdateHandler(c *gin.Context) { return } - err = assignCandlepinEnvironment(c, db, account, template.EnvironmentID, req.Systems, groups) + err = assignCandlepinEnvironment(c, db, account, &template.EnvironmentID, req.Systems, groups) if err != nil { return } @@ -195,7 +191,7 @@ func callCandlepin(ctx context.Context, consumer string, request *candlepin.Cons return candlepinRespPtr.(*candlepin.ConsumersUpdateResponse), nil } -func assignCandlepinEnvironment(c context.Context, db *gorm.DB, accountID int, env string, inventoryIDs []string, +func assignCandlepinEnvironment(c context.Context, db *gorm.DB, accountID int, env *string, inventoryIDs []string, groups map[string]string) error { var consumers = []struct { InventoryID string @@ -209,8 +205,12 @@ func assignCandlepinEnvironment(c context.Context, db *gorm.DB, accountID int, e return err } + environments := []candlepin.ConsumersUpdateEnvironment{} + if env != nil { + environments = []candlepin.ConsumersUpdateEnvironment{{ID: *env}} + } updateReq := candlepin.ConsumersUpdateRequest{ - Environments: []candlepin.ConsumersUpdateEnvironment{{ID: env}}, + Environments: environments, } for _, consumer := range consumers { if consumer.Consumer == nil { diff --git a/manager/manager.go b/manager/manager.go index 67b720fbd..84f45521b 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -2,7 +2,6 @@ package manager import ( "app/base" - "app/base/candlepin" "app/base/core" "app/base/mqueue" "app/base/utils" @@ -36,8 +35,6 @@ var basepaths = []string{"/api/patch/v3"} // @BasePath /api/patch/v3 func RunManager() { core.ConfigureApp() - config.CandlepinEnvURL = utils.FailIfEmpty(utils.CoreCfg.CandlepinAddress, "CANDLEPIN_ADDRESS") + - candlepin.APIPrefix + "/environments/" port := utils.CoreCfg.PublicPort utils.LogInfo("port", port, "Manager starting at port") From e92386f48e0ce7b8876a316c0f588ae3fecfec02 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Wed, 31 Jul 2024 14:26:17 +0200 Subject: [PATCH 5/9] RHINENG-9505: add owner_id to test data --- dev/test_data.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/test_data.sql b/dev/test_data.sql index 39bf59068..d9ce77f0a 100644 --- a/dev/test_data.sql +++ b/dev/test_data.sql @@ -194,19 +194,19 @@ INSERT INTO inventory.hosts_v1_0 (id, insights_id, account, display_name, tags, '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 1}, "rhsm": {"version": "8.0"}}', 'puptoo', '{}', 'org_1', '[{"id": "inventory-group-1", "name": "group1"}]'), ('00000000000000000000000000000004', '00000000-0000-0000-0004-000000000001', '1', '00000000-0000-0000-0000-000000000004', '[{"key": "k3", "value": "val4", "namespace": "ns1"}]', - '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 2}, "rhsm": {"version": "8.3"}}', + '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 2}, "rhsm": {"version": "8.3"}, "owner_id": "cccccccc-0000-0000-0001-000000000004"}', 'puptoo', '{}', 'org_1', '[{"id": "inventory-group-1", "name": "group1"}]'), ('00000000000000000000000000000005', '00000000-0000-0000-0005-000000000001', '1', '00000000-0000-0000-0000-000000000005', '[{"key": "k1", "value": "val1", "namespace": "ns1"}]', - '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 3}, "rhsm": {"version": "8.3"}}', + '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 3}, "rhsm": {"version": "8.3"}, "owner_id": "cccccccc-0000-0000-0001-000000000005"}', 'puptoo', '{}', 'org_1', '[{"id": "inventory-group-1", "name": "group1"}]'), ('00000000000000000000000000000006', '00000000-0000-0000-0006-000000000001', '1', '00000000-0000-0000-0000-000000000006', '[{"key": "k1", "value": "val1", "namespace": "ns1"}]', '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 7, "minor": 3}, "rhsm": {"version": "7.3"}, "mssql": { "version": "15.3.0"}}', 'puptoo', '{}', 'org_1', '[{"id": "inventory-group-1", "name": "group1"}]'), ('00000000000000000000000000000007', '00000000-0000-0000-0007-000000000001', '1', '00000000-0000-0000-0000-000000000007','[{"key": "k1", "value": "val1", "namespace": "ns1"}]', - '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": "x"}, "rhsm": {"version": "8.x"}, "ansible": {"controller_version": "1.0"}}', + '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": "x"}, "rhsm": {"version": "8.x"}, "ansible": {"controller_version": "1.0"}, "owner_id": "cccccccc-0000-0000-0001-000000000007"}', 'puptoo', '{}', 'org_1', '[{"id": "inventory-group-2", "name": "group2"}]'), ('00000000000000000000000000000008', '00000000-0000-0000-0008-000000000001', '1', '00000000-0000-0000-0000-000000000008', '[{"key": "k1", "value": "val1", "namespace": "ns1"}]', - '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 3}, "rhsm": {"version": "8.3"}}', + '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 3}, "rhsm": {"version": "8.3"}, "owner_id": "cccccccc-0000-0000-0001-000000000008"}', 'puptoo', '{}', 'org_1', '[{"id": "inventory-group-2", "name": "group2"}]'), ('00000000000000000000000000000009', '00000000-0000-0000-0009-000000000001', '2', '00000000-0000-0000-0000-000000000009', '[{"key": "k1", "value": "val1", "namespace": "ns1"}]', '2018-09-22 12:00:00-04', '2018-08-26 12:00:00-04', '2018-08-26 12:00:00-04', '{"sap_system": true, "operating_system": {"name": "RHEL", "major": 8, "minor": 1}, "rhsm": {"version": "8.1"}}', From 1b76f4b816cac7d7ade149cc5d3cd6480fa82fd7 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Tue, 3 Sep 2024 14:08:54 +0200 Subject: [PATCH 6/9] RHINENG-9505: reevaluate system added/removed from template --- manager/config/config.go | 2 ++ manager/controllers/template_systems_delete.go | 11 +++++++---- manager/controllers/template_systems_update.go | 12 +++++++----- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/manager/config/config.go b/manager/config/config.go index 0c38d97cc..fb1fe4e39 100644 --- a/manager/config/config.go +++ b/manager/config/config.go @@ -29,6 +29,8 @@ var ( // Send recalc message for systems which have been assigned to a different baseline EnableBaselineChangeEval = utils.PodConfig.GetBool("baseline_change_eval", true) + // Send recalc message for systems which have been assigned to a different template + EnableTemplateChangeEval = utils.PodConfig.GetBool("template_change_eval", true) // Honor rbac permissions (can be disabled for tests) EnableRBACCHeck = utils.PodConfig.GetBool("rbac", true) diff --git a/manager/controllers/template_systems_delete.go b/manager/controllers/template_systems_delete.go index f7622c3ad..0770eef22 100644 --- a/manager/controllers/template_systems_delete.go +++ b/manager/controllers/template_systems_delete.go @@ -2,6 +2,8 @@ package controllers import ( "app/base/utils" + "app/manager/config" + "app/manager/kafka" "app/manager/middlewares" "net/http" @@ -43,9 +45,10 @@ func TemplateSystemsDeleteHandler(c *gin.Context) { return } - // TODO: re-evaluate systems removed from templates - // inventoryAIDs := kafka.InventoryIDs2InventoryAIDs(account, req.Systems) - // kafka.EvaluateBaselineSystems(inventoryAIDs) - + // re-evaluate systems removed from templates + if config.EnableTemplateChangeEval { + inventoryAIDs := kafka.InventoryIDs2InventoryAIDs(account, req.Systems) + kafka.EvaluateBaselineSystems(inventoryAIDs) + } c.Status(http.StatusOK) } diff --git a/manager/controllers/template_systems_update.go b/manager/controllers/template_systems_update.go index f2f940000..bea2c3350 100644 --- a/manager/controllers/template_systems_update.go +++ b/manager/controllers/template_systems_update.go @@ -7,6 +7,7 @@ import ( "app/base/models" "app/base/utils" "app/manager/config" + "app/manager/kafka" "app/manager/middlewares" "context" "fmt" @@ -69,10 +70,11 @@ func TemplateSystemsUpdateHandler(c *gin.Context) { return } - // TODO: re-evaluate systems added/removed from templates - // inventoryAIDs := kafka.InventoryIDs2InventoryAIDs(account, req.InventoryIDs) - // kafka.EvaluateBaselineSystems(inventoryAIDs) - + // re-evaluate systems added/removed from templates + if config.EnableTemplateChangeEval { + inventoryAIDs := kafka.InventoryIDs2InventoryAIDs(account, req.Systems) + kafka.EvaluateBaselineSystems(inventoryAIDs) + } c.Status(http.StatusOK) } @@ -219,7 +221,7 @@ func assignCandlepinEnvironment(c context.Context, db *gorm.DB, accountID int, e } resp, apiErr := callCandlepin(c, *consumer.Consumer, &updateReq) // check response - if err != nil { + if apiErr != nil { err = errors2.Join(err, apiErr, errors.New(resp.Message)) } } From 5548a65b6598570eaf92bb3dd48ca0d7ee3b612d Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Thu, 5 Sep 2024 10:56:09 +0200 Subject: [PATCH 7/9] RHINENG-9505: vmaas updates for template system are applicable if a systems has template updates reported by yum_updates are installable updates reported by vmaas are applicable --- evaluator/evaluate.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evaluator/evaluate.go b/evaluator/evaluate.go index 8af76c84c..c2905389d 100644 --- a/evaluator/evaluate.go +++ b/evaluator/evaluate.go @@ -323,8 +323,8 @@ func getUpdatesData(ctx context.Context, system *models.SystemPlatform) (*vmaas. utils.LogWarn("Vmaas response error, continuing with yum updates only", vmaasErr.Error()) } - if system.SatelliteManaged { - // satellite managed systems has vmaas updates APPLICABLE instead of INSTALLABLE + if system.SatelliteManaged || system.TemplateID != nil { + // satellite managed systems and systems using template has vmaas updates APPLICABLE instead of INSTALLABLE mergedUpdateList := vmaasData.GetUpdateList() for nevra := range mergedUpdateList { (*mergedUpdateList[nevra]).SetUpdatesInstallability(APPLICABLE) From 0acc23ef6189d533390e24ed497a11afe58c5a67 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Mon, 9 Sep 2024 14:59:09 +0200 Subject: [PATCH 8/9] RHINENG-9505: parse response only if not empty --- base/api/client.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/base/api/client.go b/base/api/client.go index 96f8d81a1..6bab2de53 100644 --- a/base/api/client.go +++ b/base/api/client.go @@ -44,9 +44,11 @@ func (o *Client) Request(ctx *context.Context, method, url string, return httpResp, errors.Wrap(err, "Response body reading failed") } - err = json.Unmarshal(bodyBytes, responseOutPtr) - if err != nil { - return httpResp, errors.Wrap(err, "Response json parsing failed") + if len(bodyBytes) > 0 { + err = json.Unmarshal(bodyBytes, responseOutPtr) + if err != nil { + return httpResp, errors.Wrap(err, "Response json parsing failed") + } } return httpResp, nil } From 8c33cc43c5a086364aa720b712b53ef173589b29 Mon Sep 17 00:00:00 2001 From: Michael Mraka Date: Mon, 9 Sep 2024 16:06:30 +0200 Subject: [PATCH 9/9] RHINENG-9505: use the same permission as content-sources /minor --- manager/middlewares/rbac.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manager/middlewares/rbac.go b/manager/middlewares/rbac.go index e809143b7..697b0bab5 100644 --- a/manager/middlewares/rbac.go +++ b/manager/middlewares/rbac.go @@ -32,8 +32,8 @@ var granularPerms = map[string]string{ "BaselineUpdateHandler": "patch:template:write", "BaselineDeleteHandler": "patch:template:write", "BaselineSystemsRemoveHandler": "patch:template:write", - "TemplateSystemsUpdateHandler": "patch:template:write", - "TemplateSystemsDeleteHandler": "patch:template:write", + "TemplateSystemsUpdateHandler": "content-sources:templates:write", + "TemplateSystemsDeleteHandler": "content-sources:templates:write", "SystemDeleteHandler": "patch:system:write", } @@ -46,7 +46,7 @@ func makeClient(identity string) *api.Client { } if rbacURL == "" { rbacURL = utils.FailIfEmpty(utils.CoreCfg.RbacAddress, "RBAC_ADDRESS") + base.RBACApiPrefix + - "/access/?application=patch,inventory" + "/access/?application=patch,inventory,content-sources" } return &client }