Skip to content

Commit

Permalink
NIFI-5925: Added controller services to set of components that are se…
Browse files Browse the repository at this point in the history
…arched

NIFI-5925: cleanup, add negative test

NIFI-5925: fixed checkstyle

This closes apache#4105

Signed-off-by: Mike Thomsen <mthomsen@apache.org>
  • Loading branch information
m-hogue authored and driesva committed Mar 19, 2021
1 parent c8870fa commit 25be5bf
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 0 deletions.
Expand Up @@ -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<>();

Expand Down Expand Up @@ -151,6 +152,20 @@ public void setLabelResults(List<ComponentSearchResultDTO> labelResults) {
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.
*/
Expand Down
Expand Up @@ -33,6 +33,7 @@
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;
Expand Down Expand Up @@ -175,13 +176,67 @@ public void search(final SearchResultsDTO results, final String search, final Pr
}
}

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
*/
Expand Down
Expand Up @@ -19,11 +19,15 @@
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;
Expand All @@ -50,6 +54,7 @@
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;
Expand Down Expand Up @@ -420,6 +425,86 @@ public void testSearchLabels() {
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
*
Expand Down Expand Up @@ -512,6 +597,32 @@ private static void setupMockedProcessor(final String processorName, final Proce
}).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.
*
Expand Down
Expand Up @@ -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>');
Expand Down

0 comments on commit 25be5bf

Please sign in to comment.