use of org.folio.okapi.bean.ModuleDescriptor in project okapi by folio-org.
the class ModuleManager method checkAllConflicts.
/**
* Check a module list for conflicts.
*
* @param modlist modules to be checked
* @return error message listing conflicts, or "" if no problems
*/
public String checkAllConflicts(Map<String, ModuleDescriptor> modlist) {
// interface name to module name
Map<String, String> provs = new HashMap<>();
StringBuilder conflicts = new StringBuilder();
for (ModuleDescriptor md : modlist.values()) {
InterfaceDescriptor[] provides = md.getProvidesList();
for (InterfaceDescriptor mi : provides) {
if (mi.isRegularHandler()) {
String confl = provs.get(mi.getId());
if (confl == null || confl.isEmpty()) {
provs.put(mi.getId(), md.getId());
} else {
String msg = "Interface " + mi.getId() + " is provided by " + md.getId() + " and " + confl + ". ";
conflicts.append(msg);
}
}
}
}
logger.debug("checkAllConflicts: " + conflicts.toString());
return conflicts.toString();
}
use of org.folio.okapi.bean.ModuleDescriptor in project okapi by folio-org.
the class ModuleManager method resolveModuleConflicts.
private int resolveModuleConflicts(ModuleDescriptor md, Map<String, ModuleDescriptor> modsEnabled, List<TenantModuleDescriptor> tml, List<ModuleDescriptor> fromModule) {
int v = 0;
Iterator<String> it = modsEnabled.keySet().iterator();
while (it.hasNext()) {
String runningmodule = it.next();
ModuleDescriptor rm = modsEnabled.get(runningmodule);
if (md.getProduct().equals(rm.getProduct())) {
logger.info("resolveModuleConflicts from " + runningmodule);
fromModule.add(rm);
modsEnabled.remove(runningmodule);
it = modsEnabled.keySet().iterator();
v++;
} else {
for (InterfaceDescriptor pi : rm.getProvidesList()) {
if (pi.isRegularHandler()) {
String confl = pi.getId();
for (InterfaceDescriptor mi : md.getProvidesList()) {
if (mi.getId().equals(confl) && mi.isRegularHandler() && modsEnabled.containsKey(runningmodule)) {
logger.info("resolveModuleConflicts remove " + runningmodule);
TenantModuleDescriptor tm = new TenantModuleDescriptor();
tm.setAction("disable");
tm.setId(runningmodule);
tml.add(tm);
modsEnabled.remove(runningmodule);
it = modsEnabled.keySet().iterator();
v++;
}
}
}
}
}
}
return v;
}
use of org.folio.okapi.bean.ModuleDescriptor in project okapi by folio-org.
the class ModuleManager method removeModuleDependencies.
public int removeModuleDependencies(ModuleDescriptor md, Map<String, ModuleDescriptor> modsEnabled, List<TenantModuleDescriptor> tml) {
int sum = 0;
logger.info("removeModuleDependencies " + md.getId());
if (!modsEnabled.containsKey(md.getId())) {
return 0;
}
InterfaceDescriptor[] provides = md.getProvidesList();
for (InterfaceDescriptor prov : provides) {
if (prov.isRegularHandler()) {
Iterator<String> it = modsEnabled.keySet().iterator();
while (it.hasNext()) {
String runningmodule = it.next();
ModuleDescriptor rm = modsEnabled.get(runningmodule);
InterfaceDescriptor[] requires = rm.getRequiresList();
for (InterfaceDescriptor ri : requires) {
if (prov.getId().equals(ri.getId())) {
sum += removeModuleDependencies(rm, modsEnabled, tml);
it = modsEnabled.keySet().iterator();
}
}
}
}
}
modsEnabled.remove(md.getId());
TenantModuleDescriptor tm = new TenantModuleDescriptor();
tm.setAction("disable");
tm.setId(md.getId());
tml.add(tm);
return sum + 1;
}
use of org.folio.okapi.bean.ModuleDescriptor in project okapi by folio-org.
the class ProxyService method callSystemInterface.
/**
* Make a request to a system interface, like _tenant. Part 1: Check that we
* are working as the right tenant, and if not so, change identity to the
* correct one.
*
* @param tenant to make the request for
* @param inst carries the moduleDescriptor, RoutingEntry, and getPath to be
* called
* @param request body to send in the request
* @param pc ProxyContext for logging, and returning resp headers
* @param fut Callback with the OkapiClient that contains the body, headers,
* and/or errors
*/
public void callSystemInterface(Tenant tenant, ModuleInstance inst, String request, ProxyContext pc, Handler<ExtendedAsyncResult<OkapiClient>> fut) {
// the tenant we are about to enable
String tenantId = tenant.getId();
// is often the supertenant
String curTenantId = pc.getTenant();
String authToken = pc.getCtx().request().headers().get(XOkapiHeaders.TOKEN);
pc.debug("callSystemInterface on " + Json.encode(inst) + " for " + tenantId + " as " + curTenantId + " with authToken " + authToken);
if (tenantId.equals(curTenantId)) {
pc.debug("callSystemInterface: Same tenant, no need for trickery");
doCallSystemInterface(tenantId, authToken, inst, null, request, pc, fut);
return;
}
// Check if the actual tenant has auth enabled. If yes, get a token for it.
// If we have auth for current (super)tenant is irrelevant here!
pc.debug("callSystemInterface: Checking if " + tenantId + " has auth");
moduleManager.getEnabledModules(tenant, mres -> {
if (mres.failed()) {
// Should not happen
pc.warn("callSystemInterface: getEnabledModules failed: ", mres.cause());
fut.handle(new Failure<>(mres.getType(), mres.cause()));
return;
}
List<ModuleDescriptor> enabledModules = mres.result();
for (ModuleDescriptor md : enabledModules) {
RoutingEntry[] filters = md.getFilters();
if (filters != null) {
for (RoutingEntry filt : filters) {
if ("auth".equals(filt.getPhase())) {
pc.debug("callSystemInterface: Found auth filter in " + md.getId());
authForSystemInterface(md, filt, tenantId, inst, request, pc, fut);
return;
}
}
}
}
pc.debug("callSystemInterface: No auth for " + tenantId + " calling with tenant header only");
doCallSystemInterface(tenantId, null, inst, null, request, pc, fut);
});
}
use of org.folio.okapi.bean.ModuleDescriptor in project okapi by folio-org.
the class ProxyService method proxy.
public void proxy(RoutingContext ctx) {
ctx.request().pause();
ReadStream<Buffer> stream = ctx.request();
// Pause the request data stream before doing any slow ops, otherwise
// it will get read into a buffer somewhere.
ProxyContext pc = new ProxyContext(ctx);
// It would be nice to pass the request-id to the client, so it knows what
// to look for in Okapi logs. But that breaks the schemas, and RMB-based
// modules will not accept the response. Maybe later...
String tenantId = tenantHeader(pc);
if (tenantId == null) {
stream.resume();
// Error code already set in ctx
return;
}
sanitizeAuthHeaders(ctx.request().headers());
tenantManager.get(tenantId, gres -> {
if (gres.failed()) {
stream.resume();
pc.responseText(400, "No such Tenant " + tenantId);
return;
}
Tenant tenant = gres.result();
moduleManager.getEnabledModules(tenant, mres -> {
if (mres.failed()) {
stream.resume();
pc.responseError(mres.getType(), mres.cause());
return;
}
List<ModuleDescriptor> enabledModules = mres.result();
String metricKey = "proxy." + tenantId + "." + ctx.request().method() + "." + ctx.normalisedPath();
DropwizardHelper.markEvent(metricKey);
List<ModuleInstance> l = getModulesForRequest(pc, enabledModules);
if (l == null) {
stream.resume();
// ctx already set up
return;
}
pc.setModList(l);
pc.logRequest(ctx, tenantId);
ctx.request().headers().add(XOkapiHeaders.URL, okapiUrl);
ctx.request().headers().remove(XOkapiHeaders.MODULE_ID);
resolveUrls(l.iterator(), res -> {
if (res.failed()) {
stream.resume();
pc.responseError(res.getType(), res.cause());
} else {
proxyR(l.iterator(), pc, stream, null);
}
});
});
});
}
Aggregations