Description
Summary
In wso2/carbon-apimgt FederatedAPIDiscoveryRunner.java, the scheduled discovery tick only runs
reconciliation (processDiscoveredAPIs) when the current tick returns a
non-empty API list. When the third-party gateway reports zero APIs, the
else branch fires and reconciliation is skipped entirely — so the
diff-and-undeploy logic never executes and every previously-imported API is
left in place indefinitely.
Where reconciliation lives
processDiscoveredAPIs() (called from FederatedAPIDiscoveryRunner.java:145-146,
implemented at lines 190-368) does contain a real diff/reconcile mechanism:
- Fetches the set of APIs currently known as federated-discovered for that
environment/org from the DB (alreadyDiscoveredAPIsList, via
AM_DEPLOYMENT_REVISION_MAPPING / AM_REVISION / AM_API where
INITIATED_FROM_GW=1).
- Walks the freshly
discoverAPI()-returned list, importing/updating each one
and tracking every key seen (discoveredAPIsFromFederatedGW).
- At lines 340-357, diffs the two: any API in
alreadyDiscoveredAPIsList but
not in discoveredAPIsFromFederatedGW gets
FederatedGatewayUtil.deleteDeployment(...) called on it.
So per-API removal detection genuinely exists — but only inside this method,
and only when the current tick's discoveredAPIs is non-empty.
The bug
if (discoveredAPIs != null && !discoveredAPIs.isEmpty()) {
... processDiscoveredAPIs(...) // reconcile runs
} else {
log.debug(...) // reconcile is SKIPPED entirely
}
If the third-party gateway ends up with zero APIs (all deleted, gateway
decommissioned, or even a transient connectivity blip that makes discoverAPI()
return empty/null), the else branch fires and processDiscoveredAPIs never
runs — so the diff-and-undeploy logic at lines 340-357 never executes. Every
previously-imported API is left exactly as it was, indefinitely.
Impact
- Orphaned/stale API entries remain published after the source gateway removes
them or goes away.
- A transient connectivity blip returning empty/null can be
indistinguishable from a legitimate "all APIs removed" state, but is treated
as a no-op regardless.
Expected behavior
Reconciliation should run even when discoverAPI() returns an empty list, so
that APIs removed at the source are undeployed. (Empty vs. null / error should
be distinguished so a transient failure does not mass-undeploy healthy APIs.)
Screenshots
1. Guard that skips reconciliation (FederatedAPIDiscoveryRunner.java)
2. Discovered API left published in the UI (PetStore :1.0.0)
Steps to Reproduce
Steps to reproduce
- Connect a third-party (federated) gateway to the environment/org.
- Wait for the scheduled discovery to run and import APIs — confirm at least
one API shows up as a discovered/imported API (e.g. PetStore :1.0.0,
"Discovered API - AWS", Published).
- On the third-party gateway, remove all the APIs in one go (so the next
discoverAPI() call returns an empty/null list).
- Wait for the next scheduled discovery tick.
Expected result
Reconciliation runs, detects that all previously-discovered APIs are gone from
the source, and undeploys/removes them.
Actual result
Because discoveredAPIs is empty, the else branch fires and
processDiscoveredAPIs never runs. The diff-and-undeploy logic (lines 340-357)
never executes, and every previously-imported API remains published
indefinitely.
Version
4.7.0
Environment Details (with versions)
JDK: 21.0.11-tem
OS: MacOS
Third party gateway: AWS
Description
Summary
In wso2/carbon-apimgt
FederatedAPIDiscoveryRunner.java, the scheduled discovery tick only runsreconciliation (
processDiscoveredAPIs) when the current tick returns anon-empty API list. When the third-party gateway reports zero APIs, the
elsebranch fires and reconciliation is skipped entirely — so thediff-and-undeploy logic never executes and every previously-imported API is
left in place indefinitely.
Where reconciliation lives
processDiscoveredAPIs()(called fromFederatedAPIDiscoveryRunner.java:145-146,implemented at lines 190-368) does contain a real diff/reconcile mechanism:
environment/org from the DB (
alreadyDiscoveredAPIsList, viaAM_DEPLOYMENT_REVISION_MAPPING/AM_REVISION/AM_APIwhereINITIATED_FROM_GW=1).discoverAPI()-returned list, importing/updating each oneand tracking every key seen (
discoveredAPIsFromFederatedGW).alreadyDiscoveredAPIsListbutnot in
discoveredAPIsFromFederatedGWgetsFederatedGatewayUtil.deleteDeployment(...)called on it.So per-API removal detection genuinely exists — but only inside this method,
and only when the current tick's
discoveredAPIsis non-empty.The bug
If the third-party gateway ends up with zero APIs (all deleted, gateway
decommissioned, or even a transient connectivity blip that makes
discoverAPI()return empty/null), the
elsebranch fires andprocessDiscoveredAPIsneverruns — so the diff-and-undeploy logic at lines 340-357 never executes. Every
previously-imported API is left exactly as it was, indefinitely.
Impact
them or goes away.
indistinguishable from a legitimate "all APIs removed" state, but is treated
as a no-op regardless.
Expected behavior
Reconciliation should run even when
discoverAPI()returns an empty list, sothat APIs removed at the source are undeployed. (Empty vs. null / error should
be distinguished so a transient failure does not mass-undeploy healthy APIs.)
Screenshots
1. Guard that skips reconciliation (
FederatedAPIDiscoveryRunner.java)2. Discovered API left published in the UI (PetStore :1.0.0)
Steps to Reproduce
Steps to reproduce
one API shows up as a discovered/imported API (e.g.
PetStore :1.0.0,"Discovered API - AWS", Published).
discoverAPI()call returns an empty/null list).Expected result
Reconciliation runs, detects that all previously-discovered APIs are gone from
the source, and undeploys/removes them.
Actual result
Because
discoveredAPIsis empty, theelsebranch fires andprocessDiscoveredAPIsnever runs. The diff-and-undeploy logic (lines 340-357)never executes, and every previously-imported API remains published
indefinitely.
Version
4.7.0
Environment Details (with versions)
JDK: 21.0.11-tem
OS: MacOS
Third party gateway: AWS