NIFI-5925: Added controller services to set of components that are searched

NIFI-5925: cleanup, add negative test

NIFI-5925: fixed checkstyle

This closes #4105

Signed-off-by: Mike Thomsen <mthomsen@apache.org>
This commit is contained in:
Michael Hogue 2020-03-02 16:06:28 -05:00 committed by Mike Thomsen
parent 5fd25d6235
commit aeaf953e06
No known key found for this signature in database
GPG Key ID: 88511C3D4CAD246F
4 changed files with 189 additions and 0 deletions

View File

@ -36,6 +36,7 @@ public class SearchResultsDTO {
private List<ComponentSearchResultDTO> remoteProcessGroupResults = new ArrayList<>();
private List<ComponentSearchResultDTO> funnelResults = new ArrayList<>();
private List<ComponentSearchResultDTO> labelResults = new ArrayList<>();
private List<ComponentSearchResultDTO> controllerServiceNodeResults = new ArrayList<>();
private List<ComponentSearchResultDTO> parameterContextResults = new ArrayList<>();
private List<ComponentSearchResultDTO> parameterResults = new ArrayList<>();
@ -151,6 +152,20 @@ public class SearchResultsDTO {
this.labelResults = labelResults;
}
/**
* @return the controller service nodes that matched the search
*/
@ApiModelProperty(
value = "The controller service nodes that matched the search"
)
public List<ComponentSearchResultDTO> getControllerServiceNodeResults() {
return controllerServiceNodeResults;
}
public void setControllerServiceNodeResults(List<ComponentSearchResultDTO> controllerServiceNodeResults) {
this.controllerServiceNodeResults = controllerServiceNodeResults;
}
/**
* @return parameter contexts that matched the search.
*/

View File

@ -33,6 +33,7 @@ import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.ScheduledState;
import org.apache.nifi.controller.label.Label;
import org.apache.nifi.controller.queue.FlowFileQueue;
import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.flowfile.FlowFilePrioritizer;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.RemoteProcessGroup;
@ -175,13 +176,67 @@ public class ControllerSearchService {
}
}
for (final ControllerServiceNode controllerServiceNode : group.getControllerServices(false)) {
if (controllerServiceNode.isAuthorized(authorizer, RequestAction.READ, user)) {
final ComponentSearchResultDTO match = search(search, controllerServiceNode);
if (match != null) {
match.setGroupId(group.getIdentifier());
match.setParentGroup(buildResultGroup(group, user));
match.setVersionedGroup(buildVersionedGroup(group, user));
results.getControllerServiceNodeResults().add(match);
}
}
}
for (final ProcessGroup processGroup : group.getProcessGroups()) {
search(results, search, processGroup);
}
}
/**
* Searches controller service for the given search term
*
* @param search the search term
* @param controllerServiceNode a group controller service node
*/
private ComponentSearchResultDTO search(final String search, final ControllerServiceNode controllerServiceNode) {
final List<String> matches = new ArrayList<>();
addIfAppropriate(search, controllerServiceNode.getIdentifier(), "Id", matches);
addIfAppropriate(search, controllerServiceNode.getVersionedComponentId().orElse(null), "Version Control ID", matches);
addIfAppropriate(search, controllerServiceNode.getName(), "Name", matches);
addIfAppropriate(search, controllerServiceNode.getComments(), "Comments", matches);
// search property values
controllerServiceNode.getRawPropertyValues().forEach((property, propertyValue) -> {
addIfAppropriate(search, property.getName(), "Property Name", matches);
addIfAppropriate(search, property.getDescription(), "Property Description", matches);
// never include sensitive properties in search results
if (property.isSensitive()) {
return;
}
if (propertyValue != null) {
addIfAppropriate(search, propertyValue, "Property Value", matches);
} else {
addIfAppropriate(search, property.getDefaultValue(), "Property Value", matches);
}
});
if (matches.isEmpty()) {
return null;
}
final ComponentSearchResultDTO dto = new ComponentSearchResultDTO();
dto.setId(controllerServiceNode.getIdentifier());
dto.setName(controllerServiceNode.getName());
dto.setMatches(matches);
return dto;
}
/**
* Searches all parameter contexts and parameters
*
* @param results Search results
* @param search The search term
*/

View File

