exceptionfactory commented on code in PR #10476:
URL: https://github.com/apache/nifi/pull/10476#discussion_r2519862886
##########
nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenHTTP.java:
##########
@@ -422,6 +429,47 @@ public void shutdownHttpServer() {
shutdownHttpServer(toShutdown);
}
+ @Override
+ public List<ListenPort> getListenPorts(final ConfigurationContext context)
{
+
+ final List<ListenPort> ports = new ArrayList<>();
+
+ final Integer primaryPortNumber =
context.getProperty(PORT).evaluateAttributeExpressions().asInteger();
+ final Integer healthCheckPortNumber =
context.getProperty(HEALTH_CHECK_PORT).evaluateAttributeExpressions().asInteger();
+ final SSLContextProvider sslContextProvider =
context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
+ final HttpProtocolStrategy httpProtocolStrategy = sslContextProvider
== null
+ ?
HttpProtocolStrategy.valueOf(HTTP_PROTOCOL_STRATEGY.getDefaultValue())
+ :
context.getProperty(HTTP_PROTOCOL_STRATEGY).asAllowableValue(HttpProtocolStrategy.class);
+ final List<String> applicationProtocols = switch
(httpProtocolStrategy) {
+ case H2 -> List.of("h2");
+ case HTTP_1_1 -> List.of("http/1.1");
+ case H2_HTTP_1_1 -> List.of("h2", "http/1.1");
+ case null -> List.of("h2", "http/1.1");
+ };
+
+ if (primaryPortNumber != null) {
Review Comment:
The primary port is required, should this ever be `null`?
##########
nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java:
##########
@@ -3126,4 +3127,17 @@ ControllerServiceReferencingComponentsEntity
updateControllerServiceReferencingC
*/
Set<String> filterComponents(String groupId, Function<ProcessGroup,
Set<String>> getComponents);
+ // ----------------------------------------
+ // Listen Port methods
+ // ----------------------------------------
+
+ /**
+ * Get all dynamically defined data ingress ports provided by Listen
Components (e.g., Processors and Controller Services)
+ *
+ * @param user the user performing the lookup
+ * @return the list of listen Ports accessible to the current user
+ */
+ Set<ListenPortDTO> getListenPorts(NiFiUser user);
+
+
Review Comment:
Empty lines can be removed.
##########
nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ListenPortDTO.java:
##########
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.web.api.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.xml.bind.annotation.XmlType;
+
+import java.util.List;
+
+@XmlType(name = "listenPort")
+public class ListenPortDTO {
+
+ // Port definition
+ private String portName;
+ private int portNumber;
+ private String transportProtocol;
+ private List<String> applicationProtocols;
+
+ // Contextual information about the component providing the port, and the
PG containing the component
+ private String componentType;
+ private String componentId;
+ private String componentName;
+ private String componentClass;
+ private String parentGroupId;
+ private String parentGroupName;
+
+ public String getPortName() {
+ return portName;
+ }
+
+ @Schema(description = "The name of the the listen port. Useful context for
components that provide multiple ports.")
Review Comment:
It looks like this annotation should be on `getPortName()` instead of
`setPortName()`
##########
nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/flow/AbstractFlowManager.java:
##########
@@ -732,4 +734,24 @@ private void removeRuleViolationsForSubject(String
identifier) {
ruleViolationsManager.removeRuleViolationsForSubject(identifier);
}
}
+
+ @Override
+ public Set<ComponentNode> getAllListenComponents() {
+
+ final Set<ComponentNode> allListenComponents = new HashSet<>();
Review Comment:
For deterministic ordering, recommend using `LinkedHashSet`:
```suggestion
final Set<ComponentNode> allListenComponents = new LinkedHashSet<>();
```
##########
nifi-manifest/nifi-extension-manifest-model/src/main/java/org/apache/nifi/extension/manifest/ListenPortDefinition.java:
##########
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.extension.manifest;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlElementWrapper;
+
+import java.util.List;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ListenPortDefinition {
+
+ private TransportProtocol transportProtocol;
+
+ @XmlElementWrapper
+ @XmlElement(name = "applicationProtocol")
Review Comment:
Is there a reason for renaming the element to avoid the plural?
##########
nifi-manifest/nifi-extension-manifest-model/src/main/java/org/apache/nifi/extension/manifest/ListenPortDefinition.java:
##########
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.nifi.extension.manifest;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlElementWrapper;
+
+import java.util.List;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ListenPortDefinition {
+
+ private TransportProtocol transportProtocol;
+
+ @XmlElementWrapper
+ @XmlElement(name = "applicationProtocol")
+ private List<String> applicationProtocols;
+
+ @Schema(description = "The transport protocol used by this listen port")
+ public TransportProtocol getTransportProtocol() {
+ return transportProtocol;
+ }
+
+ public void setTransportProtocol(final TransportProtocol
transportProtocol) {
+ this.transportProtocol = transportProtocol;
+ }
+
+ @Schema(description = "The application protocol(s) that this listen port
could support (if any)")
Review Comment:
```suggestion
@Schema(description = "The application protocols that this listen port
could support (if any)")
```
##########
nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java:
##########
@@ -1853,6 +1859,62 @@ public SearchResultsDTO search(final String
searchLiteral, final String activeGr
return results;
}
+ /**
+ * Get all user-defined data ingress ports provided by Listen Components
(e.g., Processors and Controller Services)
+ *
+ * @param user the user performing the lookup
+ * @return the set of listen Ports accessible to the current user
+ */
+ public Set<ListenPortDTO> getListenPorts(final NiFiUser user) {
+
+ // Get all listen components for which the requesting user is
authorized
+ final Set<ComponentNode> listenComponentNodes =
flowController.getFlowManager().getAllListenComponents().stream()
+ .filter(componentNode -> componentNode.isAuthorized(authorizer,
RequestAction.READ, user))
+ .collect(Collectors.toSet());
+
+ // If the current user doesn't have access to any listen components,
return an empty result for ports
+ if (listenComponentNodes.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ // Now find all Listen Ports provided by the Listen Components. A
listen component can provide multiple Listen Ports (e.g., ListenHTTP can have a
data port and a health check port).
+ // The current Listen Ports for a component depend on configuration
(e.g., port property value), so create a configuration context to provide
ListenComponent.getListenPorts(context).
+ final Set<ListenPortDTO> listenPorts = new HashSet<>();
+ final ControllerServiceProvider controllerServiceProvider =
flowController.getControllerServiceProvider();
+ for (final ComponentNode componentNode : listenComponentNodes) {
+ final ConfigurationContext configurationContext = new
StandardConfigurationContext(componentNode, controllerServiceProvider, null);
+ final ConfigurableComponent component =
componentNode.getComponent();
+ if (component instanceof ListenComponent listenComponent /* should
always be true */) {
+
listenComponent.getListenPorts(configurationContext).forEach(listenPort -> {
+ final ListenPortDTO listenPortDTO = new ListenPortDTO();
+ listenPortDTO.setPortName(listenPort.getPortName());
+ listenPortDTO.setPortNumber(listenPort.getPortNumber());
+
listenPortDTO.setTransportProtocol(listenPort.getTransportProtocol().name());
+
listenPortDTO.setApplicationProtocols(listenPort.getApplicationProtocols());
+
listenPortDTO.setComponentClass(componentNode.getCanonicalClassName());
+
listenPortDTO.setComponentId(componentNode.getIdentifier());
+ listenPortDTO.setComponentName(componentNode.getName());
+
listenPortDTO.setParentGroupId(componentNode.getParentProcessGroup().map(ProcessGroup::getIdentifier).orElse(null));
+
listenPortDTO.setParentGroupName(componentNode.getParentProcessGroup().map(ProcessGroup::getName).orElse(null));
+
+ // TODO this next bit could be refined
Review Comment:
Recommend removing this `TODO`
##########
nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java:
##########
@@ -1853,6 +1859,62 @@ public SearchResultsDTO search(final String
searchLiteral, final String activeGr
return results;
}
+ /**
+ * Get all user-defined data ingress ports provided by Listen Components
(e.g., Processors and Controller Services)
+ *
+ * @param user the user performing the lookup
+ * @return the set of listen Ports accessible to the current user
+ */
+ public Set<ListenPortDTO> getListenPorts(final NiFiUser user) {
+
+ // Get all listen components for which the requesting user is
authorized
+ final Set<ComponentNode> listenComponentNodes =
flowController.getFlowManager().getAllListenComponents().stream()
+ .filter(componentNode -> componentNode.isAuthorized(authorizer,
RequestAction.READ, user))
+ .collect(Collectors.toSet());
+
+ // If the current user doesn't have access to any listen components,
return an empty result for ports
+ if (listenComponentNodes.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ // Now find all Listen Ports provided by the Listen Components. A
listen component can provide multiple Listen Ports (e.g., ListenHTTP can have a
data port and a health check port).
+ // The current Listen Ports for a component depend on configuration
(e.g., port property value), so create a configuration context to provide
ListenComponent.getListenPorts(context).
+ final Set<ListenPortDTO> listenPorts = new HashSet<>();
+ final ControllerServiceProvider controllerServiceProvider =
flowController.getControllerServiceProvider();
+ for (final ComponentNode componentNode : listenComponentNodes) {
+ final ConfigurationContext configurationContext = new
StandardConfigurationContext(componentNode, controllerServiceProvider, null);
+ final ConfigurableComponent component =
componentNode.getComponent();
+ if (component instanceof ListenComponent listenComponent /* should
always be true */) {
Review Comment:
For readability, recommend moving the comment above or below the line,
instead of on the same line.
##########
nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/controller/ControllerFacade.java:
##########
@@ -1853,6 +1859,62 @@ public SearchResultsDTO search(final String
searchLiteral, final String activeGr
return results;
}
+ /**
+ * Get all user-defined data ingress ports provided by Listen Components
(e.g., Processors and Controller Services)
+ *
+ * @param user the user performing the lookup
+ * @return the set of listen Ports accessible to the current user
+ */
+ public Set<ListenPortDTO> getListenPorts(final NiFiUser user) {
+
+ // Get all listen components for which the requesting user is
authorized
+ final Set<ComponentNode> listenComponentNodes =
flowController.getFlowManager().getAllListenComponents().stream()
+ .filter(componentNode -> componentNode.isAuthorized(authorizer,
RequestAction.READ, user))
+ .collect(Collectors.toSet());
+
+ // If the current user doesn't have access to any listen components,
return an empty result for ports
+ if (listenComponentNodes.isEmpty()) {
+ return Collections.emptySet();
+ }
+
+ // Now find all Listen Ports provided by the Listen Components. A
listen component can provide multiple Listen Ports (e.g., ListenHTTP can have a
data port and a health check port).
+ // The current Listen Ports for a component depend on configuration
(e.g., port property value), so create a configuration context to provide
ListenComponent.getListenPorts(context).
+ final Set<ListenPortDTO> listenPorts = new HashSet<>();
+ final ControllerServiceProvider controllerServiceProvider =
flowController.getControllerServiceProvider();
+ for (final ComponentNode componentNode : listenComponentNodes) {
+ final ConfigurationContext configurationContext = new
StandardConfigurationContext(componentNode, controllerServiceProvider, null);
+ final ConfigurableComponent component =
componentNode.getComponent();
+ if (component instanceof ListenComponent listenComponent /* should
always be true */) {
+
listenComponent.getListenPorts(configurationContext).forEach(listenPort -> {
+ final ListenPortDTO listenPortDTO = new ListenPortDTO();
+ listenPortDTO.setPortName(listenPort.getPortName());
+ listenPortDTO.setPortNumber(listenPort.getPortNumber());
+
listenPortDTO.setTransportProtocol(listenPort.getTransportProtocol().name());
+
listenPortDTO.setApplicationProtocols(listenPort.getApplicationProtocols());
+
listenPortDTO.setComponentClass(componentNode.getCanonicalClassName());
+
listenPortDTO.setComponentId(componentNode.getIdentifier());
+ listenPortDTO.setComponentName(componentNode.getName());
+
listenPortDTO.setParentGroupId(componentNode.getParentProcessGroup().map(ProcessGroup::getIdentifier).orElse(null));
+
listenPortDTO.setParentGroupName(componentNode.getParentProcessGroup().map(ProcessGroup::getName).orElse(null));
+
+ // TODO this next bit could be refined
+ if (componentNode instanceof ProcessorNode) {
+ listenPortDTO.setComponentType("Processor");
+ } else if (componentNode instanceof ControllerServiceNode)
{
+ listenPortDTO.setComponentType("ControllerService");
+ } else {
+ // Would we ever have anything other than a Processor
or Controller Service providing a Listen Port?
Review Comment:
The question can be removed since the log indicates this is unexpected.
##########
nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/flow/AbstractFlowManager.java:
##########
@@ -732,4 +734,24 @@ private void removeRuleViolationsForSubject(String
identifier) {
ruleViolationsManager.removeRuleViolationsForSubject(identifier);
}
}
+
+ @Override
+ public Set<ComponentNode> getAllListenComponents() {
+
+ final Set<ComponentNode> allListenComponents = new HashSet<>();
+
+ // TODO improve performance by adding hooks to create/delete methods
to keep track of listen components in a new hash map
Review Comment:
Recommend removing this `TODO` and creating a Jira issue instead.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]