NIFI-3762:

- Addressing issue when enabling/disabling controller services when referencing services are not in scope.
- Fixing enabled/disabled icons for referencing services.
- Rendering when a reference cycle is detected.

Signed-off-by: Scott Aslan <scottyaslan@gmail.com>

This closes #1725
This commit is contained in:
Matt Gilman 2017-05-01 15:32:46 -04:00 committed by Scott Aslan
parent 3bfe323a5d
commit 82829927ae
4 changed files with 73 additions and 33 deletions

View File

@ -62,7 +62,6 @@ import org.apache.nifi.connectable.Connection;
import org.apache.nifi.connectable.Funnel; import org.apache.nifi.connectable.Funnel;
import org.apache.nifi.connectable.Port; import org.apache.nifi.connectable.Port;
import org.apache.nifi.controller.ConfiguredComponent; import org.apache.nifi.controller.ConfiguredComponent;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.Counter; import org.apache.nifi.controller.Counter;
import org.apache.nifi.controller.FlowController; import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ProcessorNode; import org.apache.nifi.controller.ProcessorNode;
@ -85,7 +84,6 @@ import org.apache.nifi.groups.RemoteProcessGroup;
import org.apache.nifi.history.History; import org.apache.nifi.history.History;
import org.apache.nifi.history.HistoryQuery; import org.apache.nifi.history.HistoryQuery;
import org.apache.nifi.history.PreviousValue; import org.apache.nifi.history.PreviousValue;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.remote.RootGroupPort; import org.apache.nifi.remote.RootGroupPort;
import org.apache.nifi.reporting.Bulletin; import org.apache.nifi.reporting.Bulletin;
import org.apache.nifi.reporting.BulletinQuery; import org.apache.nifi.reporting.BulletinQuery;
@ -1981,7 +1979,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
*/ */
private ControllerServiceReferencingComponentsEntity createControllerServiceReferencingComponentsEntity( private ControllerServiceReferencingComponentsEntity createControllerServiceReferencingComponentsEntity(
final ControllerServiceReference reference, final Map<String, Revision> revisions) { final ControllerServiceReference reference, final Map<String, Revision> revisions) {
return createControllerServiceReferencingComponentsEntity(reference, revisions, new HashSet<>()); final Set<ControllerServiceNode> visited = new HashSet<>();
visited.add(reference.getReferencedComponent());
return createControllerServiceReferencingComponentsEntity(reference, revisions, visited);
} }
/** /**
@ -2016,6 +2016,9 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
// indicate if we've hit a cycle // indicate if we've hit a cycle
dto.setReferenceCycle(visited.contains(node)); dto.setReferenceCycle(visited.contains(node));
// mark node as visited before building the reference cycle
visited.add(node);
// if we haven't encountered this service before include it's referencing components // if we haven't encountered this service before include it's referencing components
if (!dto.getReferenceCycle()) { if (!dto.getReferenceCycle()) {
final ControllerServiceReference refReferences = node.getReferences(); final ControllerServiceReference refReferences = node.getReferences();
@ -2026,9 +2029,6 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
final ControllerServiceReferencingComponentsEntity references = createControllerServiceReferencingComponentsEntity(refReferences, referencingRevisions, visited); final ControllerServiceReferencingComponentsEntity references = createControllerServiceReferencingComponentsEntity(refReferences, referencingRevisions, visited);
dto.setReferencingComponents(references.getControllerServiceReferencingComponents()); dto.setReferencingComponents(references.getControllerServiceReferencingComponents());
} }
// mark node as visited
visited.add(node);
} }
componentEntities.add(entityFactory.createControllerServiceReferencingComponentEntity(dto, revisionDto, permissions)); componentEntities.add(entityFactory.createControllerServiceReferencingComponentEntity(dto, revisionDto, permissions));

View File

@ -285,9 +285,9 @@ div.ajax-complete:before {
div.ajax-error:before { div.ajax-error:before {
font-family: FontAwesome; font-family: FontAwesome;
content: "\f1f8"; content: "\f00d";
font-size: 16px; font-size: 16px;
color: #004849; color: #D18686;
} }
.refresh-button { .refresh-button {

View File

@ -91,6 +91,11 @@ div.context-menu-provenance {
text-shadow: 0 0 4px rgba(255,255,255,1); text-shadow: 0 0 4px rgba(255,255,255,1);
} }
.disabled:before {
content: '\e802';
font-family: flowfont;
}
.enabled { .enabled {
float: left; float: left;
color: #44a3cf !important; color: #44a3cf !important;
@ -100,6 +105,11 @@ div.context-menu-provenance {
text-shadow: 0 0 4px rgba(255,255,255,1); text-shadow: 0 0 4px rgba(255,255,255,1);
} }
.enabled:before {
content: '\f0e7';
font-family: FontAwesome;
}
.stopped { .stopped {
float: left; float: left;
color: #d18686 !important; color: #d18686 !important;

View File

@ -507,13 +507,19 @@
var referencingServiceReferencesContainer = $('<div class="referencing-component-references hidden"></div>'); var referencingServiceReferencesContainer = $('<div class="referencing-component-references hidden"></div>');
var serviceTwist = $('<div class="service expansion-button collapsed pointer"></div>').on('click', function () { var serviceTwist = $('<div class="service expansion-button collapsed pointer"></div>').on('click', function () {
if (serviceTwist.hasClass('collapsed')) { if (serviceTwist.hasClass('collapsed')) {
var controllerServiceGrid = serviceTable.data('gridInstance');
var controllerServiceData = controllerServiceGrid.getData();
var referencingServiceEntity = controllerServiceData.getItemById(referencingComponent.id);
var referencingService = referencingServiceEntity.component;
// create the markup for the references // create the markup for the references
createReferencingComponents(serviceTable, referencingServiceReferencesContainer, referencingService.referencingComponents); if (referencingComponent.referenceCycle === true) {
referencingServiceReferencesContainer.append('<div class="unset">Reference cycle detected.</div>');
} else {
var controllerServiceGrid = serviceTable.data('gridInstance');
var controllerServiceData = controllerServiceGrid.getData();
// get the controller service and expand its referencing services
getControllerService(referencingComponent.id, controllerServiceData).done(function (controllerServiceEntity) {
var cs = controllerServiceEntity.component;
createReferencingComponents(serviceTable, referencingServiceReferencesContainer, cs.referencingComponents);
});
}
} else { } else {
referencingServiceReferencesContainer.empty(); referencingServiceReferencesContainer.empty();
} }
@ -783,7 +789,7 @@
// Note: updated revisions will be retrieved after updateReferencingSchedulableComponents is invoked // Note: updated revisions will be retrieved after updateReferencingSchedulableComponents is invoked
// wait unil the polling of each service finished // wait until the polling of each service finished
return $.Deferred(function (deferred) { return $.Deferred(function (deferred) {
updated.done(function (response) { updated.done(function (response) {
// update the controller service // update the controller service
@ -803,8 +809,9 @@
// start polling for each controller service // start polling for each controller service
var polling = []; var polling = [];
services.forEach(function (controllerServiceId) { services.forEach(function (controllerServiceId) {
var referencingService = controllerServiceData.getItemById(controllerServiceId); getControllerService(controllerServiceId, controllerServiceData).done(function(controllerServiceEntity) {
polling.push(stopReferencingSchedulableComponents(referencingService, pollCondition)); polling.push(stopReferencingSchedulableComponents(controllerServiceEntity, pollCondition));
});
}); });
// wait until polling has finished // wait until polling has finished
@ -820,6 +827,29 @@
}).promise(); }).promise();
}; };
/**
* Gets the controller service with the specified id. If the service is present in the specified
* controllerServiceData it will be used. Otherwise it will query for it.
*
* @param controllerServiceId service id
* @param controllerServiceData service table data
* @returns {deferred} the controller service entity
*/
var getControllerService = function (controllerServiceId, controllerServiceData) {
var controllerServiceEntity = controllerServiceData.getItemById(controllerServiceId);
if (nfCommon.isDefinedAndNotNull(controllerServiceEntity)) {
return $.Deferred(function (deferred) {
deferred.resolve(controllerServiceEntity);
});
} else {
return $.ajax({
type: 'GET',
url: '../nifi-api/controller-services/' + encodeURIComponent(controllerServiceId),
dataType: 'json'
}).fail(nfErrorHandler.handleAjaxError);
}
};
/** /**
* Polls the specified services referencing components to see if the * Polls the specified services referencing components to see if the
* specified condition is satisfied. * specified condition is satisfied.
@ -890,12 +920,12 @@
* Continues to poll the specified controller service until all referencing schedulable * Continues to poll the specified controller service until all referencing schedulable
* components are stopped (not scheduled and 0 active threads). * components are stopped (not scheduled and 0 active threads).
* *
* @param {object} controllerService * @param {object} controllerServiceEntity
* @param {function} pollCondition * @param {function} pollCondition
*/ */
var stopReferencingSchedulableComponents = function (controllerService, pollCondition) { var stopReferencingSchedulableComponents = function (controllerServiceEntity, pollCondition) {
// continue to poll the service until all schedulable components have stopped // continue to poll the service until all schedulable components have stopped
return pollService(controllerService, function (service, bulletins) { return pollService(controllerServiceEntity, function (service, bulletins) {
var referencingComponents = service.referencingComponents; var referencingComponents = service.referencingComponents;
var stillRunning = false; var stillRunning = false;
@ -938,12 +968,12 @@
/** /**
* Continues to poll until all referencing services are enabled. * Continues to poll until all referencing services are enabled.
* *
* @param {object} controllerService * @param {object} controllerServiceEntity
* @param {function} pollCondition * @param {function} pollCondition
*/ */
var enableReferencingServices = function (controllerService, pollCondition) { var enableReferencingServices = function (controllerServiceEntity, pollCondition) {
// continue to poll the service until all referencing services are enabled // continue to poll the service until all referencing services are enabled
return pollService(controllerService, function (service, bulletins) { return pollService(controllerServiceEntity, function (service, bulletins) {
var referencingComponents = service.referencingComponents; var referencingComponents = service.referencingComponents;
var notEnabled = false; var notEnabled = false;
@ -983,12 +1013,12 @@
/** /**
* Continues to poll until all referencing services are disabled. * Continues to poll until all referencing services are disabled.
* *
* @param {object} controllerService * @param {object} controllerServiceEntity
* @param {function} pollCondition * @param {function} pollCondition
*/ */
var disableReferencingServices = function (controllerService, pollCondition) { var disableReferencingServices = function (controllerServiceEntity, pollCondition) {
// continue to poll the service until all referencing services are disabled // continue to poll the service until all referencing services are disabled
return pollService(controllerService, function (service, bulletins) { return pollService(controllerServiceEntity, function (service, bulletins) {
var referencingComponents = service.referencingComponents; var referencingComponents = service.referencingComponents;
var notDisabled = false; var notDisabled = false;
@ -1071,13 +1101,13 @@
// start polling for each controller service // start polling for each controller service
var polling = []; var polling = [];
services.forEach(function (controllerServiceId) { services.forEach(function (controllerServiceId) {
var referencingService = controllerServiceData.getItemById(controllerServiceId); getControllerService(controllerServiceId, controllerServiceData).done(function(controllerServiceEntity) {
if (enabled) {
if (enabled) { polling.push(enableReferencingServices(controllerServiceEntity, pollCondition));
polling.push(enableReferencingServices(referencingService, pollCondition)); } else {
} else { polling.push(disableReferencingServices(controllerServiceEntity, pollCondition));
polling.push(disableReferencingServices(referencingService, pollCondition)); }
} });
}); });
$.when.apply(window, polling).done(function () { $.when.apply(window, polling).done(function () {