This is an automated email from the ASF dual-hosted git repository.

mthomsen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/master by this push:
     new aeaf953  NIFI-5925: Added controller services to set of components 
that are searched
aeaf953 is described below

commit aeaf953e06615bd2c05b6ced4b8d475af09b00af
Author: Michael Hogue <hogu...@gmail.com>
AuthorDate: Mon Mar 2 16:06:28 2020 -0500

    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 <mthom...@apache.org>
---
 .../nifi/web/api/dto/search/SearchResultsDTO.java  |  15 +++
 .../web/controller/ControllerSearchService.java    |  55 ++++++++++
 .../controller/ControllerSearchServiceTest.java    | 111 +++++++++++++++++++++
 .../nf-ng-canvas-flow-status-controller.js         |   8 ++
 4 files changed, 189 insertions(+)

diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/SearchResultsDTO.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/SearchResultsDTO.java
index 1946261..ae3548a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/SearchResultsDTO.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/search/SearchResultsDTO.java
@@ -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<>();
 
@@ -152,6 +153,20 @@ public class SearchResultsDTO {
     }
 
     /**
+     * @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.
      */
     @ApiModelProperty(
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
index a41288e..7204762 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerSearchService.java
@@ -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
      */
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerSearchServiceTest.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerSearchServiceTest.java
index 74ffc1c..66ed8a9 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerSearchServiceTest.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/controller/ControllerSearchServiceTest.java
@@ -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.
      *
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-flow-status-controller.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-flow-status-controller.js
index 357ad49..61494ff 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-flow-status-controller.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-flow-status-controller.js
@@ -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>');

Reply via email to