You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2018/10/11 13:52:53 UTC
[2/6] nifi git commit: NIFI-5585 Added capability to offload a node
that is disconnected from the cluster. Updated NodeClusterCoordinator to
allow idempotent requests to offload a cluster Added capability to
connect/delete/disconnect/offload a node from
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
index 095f714..0dc74d7 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/cluster/nf-cluster-table.js
@@ -528,6 +528,8 @@
promptForConnect(item);
} else if (target.hasClass('prompt-for-removal')) {
promptForRemoval(item);
+ } else if (target.hasClass('prompt-for-offload')) {
+ promptForOffload(item);
} else if (target.hasClass('prompt-for-disconnect')) {
promptForDisconnect(item);
}
@@ -630,19 +632,29 @@
var actionFormatter = function (row, cell, value, columnDef, dataContext) {
var canDisconnect = false;
var canConnect = false;
+ var isOffloaded = false;
// determine the current status
if (dataContext.status === 'CONNECTED' || dataContext.status === 'CONNECTING') {
canDisconnect = true;
- } else if (dataContext.status === 'DISCONNECTED') {
+ }
+ if (dataContext.status === 'DISCONNECTED') {
canConnect = true;
}
+ if (dataContext.status === 'OFFLOADED') {
+ isOffloaded = true;
+ }
// return the appropriate markup
if (canConnect) {
- return '<div title="Connect" class="pointer prompt-for-connect fa fa-plug"></div><div title="Delete" class="pointer prompt-for-removal fa fa-trash"></div>';
+ return '<div title="Connect" class="pointer prompt-for-connect fa fa-plug"></div>' +
+ '<div title="Delete" class="pointer prompt-for-removal fa fa-trash"></div>' +
+ '<div title="Offload" class="pointer prompt-for-offload fa fa-rotate-90 fa-upload"></div>';
} else if (canDisconnect) {
return '<div title="Disconnect" class="pointer prompt-for-disconnect fa fa-power-off"></div>';
+ } else if (isOffloaded) {
+ return '<div title="Connect" class="pointer prompt-for-connect fa fa-plug"></div>' +
+ '<div title="Delete" class="pointer prompt-for-removal fa fa-trash"></div>';
} else {
return '<div style="width: 16px; height: 16px;"> </div>';
}
@@ -947,6 +959,50 @@
};
/**
+ * Prompts to verify node offload.
+ *
+ * @argument {object} node The node
+ */
+ var promptForOffload = function (node) {
+ nfDialog.showYesNoDialog({
+ headerText: 'Offload Node',
+ dialogContent: 'Offload \'' + formatNodeAddress(node) + '\'?',
+ yesHandler: function () {
+ offload(node.nodeId);
+ }
+ });
+ };
+
+ /**
+ * Offloads the node in the specified row.
+ *
+ * @argument {string} nodeId The node id
+ */
+ var offload = function (nodeId) {
+ var entity = {
+ 'node': {
+ 'nodeId': nodeId,
+ 'status': 'OFFLOADING'
+ }
+ };
+
+ $.ajax({
+ type: 'PUT',
+ url: config.urls.nodes + '/' + encodeURIComponent(nodeId),
+ data: JSON.stringify(entity),
+ dataType: 'json',
+ contentType: 'application/json'
+ }).done(function (response) {
+ var node = response.node;
+
+ // update the node in the table
+ var clusterGrid = $('#cluster-nodes-table').data('gridInstance');
+ var clusterData = clusterGrid.getData();
+ clusterData.updateItem(node.nodeId, node);
+ }).fail(nfErrorHandler.handleAjaxError);
+ };
+
+ /**
* Prompts to verify node disconnection.
*
* @argument {object} node The node
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/ControllerClient.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/ControllerClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/ControllerClient.java
index 22821ee..6cb3226 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/ControllerClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/ControllerClient.java
@@ -16,6 +16,8 @@
*/
package org.apache.nifi.toolkit.cli.impl.client.nifi;
+import org.apache.nifi.web.api.entity.ClusterEntity;
+import org.apache.nifi.web.api.entity.NodeEntity;
import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.RegistryClientsEntity;
@@ -34,4 +36,16 @@ public interface ControllerClient {
RegistryClientEntity updateRegistryClient(RegistryClientEntity registryClientEntity) throws NiFiClientException, IOException;
+ NodeEntity connectNode(String nodeId, NodeEntity nodeEntity) throws NiFiClientException, IOException;
+
+ NodeEntity deleteNode(String nodeId) throws NiFiClientException, IOException;
+
+ NodeEntity disconnectNode(String nodeId, NodeEntity nodeEntity) throws NiFiClientException, IOException;
+
+ NodeEntity getNode(String nodeId) throws NiFiClientException, IOException;
+
+ ClusterEntity getNodes() throws NiFiClientException, IOException;
+
+ NodeEntity offloadNode(String nodeId, NodeEntity nodeEntity) throws NiFiClientException, IOException;
+
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
index 9c9ffc4..a162790 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/client/nifi/impl/JerseyControllerClient.java
@@ -19,6 +19,8 @@ package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.web.api.entity.ClusterEntity;
+import org.apache.nifi.web.api.entity.NodeEntity;
import org.apache.nifi.web.api.entity.RegistryClientEntity;
import org.apache.nifi.web.api.entity.RegistryClientsEntity;
@@ -104,4 +106,89 @@ public class JerseyControllerClient extends AbstractJerseyClient implements Cont
});
}
+ @Override
+ public NodeEntity deleteNode(final String nodeId) throws NiFiClientException, IOException {
+ if (StringUtils.isBlank(nodeId)) {
+ throw new IllegalArgumentException("Node ID cannot be null or empty");
+ }
+
+ return executeAction("Error deleting node", () -> {
+ final WebTarget target = controllerTarget.path("cluster/nodes/" + nodeId);
+
+ return getRequestBuilder(target).delete(NodeEntity.class);
+ });
+ }
+
+ @Override
+ public NodeEntity connectNode(final String nodeId, final NodeEntity nodeEntity) throws NiFiClientException, IOException {
+ if (StringUtils.isBlank(nodeId)) {
+ throw new IllegalArgumentException("Node ID cannot be null or empty");
+ }
+
+ if (nodeEntity == null) {
+ throw new IllegalArgumentException("Node entity cannot be null");
+ }
+
+ return executeAction("Error connecting node", () -> {
+ final WebTarget target = controllerTarget.path("cluster/nodes/" + nodeId);
+
+ return getRequestBuilder(target).put(Entity.entity(nodeEntity, MediaType.APPLICATION_JSON), NodeEntity.class);
+ });
+ }
+
+ @Override
+ public NodeEntity offloadNode(final String nodeId, final NodeEntity nodeEntity) throws NiFiClientException, IOException {
+ if (StringUtils.isBlank(nodeId)) {
+ throw new IllegalArgumentException("Node ID cannot be null or empty");
+ }
+
+ if (nodeEntity == null) {
+ throw new IllegalArgumentException("Node entity cannot be null");
+ }
+
+ return executeAction("Error offloading node", () -> {
+ final WebTarget target = controllerTarget.path("cluster/nodes/" + nodeId);
+
+ return getRequestBuilder(target).put(Entity.entity(nodeEntity, MediaType.APPLICATION_JSON), NodeEntity.class);
+ });
+ }
+
+ @Override
+ public NodeEntity disconnectNode(final String nodeId, final NodeEntity nodeEntity) throws NiFiClientException, IOException {
+ if (StringUtils.isBlank(nodeId)) {
+ throw new IllegalArgumentException("Node ID cannot be null or empty");
+ }
+
+ if (nodeEntity == null) {
+ throw new IllegalArgumentException("Node entity cannot be null");
+ }
+
+ return executeAction("Error disconnecting node", () -> {
+ final WebTarget target = controllerTarget.path("cluster/nodes/" + nodeId);
+
+ return getRequestBuilder(target).put(Entity.entity(nodeEntity, MediaType.APPLICATION_JSON), NodeEntity.class);
+ });
+ }
+
+ @Override
+ public NodeEntity getNode(String nodeId) throws NiFiClientException, IOException {
+ if (StringUtils.isBlank(nodeId)) {
+ throw new IllegalArgumentException("Node ID cannot be null or empty");
+ }
+
+ return executeAction("Error retrieving node status", () -> {
+ final WebTarget target = controllerTarget.path("cluster/nodes/" + nodeId);
+
+ return getRequestBuilder(target).get(NodeEntity.class);
+ });
+ }
+
+ @Override
+ public ClusterEntity getNodes() throws NiFiClientException, IOException {
+ return executeAction("Error retrieving node status", () -> {
+ final WebTarget target = controllerTarget.path("cluster");
+
+ return getRequestBuilder(target).get(ClusterEntity.class);
+ });
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
index ad15036..171e6cf 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java
@@ -49,6 +49,9 @@ public enum CommandOption {
SRC_FLOW_ID("sf", "sourceFlowIdentifier", "A flow identifier from the source registry", true),
SRC_FLOW_VERSION("sfv", "sourceFlowVersion", "A version of a flow from the source registry", true),
+ // NiFi - Nodes
+ NIFI_NODE_ID("nnid", "nifiNodeId", "The ID of a node in the NiFi cluster", true),
+
// NiFi - Registries
REGISTRY_CLIENT_ID("rcid", "registryClientId", "The id of a registry client", true),
REGISTRY_CLIENT_NAME("rcn", "registryClientName", "The name of the registry client", true),
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
index 00a38a2..298b709 100644
--- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java
@@ -21,6 +21,12 @@ import org.apache.nifi.toolkit.cli.impl.command.AbstractCommandGroup;
import org.apache.nifi.toolkit.cli.impl.command.nifi.flow.ClusterSummary;
import org.apache.nifi.toolkit.cli.impl.command.nifi.flow.CurrentUser;
import org.apache.nifi.toolkit.cli.impl.command.nifi.flow.GetRootId;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.nodes.ConnectNode;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.nodes.OffloadNode;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.nodes.DeleteNode;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.nodes.DisconnectNode;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.nodes.GetNode;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.nodes.GetNodes;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGChangeVersion;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGDisableControllerServices;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGEnableControllerServices;
@@ -58,7 +64,13 @@ public class NiFiCommandGroup extends AbstractCommandGroup {
final List<AbstractNiFiCommand> commands = new ArrayList<>();
commands.add(new CurrentUser());
commands.add(new ClusterSummary());
+ commands.add(new ConnectNode());
+ commands.add(new DeleteNode());
+ commands.add(new DisconnectNode());
commands.add(new GetRootId());
+ commands.add(new GetNode());
+ commands.add(new GetNodes());
+ commands.add(new OffloadNode());
commands.add(new ListRegistryClients());
commands.add(new CreateRegistryClient());
commands.add(new UpdateRegistryClient());
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/ConnectNode.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/ConnectNode.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/ConnectNode.java
new file mode 100644
index 0000000..8ec0066
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/ConnectNode.java
@@ -0,0 +1,67 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.nodes;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.NodeResult;
+import org.apache.nifi.web.api.dto.NodeDTO;
+import org.apache.nifi.web.api.entity.NodeEntity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Command for offloading a node of the NiFi cluster.
+ */
+public class ConnectNode extends AbstractNiFiCommand<NodeResult> {
+
+ public ConnectNode() {
+ super("connect-node", NodeResult.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Connects a node to the NiFi cluster.";
+ }
+
+ @Override
+ protected void doInitialize(Context context) {
+ addOption(CommandOption.NIFI_NODE_ID.createOption());
+ }
+
+ @Override
+ public NodeResult doExecute(NiFiClient client, Properties properties) throws NiFiClientException, IOException, MissingOptionException, CommandException {
+ final String nodeId = getRequiredArg(properties, CommandOption.NIFI_NODE_ID);
+ final ControllerClient controllerClient = client.getControllerClient();
+
+ NodeDTO nodeDto = new NodeDTO();
+ nodeDto.setNodeId(nodeId);
+ // TODO There are no constants for the CONNECT node statuses
+ nodeDto.setStatus("CONNECTING");
+ NodeEntity nodeEntity = new NodeEntity();
+ nodeEntity.setNode(nodeDto);
+ NodeEntity nodeEntityResult = controllerClient.connectNode(nodeId, nodeEntity);
+ return new NodeResult(getResultType(properties), nodeEntityResult);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DeleteNode.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DeleteNode.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DeleteNode.java
new file mode 100644
index 0000000..280e625
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DeleteNode.java
@@ -0,0 +1,58 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.nodes;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.OkResult;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Command for deleting a node from the NiFi cluster.
+ */
+public class DeleteNode extends AbstractNiFiCommand<OkResult> {
+
+ public DeleteNode() {
+ super("delete-node", OkResult.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Deletes a node from the NiFi cluster.";
+ }
+
+ @Override
+ protected void doInitialize(Context context) {
+ addOption(CommandOption.NIFI_NODE_ID.createOption());
+ }
+
+ @Override
+ public OkResult doExecute(NiFiClient client, Properties properties) throws NiFiClientException, IOException, MissingOptionException {
+ final String nodeId = getRequiredArg(properties, CommandOption.NIFI_NODE_ID);
+ final ControllerClient controllerClient = client.getControllerClient();
+
+ controllerClient.deleteNode(nodeId);
+ return new OkResult(getContext().isInteractive());
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DisconnectNode.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DisconnectNode.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DisconnectNode.java
new file mode 100644
index 0000000..98fa03a
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/DisconnectNode.java
@@ -0,0 +1,67 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.nodes;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.NodeResult;
+import org.apache.nifi.web.api.dto.NodeDTO;
+import org.apache.nifi.web.api.entity.NodeEntity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Command for disconnecting a node from the NiFi cluster.
+ */
+public class DisconnectNode extends AbstractNiFiCommand<NodeResult> {
+
+ public DisconnectNode() {
+ super("disconnect-node", NodeResult.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Disconnects a node from the NiFi cluster.";
+ }
+
+ @Override
+ protected void doInitialize(Context context) {
+ addOption(CommandOption.NIFI_NODE_ID.createOption());
+ }
+
+ @Override
+ public NodeResult doExecute(NiFiClient client, Properties properties) throws NiFiClientException, IOException, MissingOptionException, CommandException {
+ final String nodeId = getRequiredArg(properties, CommandOption.NIFI_NODE_ID);
+ final ControllerClient controllerClient = client.getControllerClient();
+
+ NodeDTO nodeDto = new NodeDTO();
+ nodeDto.setNodeId(nodeId);
+ // TODO There's no constant for node status in
+ nodeDto.setStatus("DISCONNECTING");
+ NodeEntity nodeEntity = new NodeEntity();
+ nodeEntity.setNode(nodeDto);
+ NodeEntity nodeEntityResult = controllerClient.disconnectNode(nodeId, nodeEntity);
+ return new NodeResult(getResultType(properties), nodeEntityResult);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNode.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNode.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNode.java
new file mode 100644
index 0000000..54687bd
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNode.java
@@ -0,0 +1,59 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.nodes;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.NodeResult;
+import org.apache.nifi.web.api.entity.NodeEntity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Command for retrieving the status of the nodes from the NiFi cluster.
+ */
+public class GetNode extends AbstractNiFiCommand<NodeResult> {
+
+ public GetNode() {
+ super("get-node", NodeResult.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Retrieves the status for a node in the NiFi cluster.";
+ }
+
+ @Override
+ protected void doInitialize(Context context) {
+ addOption(CommandOption.NIFI_NODE_ID.createOption());
+ }
+
+ @Override
+ public NodeResult doExecute(NiFiClient client, Properties properties) throws NiFiClientException, IOException, MissingOptionException {
+ final String nodeId = getRequiredArg(properties, CommandOption.NIFI_NODE_ID);
+ final ControllerClient controllerClient = client.getControllerClient();
+
+ NodeEntity nodeEntityResult = controllerClient.getNode(nodeId);
+ return new NodeResult(getResultType(properties), nodeEntityResult);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNodes.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNodes.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNodes.java
new file mode 100644
index 0000000..368fb4d
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/GetNodes.java
@@ -0,0 +1,52 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.nodes;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.NodesResult;
+import org.apache.nifi.web.api.entity.ClusterEntity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Command for retrieving the status of the nodes from the NiFi cluster.
+ */
+public class GetNodes extends AbstractNiFiCommand<NodesResult> {
+
+ public GetNodes() {
+ super("get-nodes", NodesResult.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Retrieves statuses for the nodes of the NiFi cluster.";
+ }
+
+ @Override
+ public NodesResult doExecute(NiFiClient client, Properties properties) throws NiFiClientException, IOException, MissingOptionException, CommandException {
+ final ControllerClient controllerClient = client.getControllerClient();
+
+ ClusterEntity clusterEntityResult = controllerClient.getNodes();
+ return new NodesResult(getResultType(properties), clusterEntityResult);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/OffloadNode.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/OffloadNode.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/OffloadNode.java
new file mode 100644
index 0000000..aa759b1
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/nodes/OffloadNode.java
@@ -0,0 +1,67 @@
+/*
+ * 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.toolkit.cli.impl.command.nifi.nodes;
+
+import org.apache.commons.cli.MissingOptionException;
+import org.apache.nifi.toolkit.cli.api.CommandException;
+import org.apache.nifi.toolkit.cli.api.Context;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.ControllerClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
+import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
+import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
+import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
+import org.apache.nifi.toolkit.cli.impl.result.NodeResult;
+import org.apache.nifi.web.api.dto.NodeDTO;
+import org.apache.nifi.web.api.entity.NodeEntity;
+
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Command for offloading a node of the NiFi cluster.
+ */
+public class OffloadNode extends AbstractNiFiCommand<NodeResult> {
+
+ public OffloadNode() {
+ super("offload-node", NodeResult.class);
+ }
+
+ @Override
+ public String getDescription() {
+ return "Offloads a node of the NiFi cluster.";
+ }
+
+ @Override
+ protected void doInitialize(Context context) {
+ addOption(CommandOption.NIFI_NODE_ID.createOption());
+ }
+
+ @Override
+ public NodeResult doExecute(NiFiClient client, Properties properties) throws NiFiClientException, IOException, MissingOptionException, CommandException {
+ final String nodeId = getRequiredArg(properties, CommandOption.NIFI_NODE_ID);
+ final ControllerClient controllerClient = client.getControllerClient();
+
+ NodeDTO nodeDto = new NodeDTO();
+ nodeDto.setNodeId(nodeId);
+ // TODO There are no constants for the OFFLOAD node statuses
+ nodeDto.setStatus("OFFLOADING");
+ NodeEntity nodeEntity = new NodeEntity();
+ nodeEntity.setNode(nodeDto);
+ NodeEntity nodeEntityResult = controllerClient.offloadNode(nodeId, nodeEntity);
+ return new NodeResult(getResultType(properties), nodeEntityResult);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodeResult.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodeResult.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodeResult.java
new file mode 100644
index 0000000..3e1efdf
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodeResult.java
@@ -0,0 +1,48 @@
+/*
+ * 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.toolkit.cli.impl.result;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.nifi.toolkit.cli.api.ResultType;
+import org.apache.nifi.web.api.dto.NodeDTO;
+import org.apache.nifi.web.api.entity.NodeEntity;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class NodeResult extends AbstractWritableResult<NodeEntity> {
+
+ private final NodeEntity nodeEntity;
+
+ public NodeResult(ResultType resultType, NodeEntity nodeEntity) {
+ super(resultType);
+ this.nodeEntity = nodeEntity;
+ Validate.notNull(nodeEntity);
+ }
+
+ @Override
+ public NodeEntity getResult() {
+ return nodeEntity;
+ }
+
+ @Override
+ protected void writeSimpleResult(PrintStream output) throws IOException {
+ NodeDTO nodeDTO = nodeEntity.getNode();
+ output.printf("Node ID: %s\nNode Address: %s\nAPI Port: %s\nNode Status:%s",
+ nodeDTO.getNodeId(), nodeDTO.getAddress(), nodeDTO.getApiPort(), nodeDTO.getStatus());
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/04d8da8f/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodesResult.java
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodesResult.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodesResult.java
new file mode 100644
index 0000000..daab27f
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/NodesResult.java
@@ -0,0 +1,66 @@
+/*
+ * 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.toolkit.cli.impl.result;
+
+import org.apache.commons.lang3.Validate;
+import org.apache.nifi.toolkit.cli.api.ResultType;
+import org.apache.nifi.toolkit.cli.impl.result.writer.DynamicTableWriter;
+import org.apache.nifi.toolkit.cli.impl.result.writer.Table;
+import org.apache.nifi.toolkit.cli.impl.result.writer.TableWriter;
+import org.apache.nifi.web.api.dto.NodeDTO;
+import org.apache.nifi.web.api.entity.ClusterEntity;
+import org.glassfish.jersey.internal.guava.Lists;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+
+public class NodesResult extends AbstractWritableResult<ClusterEntity> {
+
+ private final ClusterEntity clusterEntity;
+
+ public NodesResult(ResultType resultType, ClusterEntity clusterEntity) {
+ super(resultType);
+ this.clusterEntity = clusterEntity;
+ Validate.notNull(clusterEntity);
+ }
+
+ @Override
+ public ClusterEntity getResult() {
+ return clusterEntity;
+ }
+
+ @Override
+ protected void writeSimpleResult(PrintStream output) throws IOException {
+ final Table table = new Table.Builder()
+ .column("#", 3, 3, false)
+ .column("Node ID", 36, 36, false)
+ .column("Node Address", 36, 36, true)
+ .column("API Port", 8, 8, false)
+ .column("Node Status", 13, 13, false)
+ .build();
+
+ List<NodeDTO> nodes = Lists.newArrayList(clusterEntity.getCluster().getNodes());
+ for (int i = 0; i < nodes.size(); ++i) {
+ NodeDTO nodeDTO = nodes.get(i);
+ table.addRow(String.valueOf(i), nodeDTO.getNodeId(), nodeDTO.getAddress(), String.valueOf(nodeDTO.getApiPort()), nodeDTO.getStatus());
+ }
+
+ final TableWriter tableWriter = new DynamicTableWriter();
+ tableWriter.write(table, output);
+ }
+}