@ -19,11 +19,15 @@ package org.apache.nifi.web.controller;
import org.apache.nifi.authorization.Authorizer;
import org.apache.nifi.authorization.RequestAction;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.StandardProcessorNode;
import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.controller.label.Label;
import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.controller.service.StandardControllerServiceNode;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.parameter.Parameter;
import org.apache.nifi.parameter.ParameterContext;
@ -50,6 +54,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@ -420,6 +425,86 @@ public class ControllerSearchServiceTest {
assertTrue(searchResultsDTO.getLabelResults().get(0).getName().equals("Value for label foo"));
}
@Test
public void testSearchControllerServices() {
final ProcessGroup rootProcessGroup = setupMockedProcessGroup("root", null, true, variableRegistry, null);
final String controllerServiceName = "controllerServiceName";
final String controllerServiceId = controllerServiceName + "Id";
final Map<PropertyDescriptor, String> props = new HashMap<>();
final PropertyDescriptor prop1 = new PropertyDescriptor.Builder()
.name("prop1-name")
.displayName("prop1-displayname")
.description("prop1 description")
.defaultValue("prop1-default")
.build();
final PropertyDescriptor prop2 = new PropertyDescriptor.Builder()
.name("prop2-name")
.displayName("prop2-displayname")
.description("prop2 description")
.defaultValue("prop2-default")
.build();
props.put(prop1, "prop1-value");
props.put(prop2, null);
setupMockedControllerService(controllerServiceName, rootProcessGroup, true, props);
// search for name
service.search(searchResultsDTO, "controllerserv", rootProcessGroup);
assertEquals(1, searchResultsDTO.getControllerServiceNodeResults().size());
assertEquals(controllerServiceId, searchResultsDTO.getControllerServiceNodeResults().get(0).getId());
assertEquals(controllerServiceName, searchResultsDTO.getControllerServiceNodeResults().get(0).getName());
// search for comments
searchResultsDTO = new SearchResultsDTO();
service.search(searchResultsDTO, "foo comment", rootProcessGroup);
assertEquals(1, searchResultsDTO.getControllerServiceNodeResults().size());
assertEquals(controllerServiceId, searchResultsDTO.getControllerServiceNodeResults().get(0).getId());
assertEquals(controllerServiceName, searchResultsDTO.getControllerServiceNodeResults().get(0).getName());
// search for properties
searchResultsDTO = new SearchResultsDTO();
service.search(searchResultsDTO, "prop1-name", rootProcessGroup);
assertEquals(1, searchResultsDTO.getControllerServiceNodeResults().size());
assertEquals(controllerServiceId, searchResultsDTO.getControllerServiceNodeResults().get(0).getId());
assertEquals(controllerServiceName, searchResultsDTO.getControllerServiceNodeResults().get(0).getName());
// by default
searchResultsDTO = new SearchResultsDTO();
service.search(searchResultsDTO, "prop2-def", rootProcessGroup);
assertEquals(1, searchResultsDTO.getControllerServiceNodeResults().size());
assertEquals(controllerServiceId, searchResultsDTO.getControllerServiceNodeResults().get(0).getId());
assertEquals(controllerServiceName, searchResultsDTO.getControllerServiceNodeResults().get(0).getName());
// by description
searchResultsDTO = new SearchResultsDTO();
service.search(searchResultsDTO, "desc", rootProcessGroup);
// "desc" would typically match both props, but it's for the same controller service.
assertEquals(1, searchResultsDTO.getControllerServiceNodeResults().size());
assertEquals(controllerServiceId, searchResultsDTO.getControllerServiceNodeResults().get(0).getId());
assertEquals(controllerServiceName, searchResultsDTO.getControllerServiceNodeResults().get(0).getName());
// by specified value
searchResultsDTO = new SearchResultsDTO();
service.search(searchResultsDTO, "prop1-value", rootProcessGroup);
assertEquals(1, searchResultsDTO.getControllerServiceNodeResults().size());
assertEquals(controllerServiceId, searchResultsDTO.getControllerServiceNodeResults().get(0).getId());
assertEquals(controllerServiceName, searchResultsDTO.getControllerServiceNodeResults().get(0).getName());
// search finding no match
searchResultsDTO = new SearchResultsDTO();
service.search(searchResultsDTO, "ZZZZZZZZZYYYYYY", rootProcessGroup);
assertEquals(0, searchResultsDTO.getControllerServiceNodeResults().size());
}
/**
* Mocks Labels including isAuthorized() and their identifier and value
*
@ -512,6 +597,32 @@ public class ControllerSearchServiceTest {
}).when(containingProcessGroup).getProcessors();
}
private static void setupMockedControllerService(final String controllerServiceName, final ProcessGroup containingProcessGroup, boolean authorizedToRead,
Map<PropertyDescriptor, String> properties) {
final String controllerServiceId = controllerServiceName + "Id";
final ControllerService controllerService = mock(ControllerService.class);
final ControllerServiceNode controllerServiceNode1 = mock(StandardControllerServiceNode.class);
Mockito.doReturn(authorizedToRead).when(controllerServiceNode1)
.isAuthorized(AdditionalMatchers.or(any(Authorizer.class), isNull()), eq(RequestAction.READ), AdditionalMatchers.or(any(NiFiUser.class), isNull()));
Mockito.doReturn(controllerService).when(controllerServiceNode1).getControllerServiceImplementation();
// set controller service node attributes
Mockito.doReturn(controllerServiceId).when(controllerServiceNode1).getIdentifier();
Mockito.doReturn(controllerServiceName).when(controllerServiceNode1).getName();
Mockito.doReturn(Optional.ofNullable(null)).when(controllerServiceNode1).getVersionedComponentId();
Mockito.doReturn("foo comments").when(controllerServiceNode1).getComments();
//set properties
Mockito.doReturn(properties).when(controllerServiceNode1).getRawPropertyValues();
// assign controller service node to its PG
Mockito.doReturn(new HashSet<ControllerServiceNode>() {
{
add(controllerServiceNode1);
}
}).when(containingProcessGroup).getControllerServices(anyBoolean());
}
/**
* Mocks ProcessGroup due to isAuthorized(). The final class StandardProcessGroup can't be used.
*

View File

@ -208,6 +208,14 @@
});
}
// show all controller services
if (!nfCommon.isEmpty(searchResults.controllerServiceNodeResults)) {
ul.append('<li class="search-header"><div class="search-result-icon icon"></div>Controller Services</li>');
$.each(searchResults.controllerServiceNodeResults, function (i, controllerServiceMatch) {
nfSearchAutocomplete._renderItem(ul, $.extend({}, controllerServiceMatch, { type: 'controller service' }));
});
}
// show all parameter contexts and parameters
if (!nfCommon.isEmpty(searchResults.parameterContextResults)) {
ul.append('<li class="search-header"><div class="search-result-icon icon"></div>Parameter Contexts</li>');