Skip to content

Commit a495bbf

Browse files
committed
NIFI-15156 Add REST API endpoint for discovering Listen Ports
1 parent e9512aa commit a495bbf

File tree

3 files changed

+269
-0
lines changed

3 files changed

+269
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
package org.apache.nifi.web.api.dto;
17+
18+
import io.swagger.v3.oas.annotations.media.Schema;
19+
import jakarta.xml.bind.annotation.XmlType;
20+
21+
import java.util.List;
22+
23+
@XmlType(name = "listenPort")
24+
public class ListenPortDTO {
25+
26+
// Port definition
27+
private int portNumber;
28+
private String transportProtocol;
29+
private List<String> applicationProtocols;
30+
31+
// Contextual information about the component providing the port, and the PG containing the component
32+
private String componentType;
33+
private String componentId;
34+
private String componentName;
35+
private String componentClass;
36+
37+
private String parentGroupId;
38+
private String parentGroupName;
39+
40+
// TODO not sure this is needed
41+
// The idea is that if the ListenComponent belongs to a nested PG, the "ancestor" group would identify the highest level PG that is not the root group
42+
private String ancestorGroupId;
43+
private String ancestorGroupName;
44+
45+
@Schema(description = "The ingress port number")
46+
public int getPortNumber() {
47+
return portNumber;
48+
}
49+
50+
public void setPortNumber(final int portNumber) {
51+
this.portNumber = portNumber;
52+
}
53+
54+
@Schema(description = "The ingress transport protocol (TCP or UDP)")
55+
public String getTransportProtocol() {
56+
return transportProtocol;
57+
}
58+
59+
public void setTransportProtocol(final String transportProtocol) {
60+
this.transportProtocol = transportProtocol;
61+
}
62+
63+
@Schema(description = "Supported application protocols, if applicable")
64+
public List<String> getApplicationProtocols() {
65+
return applicationProtocols;
66+
}
67+
68+
public void setApplicationProtocols(final List<String> applicationProtocols) {
69+
this.applicationProtocols = applicationProtocols;
70+
}
71+
72+
@Schema(description = "The type of component providing the listen port (e.g., Processor, ControllerService)")
73+
public String getComponentType() {
74+
return componentType;
75+
}
76+
77+
public void setComponentType(final String componentType) {
78+
this.componentType = componentType;
79+
}
80+
81+
@Schema(description = "The id of the component providing the listen port")
82+
public String getComponentId() {
83+
return componentId;
84+
}
85+
86+
public void setComponentId(final String componentId) {
87+
this.componentId = componentId;
88+
}
89+
90+
@Schema(description = "The name of the component providing the listen port")
91+
public String getComponentName() {
92+
return componentName;
93+
}
94+
95+
public void setComponentName(final String componentName) {
96+
this.componentName = componentName;
97+
}
98+
99+
@Schema(description = "The class type of the component providing the listen port")
100+
public String getComponentClass() {
101+
return componentClass;
102+
}
103+
104+
public void setComponentClass(final String componentClass) {
105+
this.componentClass = componentClass;
106+
}
107+
108+
@Schema(description = "The id of the process group containing the component providing the listen port, if applicable")
109+
public String getParentGroupId() {
110+
return parentGroupId;
111+
}
112+
113+
public void setParentGroupId(final String parentGroupId) {
114+
this.parentGroupId = parentGroupId;
115+
}
116+
117+
@Schema(description = "The name of the process group containing the component providing the listen port, if applicable")
118+
public String getParentGroupName() {
119+
return parentGroupName;
120+
}
121+
122+
public void setParentGroupName(final String parentGroupName) {
123+
this.parentGroupName = parentGroupName;
124+
}
125+
126+
@Schema(description = "The id of the highest level process group containing the component providing the listen port that is not the root group, if applicable")
127+
public String getAncestorGroupId() {
128+
return ancestorGroupId;
129+
}
130+
131+
public void setAncestorGroupId(final String ancestorGroupId) {
132+
this.ancestorGroupId = ancestorGroupId;
133+
}
134+
135+
@Schema(description = "The name of the highest level process group containing the component providing the listen port that is not the root group, if applicable")
136+
public String getAncestorGroupName() {
137+
return ancestorGroupName;
138+
}
139+
140+
public void setAncestorGroupName(final String ancestorGroupName) {
141+
this.ancestorGroupName = ancestorGroupName;
142+
}
143+
144+
@Override
145+
public String toString() {
146+
return "ListenPortDTO{" +
147+
"portNumber=" + portNumber +
148+
", transportProtocol='" + transportProtocol + '\'' +
149+
", applicationProtocols=" + applicationProtocols +
150+
", componentType='" + componentType + '\'' +
151+
", componentId='" + componentId + '\'' +
152+
", componentName='" + componentName + '\'' +
153+
", componentClass='" + componentClass + '\'' +
154+
'}';
155+
}
156+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
package org.apache.nifi.web.api.entity;
17+
18+
import io.swagger.v3.oas.annotations.media.Schema;
19+
import jakarta.xml.bind.annotation.XmlRootElement;
20+
import org.apache.nifi.web.api.dto.ListenPortDTO;
21+
22+
import java.util.List;
23+
24+
@XmlRootElement(name = "listenPortsEntity")
25+
public class ListenPortsEntity {
26+
27+
private List<ListenPortDTO> listenPorts;
28+
29+
public ListenPortsEntity() {
30+
}
31+
32+
public ListenPortsEntity(final List<ListenPortDTO> listenPorts) {
33+
this.listenPorts = listenPorts;
34+
}
35+
36+
@Schema(description = "A list of ingress ports that are currently configured")
37+
public List<ListenPortDTO> getListenPorts() {
38+
return listenPorts;
39+
}
40+
41+
public void setListenPorts(final List<ListenPortDTO> listenPorts) {
42+
this.listenPorts = listenPorts;
43+
}
44+
}

nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/FlowResource.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import org.apache.nifi.web.api.dto.ComponentDifferenceDTO;
8989
import org.apache.nifi.web.api.dto.ContentViewerDTO;
9090
import org.apache.nifi.web.api.dto.DifferenceDTO;
91+
import org.apache.nifi.web.api.dto.ListenPortDTO;
9192
import org.apache.nifi.web.api.dto.NodeDTO;
9293
import org.apache.nifi.web.api.dto.ProcessGroupDTO;
9394
import org.apache.nifi.web.api.dto.RevisionDTO;
@@ -129,6 +130,7 @@
129130
import org.apache.nifi.web.api.entity.FlowRegistryClientEntity;
130131
import org.apache.nifi.web.api.entity.FlowRegistryClientsEntity;
131132
import org.apache.nifi.web.api.entity.HistoryEntity;
133+
import org.apache.nifi.web.api.entity.ListenPortsEntity;
132134
import org.apache.nifi.web.api.entity.ParameterContextEntity;
133135
import org.apache.nifi.web.api.entity.ParameterContextsEntity;
134136
import org.apache.nifi.web.api.entity.ParameterProviderEntity;
@@ -1275,6 +1277,73 @@ public Response searchFlow(
12751277
return noCache(Response.ok(entity)).build();
12761278
}
12771279

1280+
@GET
1281+
@Path("listen-ports")
1282+
@Consumes(MediaType.WILDCARD)
1283+
@Produces(MediaType.APPLICATION_JSON)
1284+
@Operation(
1285+
summary = "Gets all listen ports configured on this NiFi that the current user has access to",
1286+
responses = {
1287+
@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = ListenPortsEntity.class))),
1288+
@ApiResponse(responseCode = "400", description = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
1289+
@ApiResponse(responseCode = "401", description = "Client could not be authenticated."),
1290+
@ApiResponse(responseCode = "403", description = "Client is not authorized to make this request."),
1291+
@ApiResponse(responseCode = "409", description = "The request was valid but NiFi was not in the appropriate state to process it.")
1292+
},
1293+
security = {
1294+
@SecurityRequirement(name = "Read - /flow")
1295+
}
1296+
)
1297+
public Response getListenPorts() {
1298+
authorizeFlow();
1299+
1300+
final Set<ListenPortDTO> listenPorts;
1301+
1302+
final boolean useMockData = false;
1303+
if (useMockData) {
1304+
final ListenPortDTO listenPort1 = new ListenPortDTO();
1305+
listenPort1.setPortNumber(1000);
1306+
listenPort1.setTransportProtocol("TCP");
1307+
listenPort1.setApplicationProtocols(List.of("http/1.1", "h2"));
1308+
listenPort1.setComponentType("Processor");
1309+
listenPort1.setComponentId("fb67914a-3f92-4c4f-b44d-8a3ffb8c8284");
1310+
listenPort1.setComponentName("ListenHTTP");
1311+
listenPort1.setComponentClass("org.apache.nifi.processors.standard.ListenHTTP");
1312+
listenPort1.setParentGroupId("13cadd35-17ac-42ae-a31e-89c23b2b7413");
1313+
listenPort1.setParentGroupName("Jira Webhook Events to Snowflake");
1314+
1315+
final ListenPortDTO listenPort2 = new ListenPortDTO();
1316+
listenPort2.setPortNumber(2000);
1317+
listenPort2.setTransportProtocol("TCP");
1318+
listenPort2.setApplicationProtocols(List.of("ws"));
1319+
listenPort2.setComponentType("ControllerService");
1320+
listenPort2.setComponentId("fb67914a-3f92-4c4f-b44d-8a3ffb8c8284");
1321+
listenPort2.setComponentName("JettyWebSocketServer");
1322+
listenPort2.setComponentClass("org.apache.nifi.websocket.jetty.JettyWebSocketServer");
1323+
listenPort2.setParentGroupId("1e0d45de-8b41-454d-97f8-8c351049e5b4");
1324+
listenPort2.setParentGroupName("Root");
1325+
1326+
final ListenPortDTO listenPort3 = new ListenPortDTO();
1327+
listenPort3.setPortNumber(3000);
1328+
listenPort3.setTransportProtocol("TCP");
1329+
listenPort3.setApplicationProtocols(List.of("h2"));
1330+
listenPort3.setComponentType("Connector");
1331+
listenPort3.setComponentId("13bd2f1f-6b62-403f-bf97-7ba2283a09fc");
1332+
listenPort3.setComponentName("FutureConnector");
1333+
listenPort3.setComponentClass("org.apache.nifi.connectors.standard.FutureConnector");
1334+
listenPort3.setParentGroupId(null);
1335+
listenPort3.setParentGroupName(null);
1336+
1337+
listenPorts = Set.of(listenPort1, listenPort2, listenPort3);
1338+
} else {
1339+
listenPorts = serviceFacade.getListenPorts(NiFiUserUtils.getNiFiUser());
1340+
}
1341+
1342+
final ListenPortsEntity listenPortsEntity = new ListenPortsEntity(new ArrayList<>(listenPorts));
1343+
1344+
return generateOkResponse(listenPortsEntity).build();
1345+
}
1346+
12781347
/**
12791348
* Retrieves the status for this NiFi.
12801349
*

0 commit comments

Comments
 (0)