From 323b71d8be692c790580700110a983f45291fc10 Mon Sep 17 00:00:00 2001 From: Ken Zangelin Date: Wed, 4 Sep 2024 07:55:47 +0200 Subject: [PATCH] Support for management::localOnly in registrations --- CHANGES_NEXT_RELEASE | 1 + src/lib/orionld/distOp/distOpSend.cpp | 6 +- src/lib/orionld/regCache/regCacheItemAdd.cpp | 8 + .../regMatch/regMatchForEntitiesQuery.cpp | 2 - .../orionldPatchRegistration.cpp | 8 + src/lib/orionld/types/RegCacheItem.h | 1 + .../ngsild_reg-with-localOnly.test | 425 ++++++++++++++++++ 7 files changed, 446 insertions(+), 5 deletions(-) create mode 100644 test/functionalTest/cases/0000_ngsild/ngsild_reg-with-localOnly.test diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 48ec5fb936..16ceae5883 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -7,6 +7,7 @@ - Also supporting sorting on entity id, type, and modifiedAt - One more URL parameter '?reverse=true' to reverse the sorting order * Support for GET /ngsi-ld/v1/info/sourceIdentity + * Support for management::localOnly in registrations ## Notes * Lots of improvements for subordinate subscriptions - still not 100% ready, but a lot better. diff --git a/src/lib/orionld/distOp/distOpSend.cpp b/src/lib/orionld/distOp/distOpSend.cpp index d7bb2280d1..d54cb048e5 100644 --- a/src/lib/orionld/distOp/distOpSend.cpp +++ b/src/lib/orionld/distOp/distOpSend.cpp @@ -498,9 +498,6 @@ bool distOpSend(DistOp* distOpP, const char* dateHeader, const char* xForwardedF uriParamAdd(&urlParts, "id", distOpP->entityId, -1); } - if (local == true) - uriParamAdd(&urlParts, "local=true", NULL, 10); - if (distOpP->qNode != NULL) { char buf[256]; @@ -520,6 +517,9 @@ bool distOpSend(DistOp* distOpP, const char* dateHeader, const char* xForwardedF } } + if ((local == true) || (distOpP->regP->localOnly == true)) + uriParamAdd(&urlParts, "local=true", NULL, 10); + if (orionldState.uriParams.lang != NULL) uriParamAdd(&urlParts, "lang", orionldState.uriParams.lang, -1); diff --git a/src/lib/orionld/regCache/regCacheItemAdd.cpp b/src/lib/orionld/regCache/regCacheItemAdd.cpp index bca737d980..d95aee8908 100644 --- a/src/lib/orionld/regCache/regCacheItemAdd.cpp +++ b/src/lib/orionld/regCache/regCacheItemAdd.cpp @@ -193,10 +193,18 @@ RegCacheItem* regCacheItemAdd(RegCache* rcP, const char* registrationId, KjNode* KjNode* operationsP = kjLookup(rciP->regTree, "operations"); KjNode* modeP = kjLookup(rciP->regTree, "mode"); KjNode* informationP = kjLookup(rciP->regTree, "information"); + KjNode* managementP = kjLookup(rciP->regTree, "management"); rciP->opMask = distOpTypeMask(operationsP); rciP->mode = (modeP != NULL)? registrationMode(modeP->value.s) : RegModeInclusive; + if (managementP != NULL) + { + KjNode* localOnlyP = kjLookup(managementP, "localOnly"); + + rciP->localOnly = (localOnlyP != NULL)? localOnlyP->value.b : false; + } + if (regCacheIdPatternRegexCompile(rciP, informationP) == false) LM_X(1, ("Internal Error (if this happens it's a SW bug of Orion-LD - the idPattern was checked in pcheckEntityInfo and all was OK")); diff --git a/src/lib/orionld/regMatch/regMatchForEntitiesQuery.cpp b/src/lib/orionld/regMatch/regMatchForEntitiesQuery.cpp index f5fbbe0fb8..ecb762a887 100644 --- a/src/lib/orionld/regMatch/regMatchForEntitiesQuery.cpp +++ b/src/lib/orionld/regMatch/regMatchForEntitiesQuery.cpp @@ -54,10 +54,8 @@ DistOp* regMatchForEntitiesQuery { DistOp* distOpList = NULL; - LM_W(("Looping over regCache of tenant '%s' (cache at %p, first reg at %p)", orionldState.tenantP->mongoDbName, orionldState.tenantP->regCache, orionldState.tenantP->regCache->regList)); for (RegCacheItem* regP = orionldState.tenantP->regCache->regList; regP != NULL; regP = regP->next) { - LM_W(("In Loop")); if ((regP->mode & regMode) == 0) { LM_T(LmtRegMatch, ("%s: No Reg Match due to RegistrationMode ('%s' vs '%s')", regP->regId, registrationModeToString(regP->mode), registrationModeToString(regMode))); diff --git a/src/lib/orionld/serviceRoutines/orionldPatchRegistration.cpp b/src/lib/orionld/serviceRoutines/orionldPatchRegistration.cpp index 766ca01cd7..c59b309767 100644 --- a/src/lib/orionld/serviceRoutines/orionldPatchRegistration.cpp +++ b/src/lib/orionld/serviceRoutines/orionldPatchRegistration.cpp @@ -763,6 +763,7 @@ bool orionldPatchRegistration(void) KjNode* operationsP = kjLookup(rciP->regTree, "operations"); KjNode* modeP = kjLookup(rciP->regTree, "mode"); KjNode* informationP = kjLookup(rciP->regTree, "information"); + KjNode* managementP = kjLookup(rciP->regTree, "management"); rciP->mode = (modeP != NULL)? registrationMode(modeP->value.s) : RegModeInclusive; @@ -775,6 +776,13 @@ bool orionldPatchRegistration(void) LM_X(1, ("Internal Error (if this happens it's a bug of Orion-LD - the idPattern was checked in pcheckEntityInfo and all OK")); } + if (managementP != NULL) + { + KjNode* localOnlyP = kjLookup(managementP, "localOnly"); + + rciP->localOnly = (localOnlyP != NULL)? localOnlyP->value.b : false; + } + if (lmTraceIsSet(LmtRegCache)) regCachePresent(); diff --git a/src/lib/orionld/types/RegCacheItem.h b/src/lib/orionld/types/RegCacheItem.h index 5210f03562..60143ebdaf 100644 --- a/src/lib/orionld/types/RegCacheItem.h +++ b/src/lib/orionld/types/RegCacheItem.h @@ -71,6 +71,7 @@ typedef struct RegCacheItem char* ipAndPort; // IP:port - for X-Forwarded-For RegIdPattern* idPatternRegexList; char* hostAlias; // Broker identity - for the Via header (replacing X-Forwarded-For) + bool localOnly; // Forwarded reqs to include local=true if this field is true struct RegCacheItem* next; } RegCacheItem; diff --git a/test/functionalTest/cases/0000_ngsild/ngsild_reg-with-localOnly.test b/test/functionalTest/cases/0000_ngsild/ngsild_reg-with-localOnly.test new file mode 100644 index 0000000000..77cc7f79a2 --- /dev/null +++ b/test/functionalTest/cases/0000_ngsild/ngsild_reg-with-localOnly.test @@ -0,0 +1,425 @@ +# Copyright 2024 FIWARE Foundation e.V. +# +# This file is part of Orion-LD Context Broker. +# +# Orion-LD Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion-LD Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# orionld at fiware dot org + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Looking for a bug in the reg cache + +--SHELL-INIT-- +dbInit CB +dbInit CP1 +dbInit CP2 +orionldStart CB -forwarding -experimental -wip entityMaps,distSubs +orionldStart CP1 -forwarding -experimental -wip entityMaps,distSubs +orionldStart CP2 -forwarding -experimental -wip entityMaps,distSubs + +--SHELL-- + +# +# 01. Create a registration R1 on CB for CP1, with management::localOnly=true +# 02. Create a registration R2 on CP1 for CP2 +# 03. Create an entity E1 on CB +# 04. Create an entity E2 on CP1 +# 05. Create an entity E3 on CP2 +# 06. GET entities on CB - see E1+E2 +# 07. Patch R1 on CB, setting management::localOnly=false +# 08. GET entities on CB - see E1+E2+E3 +# 09. Remove R1 +# 10. Re-create R1 on CB, without management::localOnly +# 11. GET entities on CB - see E1+E2+E3 +# 12. Patch R1 on CB, setting management::localOnly=true +# 13. GET entities on CB - see E1+E2 +# + + +echo "01. Create a registration R1 on CB for CP1, with management::localOnly=true" +echo "===========================================================================" +payload='{ + "id": "urn:R1", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "type": "T" + } + ] + } + ], + "endpoint": "http://localhost:'$CP1_PORT'", + "management": { + "localOnly": true + } +}' +orionCurl --url /ngsi-ld/v1/csourceRegistrations --payload "$payload" +echo +echo + + +echo "02. Create a registration R2 on CP1 for CP2" +echo "===========================================" +payload='{ + "id": "urn:R2", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "type": "T" + } + ] + } + ], + "endpoint": "http://localhost:'$CP2_PORT'" +}' +orionCurl --url /ngsi-ld/v1/csourceRegistrations --payload "$payload" --port $CP1_PORT +echo +echo + + + +echo "03. Create an entity E1 on CB" +echo "=============================" +payload='{ + "id": "urn:E1", + "type": "T", + "P1": 1 +}' +orionCurl --url /ngsi-ld/v1/entities --payload "$payload" +echo +echo + + +echo "04. Create an entity E2 on CP1" +echo "==============================" +payload='{ + "id": "urn:E2", + "type": "T", + "P1": 1 +}' +orionCurl --url /ngsi-ld/v1/entities --payload "$payload" --port $CP1_PORT +echo +echo + + +echo "05. Create an entity E3 on CP2" +echo "==============================" +payload='{ + "id": "urn:E3", + "type": "T", + "P1": 1 +}' +orionCurl --url /ngsi-ld/v1/entities --payload "$payload" --port $CP2_PORT +echo +echo + + +echo "06. GET entities on CB - see E1+E2" +echo "==================================" +orionCurl --url /ngsi-ld/v1/entities?type=T +echo +echo + + +echo "07. Patch R1 on CB, setting management::localOnly=false" +echo "=======================================================" +payload='{ + "management": { + "localOnly": false + } +}' +orionCurl --url /ngsi-ld/v1/csourceRegistrations/urn:R1 --payload "$payload" -X PATCH +echo +echo + + +echo "08. GET entities on CB - see E1+E2+E3" +echo "=====================================" +orionCurl --url /ngsi-ld/v1/entities?type=T +echo +echo + + +echo "09. Remove R1" +echo "=============" +orionCurl --url /ngsi-ld/v1/csourceRegistrations/urn:R1 -X DELETE +echo +echo + + +echo "10. Re-create R1 on CB, without management::localOnly" +echo "=====================================================" +payload='{ + "id": "urn:R1", + "type": "ContextSourceRegistration", + "information": [ + { + "entities": [ + { + "type": "T" + } + ] + } + ], + "endpoint": "http://localhost:'$CP1_PORT'" +}' +orionCurl --url /ngsi-ld/v1/csourceRegistrations --payload "$payload" +echo +echo + + +echo "11. GET entities on CB - see E1+E2+E3" +echo "=====================================" +orionCurl --url /ngsi-ld/v1/entities?type=T +echo +echo + + +echo "12. Patch R1 on CB, setting management::localOnly=true" +echo "======================================================" +payload='{ + "management": { + "localOnly": true + } +}' +orionCurl --url /ngsi-ld/v1/csourceRegistrations/urn:R1 --payload "$payload" -X PATCH +echo +echo + + +echo "13. GET entities on CB - see E1+E2" +echo "==================================" +orionCurl --url /ngsi-ld/v1/entities?type=T +echo +echo + + +--REGEXPECT-- +01. Create a registration R1 on CB for CP1, with management::localOnly=true +=========================================================================== +HTTP/1.1 201 Created +Content-Length: 0 +Date: REGEX(.*) +Location: /ngsi-ld/v1/csourceRegistrations/urn:R1 + + + +02. Create a registration R2 on CP1 for CP2 +=========================================== +HTTP/1.1 201 Created +Content-Length: 0 +Date: REGEX(.*) +Location: /ngsi-ld/v1/csourceRegistrations/urn:R2 + + + +03. Create an entity E1 on CB +============================= +HTTP/1.1 201 Created +Content-Length: 0 +Date: REGEX(.*) +Location: /ngsi-ld/v1/entities/urn:E1 + + + +04. Create an entity E2 on CP1 +============================== +HTTP/1.1 201 Created +Content-Length: 0 +Date: REGEX(.*) +Location: /ngsi-ld/v1/entities/urn:E2 + + + +05. Create an entity E3 on CP2 +============================== +HTTP/1.1 201 Created +Content-Length: 0 +Date: REGEX(.*) +Location: /ngsi-ld/v1/entities/urn:E3 + + + +06. GET entities on CB - see E1+E2 +================================== +HTTP/1.1 200 OK +Content-Length: 125 +Content-Type: application/json +Date: REGEX(.*) +Link: