geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kh...@apache.org
Subject [geode] branch develop updated: GEODE-2665: Add Gfsh command to delete async event queues (#1116)
Date Thu, 21 Dec 2017 17:19:21 GMT
This is an automated email from the ASF dual-hosted git repository.

khowe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new d4183f6  GEODE-2665: Add Gfsh command to delete async event queues (#1116)
d4183f6 is described below

commit d4183f67920e8d92f37a2ed09b0c6f3196c83058
Author: Kenneth Howe <khowe@pivotal.io>
AuthorDate: Thu Dec 21 09:19:18 2017 -0800

    GEODE-2665: Add Gfsh command to delete async event queues (#1116)
    
    * GEODE-2665: Add Gfsh command to delete async event queues
    
    New classes added for the Command, Function and FunctionArgs
    New test classes added for DUnit and Unit tests
    
    Command supports --if-exists option for idempotency
    
    Refactor tests for changes in handling function results errors
---
 .../commands/DestroyAsyncEventQueueCommand.java    |  79 ++++++++
 .../functions/DestroyAsyncEventQueueFunction.java  |  80 ++++++++
 .../DestroyAsyncEventQueueFunctionArgs.java        |  38 ++++
 .../sanctioned-geode-core-serializables.txt        |   2 +
 .../DestroyAsyncEventQueueCommandDUnitTest.java    | 216 +++++++++++++++++++++
 .../DestroyAsyncEventQueueCommandTest.java         | 198 +++++++++++++++++++
 .../DestroyAsyncEventQueueFunctionTest.java        | 107 ++++++++++
 7 files changed, 720 insertions(+)

diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommand.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommand.java
new file mode 100644
index 0000000..c46dc9a
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommand.java
@@ -0,0 +1,79 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.IFEXISTS;
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.IFEXISTS_HELP;
+
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.management.cli.ConverterHint;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.DestroyAsyncEventQueueFunction;
+import org.apache.geode.management.internal.cli.functions.DestroyAsyncEventQueueFunctionArgs;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+public class DestroyAsyncEventQueueCommand implements GfshCommand {
+  public static final String DESTROY_ASYNC_EVENT_QUEUE = "destroy async-event-queue";
+  public static final String DESTROY_ASYNC_EVENT_QUEUE__HELP = "destroy an Async Event Queue";
+  public static final String DESTROY_ASYNC_EVENT_QUEUE__ID = "id";
+  public static final String DESTROY_ASYNC_EVENT_QUEUE__ID__HELP =
+      "ID of the queue to be destroyed.";
+  public static final String DESTROY_ASYNC_EVENT_QUEUE__GROUP__HELP =
+      "Group(s) of members on which to destroy the async event queue.";
+
+  public static final String DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND =
+      "Async event queue \"%s\" not found";
+  public static final String DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED =
+      "Async event queue \"%s\" destroyed";
+
+  @CliCommand(value = DESTROY_ASYNC_EVENT_QUEUE, help = DESTROY_ASYNC_EVENT_QUEUE__HELP)
+  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+      operation = ResourcePermission.Operation.MANAGE)
+  public Result destroyAsyncEventQueue(
+      @CliOption(key = DESTROY_ASYNC_EVENT_QUEUE__ID, mandatory = true,
+          help = DESTROY_ASYNC_EVENT_QUEUE__ID__HELP) String aeqId,
+      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
+          optionContext = ConverterHint.MEMBERGROUP,
+          help = DESTROY_ASYNC_EVENT_QUEUE__GROUP__HELP) String[] onGroups,
+      @CliOption(key = IFEXISTS, help = IFEXISTS_HELP, specifiedDefaultValue = "true",
+          unspecifiedDefaultValue = "false") boolean ifExists)
+      throws Throwable {
+    DestroyAsyncEventQueueFunctionArgs asyncEventQueueDestoryFunctionArgs =
+        new DestroyAsyncEventQueueFunctionArgs(aeqId, ifExists);
+
+    Set<DistributedMember> members = getMembers(onGroups, null);
+    List<CliFunctionResult> functionResults = executeAndGetFunctionResult(
+        new DestroyAsyncEventQueueFunction(), asyncEventQueueDestoryFunctionArgs, members);
+
+    Result commandResult = ResultBuilder.buildResult(functionResults);
+    XmlEntity xmlEntity = findXmlEntity(functionResults);
+    if (xmlEntity != null) {
+      persistClusterConfiguration(commandResult,
+          () -> getSharedConfiguration().deleteXmlEntity(xmlEntity, onGroups));
+    }
+    return commandResult;
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunction.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunction.java
new file mode 100644
index 0000000..54b3000
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunction.java
@@ -0,0 +1,80 @@
+/*
+ * 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.geode.management.internal.cli.functions;
+
+import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueImpl;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.internal.InternalEntity;
+import org.apache.geode.internal.cache.xmlcache.CacheXml;
+import org.apache.geode.management.internal.cli.commands.DestroyAsyncEventQueueCommand;
+import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+
+/**
+ * Function used by the 'destroy async-event-queue' gfsh command to destroy an asynchronous
event
+ * queue on a member.
+ */
+public class DestroyAsyncEventQueueFunction implements Function, InternalEntity {
+
+  private static final long serialVersionUID = -7754359270344102817L;
+
+  @Override
+  public void execute(FunctionContext context) {
+    String memberId = "";
+
+    DestroyAsyncEventQueueFunctionArgs aeqArgs =
+        (DestroyAsyncEventQueueFunctionArgs) context.getArguments();
+    String aeqId = aeqArgs.getId();
+    memberId = context.getMemberName();
+
+    try {
+      AsyncEventQueueImpl aeq = (AsyncEventQueueImpl) context.getCache().getAsyncEventQueue(aeqId);
+      if (aeq == null) {
+        if (aeqArgs.isIfExists()) {
+          context.getResultSender()
+              .lastResult(new CliFunctionResult(memberId, true,
+                  String.format(
+                      "Skipping: "
+                          + DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+                      aeqId)));
+        } else {
+          context.getResultSender().lastResult(new CliFunctionResult(memberId, false, String.format(
+              DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND, aeqId)));
+        }
+      } else {
+        // this is the XmlEntity that needs to be removed from the cluster config
+        XmlEntity xmlEntity = getAEQXmlEntity("id", aeqId);
+
+        aeq.stop();
+        aeq.destroy();
+        context.getResultSender()
+            .lastResult(new CliFunctionResult(memberId, xmlEntity, String.format(
+                DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED,
aeqId)));
+      }
+    } catch (Exception e) {
+      context.getResultSender().lastResult(new CliFunctionResult(memberId, e, e.getMessage()));
+    }
+  }
+
+  XmlEntity getAEQXmlEntity(String key, String value) {
+    XmlEntity xmlEntity = new XmlEntity(CacheXml.ASYNC_EVENT_QUEUE, key, value);
+    return xmlEntity;
+  }
+
+  @Override
+  public String getId() {
+    return DestroyAsyncEventQueueFunction.class.getName();
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionArgs.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionArgs.java
new file mode 100644
index 0000000..7733ea6
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionArgs.java
@@ -0,0 +1,38 @@
+/*
+ * 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.geode.management.internal.cli.functions;
+
+import java.io.Serializable;
+
+public class DestroyAsyncEventQueueFunctionArgs implements Serializable {
+
+  private static final long serialVersionUID = 1755045410754561928L;
+  private String id;
+  private boolean ifExists;
+
+
+  public DestroyAsyncEventQueueFunctionArgs(String id, boolean ifExists) {
+    this.id = id;
+    this.ifExists = ifExists;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public boolean isIfExists() {
+    return ifExists;
+  }
+}
diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index 295289b..19fea74 100644
--- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -517,6 +517,8 @@ org/apache/geode/management/internal/cli/functions/CreateIndexFunction,true,1
 org/apache/geode/management/internal/cli/functions/DataCommandFunction,true,1,optimizeForWrite:boolean
 org/apache/geode/management/internal/cli/functions/DeployFunction,true,1
 org/apache/geode/management/internal/cli/functions/DescribeDiskStoreFunction,false
+org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunction,true,-7754359270344102817
+org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionArgs,true,1755045410754561928,id:java/lang/String,ifExists:boolean
 org/apache/geode/management/internal/cli/functions/DestroyDiskStoreFunction,true,1
 org/apache/geode/management/internal/cli/functions/DestroyDiskStoreFunctionArgs,true,2296397958405313306,id:java/lang/String,ifExists:boolean
 org/apache/geode/management/internal/cli/functions/DestroyIndexFunction,true,-868082551095130315
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommandDUnitTest.java
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommandDUnitTest.java
new file mode 100644
index 0000000..0012fde
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommandDUnitTest.java
@@ -0,0 +1,216 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.distributed.internal.ClusterConfigurationService;
+import org.apache.geode.internal.cache.wan.MyAsyncEventListener;
+import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.json.GfJsonException;
+import org.apache.geode.management.internal.configuration.domain.Configuration;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+
+@Category(DistributedTest.class)
+public class DestroyAsyncEventQueueCommandDUnitTest {
+
+  private static MemberVM locator, server1, server2, server3;
+
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Rule
+  public GfshCommandRule gfsh = new GfshCommandRule();
+
+  @Before
+  public void setUp() throws Exception {
+    locator = lsRule.startLocatorVM(0);
+    server1 = lsRule.startServerVM(1, "group1", locator.getPort());
+    server2 = lsRule.startServerVM(2, locator.getPort());
+    gfsh.connectAndVerify(locator);
+  }
+
+  @Test
+  public void destroyAeq_returnsSuccess() {
+    gfsh.executeAndAssertThat(
+        "create async-event-queue --id=queue1 --listener=" + MyAsyncEventListener.class.getName())
+        .statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 2);
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess();
+
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration config = service.getConfiguration("cluster");
+      assertThat(config.getCacheXmlContent()).contains("id=\"queue1\"");
+    });
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 ").statusIsSuccess();
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess()
+        .containsOutput("No Async Event Queues Found");
+
+    // verify that aeq entry is deleted from cluster config
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration config = service.getConfiguration("cluster");
+      assertThat(config.getCacheXmlContent()).doesNotContain("id=\"queue1\"");
+    });
+  }
+
+  @Test
+  public void destroyAeqWhenQueueDoesNotExist_deafultReturnsError() {
+    gfsh.executeAndAssertThat(
+        "create async-event-queue --id=queue1 --listener=" + MyAsyncEventListener.class.getName())
+        .statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 2);
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess();
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 ").statusIsSuccess();
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 ").statusIsError();
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess()
+        .containsOutput("No Async Event Queues Found");
+  }
+
+  @Test
+  public void destroyAeqWhenQueueDoesNotExist_withIfExistsReturnsSuccess() {
+    gfsh.executeAndAssertThat(
+        "create async-event-queue --id=queue1 --listener=" + MyAsyncEventListener.class.getName())
+        .statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 2);
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess();
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 ").statusIsSuccess();
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 --if-exists")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess()
+        .containsOutput("No Async Event Queues Found");
+
+    // verify that aeq entry is deleted from cluster config
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration config = service.getConfiguration("cluster");
+      assertThat(config.getCacheXmlContent()).doesNotContain("id=\"queue1\"");
+    });
+  }
+
+  @Test
+  public void destroyAeqOnGroup_returnsSuccess() {
+    gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 --listener="
+        + MyAsyncEventListener.class.getName()).statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1);
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 --group=group1")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess()
+        .containsOutput("No Async Event Queues Found");
+
+    // verify that aeq entry is deleted from cluster config
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration config = service.getConfiguration("group1");
+      assertThat(config.getCacheXmlContent()).doesNotContain("id=\"queue1\"");
+    });
+  }
+
+  @Test
+  public void destroyAeqOnGroupThatDoesNotExisit_returnsError() {
+    gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 --listener="
+        + MyAsyncEventListener.class.getName()).statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1);
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 --group=group2")
+        .statusIsError().containsOutput(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess();
+
+    // verify that aeq entry is not deleted from cluster config
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration config = service.getConfiguration("group1");
+      assertThat(config.getCacheXmlContent()).contains("id=\"queue1\"");
+    });
+  }
+
+  @Test
+  public void destroyAeq_selectsQueuesOnGroup_showsErrorForServersNotInGroup()
+      throws GfJsonException {
+    gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 --listener="
+        + MyAsyncEventListener.class.getName()).statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1);
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess();
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1").statusIsSuccess()
+        .tableHasRowWithValues("Member", "Status", "server-1",
+            String.format(DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED,
+                "queue1"))
+        .tableHasRowWithValues("Member", "Status", "server-2",
+            String.format(
+                "ERROR: "
+                    + DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+                "queue1"));
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess()
+        .containsOutput("No Async Event Queues Found");
+  }
+
+  @Test
+  public void destroyAeq_selectsQueuesByGroup_returnsSuccess() throws GfJsonException, IOException
{
+    server3 = lsRule.startServerVM(3, "group3", locator.getPort());
+
+    gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 --listener="
+        + MyAsyncEventListener.class.getName()).statusIsSuccess();
+    gfsh.executeAndAssertThat("create async-event-queue --id=queue3 --group=group3 --listener="
+        + MyAsyncEventListener.class.getName())/* .statusIsSuccess() */;
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1);
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue3", 1);
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess();
+
+    gfsh.executeAndAssertThat("destroy async-event-queue --id=queue1 --group=group1")
+        .statusIsSuccess().containsOutput(String.format(
+            DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED, "queue1"));
+    gfsh.executeAndAssertThat("list async-event-queues").statusIsSuccess()
+        .tableHasRowWithValues("Member", "ID", "server-3", "queue3");
+
+    // verify that cluster config aeq entry for destroyed queue is deleted
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      System.out.println("cluster config: " + service.getConfiguration("cluster"));
+      Configuration config1 = service.getConfiguration("group1");
+      assertThat(config1.getCacheXmlContent()).doesNotContain("id=\"queue1\"");
+      Configuration config3 = service.getConfiguration("group3");
+      assertThat(config3.getCacheXmlContent()).contains("id=\"queue3\"");
+    });
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommandTest.java
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommandTest.java
new file mode 100644
index 0000000..04903a0
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyAsyncEventQueueCommandTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.geode.management.internal.cli.commands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.internal.ClusterConfigurationService;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
+import org.apache.geode.management.internal.cli.functions.DestroyAsyncEventQueueFunction;
+import org.apache.geode.management.internal.cli.functions.DestroyAsyncEventQueueFunctionArgs;
+import org.apache.geode.management.internal.configuration.domain.Configuration;
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.apache.geode.test.junit.rules.GfshParserRule;
+
+@Category(UnitTest.class)
+public class DestroyAsyncEventQueueCommandTest {
+  @ClassRule
+  public static GfshParserRule gfsh = new GfshParserRule();
+
+  private DestroyAsyncEventQueueCommand command;
+  private ClusterConfigurationService service;
+  private Map<String, Configuration> configurationMap;
+  private DistributedMember member1 = mock(DistributedMember.class);
+  private DistributedMember member2 = mock(DistributedMember.class);
+  private Set<DistributedMember> members;
+  private ResultCollector collector;
+  private InternalCache cache;
+  private List<CliFunctionResult> functionResults;
+
+  @Before
+  public void setUp() throws Exception {
+    command = spy(DestroyAsyncEventQueueCommand.class);
+
+    cache = mock(InternalCache.class);
+    doReturn(cache).when(command).getCache();
+
+
+    functionResults = new ArrayList<>();
+    doReturn(functionResults).when(command).executeAndGetFunctionResult(
+        any(DestroyAsyncEventQueueFunction.class), any(DestroyAsyncEventQueueFunctionArgs.class),
+        any(Set.class));
+
+    members = new HashSet<>();
+    doReturn(members).when(command).getMembers(any(), any());
+  }
+
+  @Test
+  public void mandatoryOption() throws Exception {
+    gfsh.executeAndAssertThat(command, "destroy async-event-queue").statusIsError()
+        .containsOutput("Invalid command");
+  }
+
+  @Test
+  public void noOptionalGroup_successful() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    functionResults.add(new CliFunctionResult("member2", true, String.format(
+        DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED, "queue1")));
+    functionResults.add(new CliFunctionResult("member1", true, String.format(
+        DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED, "queue1")));
+
+    gfsh.executeAndAssertThat(command, "destroy async-event-queue --id=queue1").statusIsSuccess()
+        .containsOutput("\\\"queue1\\\" destroyed").tableHasRowCount("Member", 2);
+  }
+
+  @Test
+  public void ifExistsSpecified_defaultIsTrue() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    functionResults.add(new CliFunctionResult("member1", true,
+        String.format(
+            "Skipping: " + DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "nonexistentQueue")));
+    functionResults.add(new CliFunctionResult("member2", true,
+        String.format(
+            "Skipping: " + DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "nonexistentQueue")));
+    ArgumentCaptor<DestroyAsyncEventQueueFunctionArgs> argCaptor =
+        ArgumentCaptor.forClass(DestroyAsyncEventQueueFunctionArgs.class);
+
+    gfsh.executeAndAssertThat(command,
+        "destroy async-event-queue --id=nonexistentQueue --if-exists")
+        .tableHasRowCount("Member", 2);
+    verify(command).executeAndGetFunctionResult(any(), argCaptor.capture(), eq(members));
+    assertThat(argCaptor.getValue().isIfExists()).isEqualTo(true);
+  }
+
+  @Test
+  public void ifExistsNotSpecified_isFalse() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    functionResults.add(new CliFunctionResult("member1", false,
+        String.format(DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "nonexistentQueue")));
+    functionResults.add(new CliFunctionResult("member2", false,
+        String.format(DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "nonexistentQueue")));
+    ArgumentCaptor<DestroyAsyncEventQueueFunctionArgs> argCaptor =
+        ArgumentCaptor.forClass(DestroyAsyncEventQueueFunctionArgs.class);
+
+    gfsh.executeAndAssertThat(command, "destroy async-event-queue --id=nonexistentQueue")
+        .statusIsError().tableHasRowCount("Member", 2);
+    verify(command).executeAndGetFunctionResult(any(), argCaptor.capture(), eq(members));
+    assertThat(argCaptor.getValue().isIfExists()).isEqualTo(false);
+  }
+
+  @Test
+  public void ifExistsSpecifiedFalse() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    ArgumentCaptor<DestroyAsyncEventQueueFunctionArgs> argCaptor =
+        ArgumentCaptor.forClass(DestroyAsyncEventQueueFunctionArgs.class);
+    gfsh.executeAndAssertThat(command,
+        "destroy async-event-queue --id=nonexistentQueue --if-exists=false");
+
+    verify(command).executeAndGetFunctionResult(any(), argCaptor.capture(), eq(members));
+    assertThat(argCaptor.getValue().isIfExists()).isEqualTo(false);
+  }
+
+  @Test
+  public void ifExistsSpecifiedTrue() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    functionResults.add(new CliFunctionResult("member1", false,
+        String.format(DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "nonexistentQueue")));
+    functionResults.add(new CliFunctionResult("member2", false,
+        String.format(DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "nonexistentQueue")));
+    ArgumentCaptor<DestroyAsyncEventQueueFunctionArgs> argCaptor =
+        ArgumentCaptor.forClass(DestroyAsyncEventQueueFunctionArgs.class);
+
+    gfsh.executeAndAssertThat(command,
+        "destroy async-event-queue --id=nonexistentQueue --if-exists=true");
+    verify(command).executeAndGetFunctionResult(any(), argCaptor.capture(), eq(members));
+    assertThat(argCaptor.getValue().isIfExists()).isEqualTo(true);
+  }
+
+  @Test
+  public void mixedFunctionResults_returnsSuccess() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    functionResults.add(new CliFunctionResult("member2", false, String.format(
+        DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND, "queue1")));
+    functionResults.add(new CliFunctionResult("member1", true, String.format(
+        DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED, "queue1")));
+
+    gfsh.executeAndAssertThat(command, "destroy async-event-queue --id=queue1").statusIsSuccess();
+  }
+
+  @Test
+  public void mixedFunctionResultsWithIfExists_returnsSuccess() throws Exception {
+    members.add(member1);
+    members.add(member2);
+    functionResults.add(new CliFunctionResult("member1", true,
+        String.format(
+            "Skipping: " + DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_NOT_FOUND,
+            "queue1")));
+    functionResults.add(new CliFunctionResult("member1", true, String.format(
+        DestroyAsyncEventQueueCommand.DESTROY_ASYNC_EVENT_QUEUE__AEQ_0_DESTROYED, "queue1")));
+
+    gfsh.executeAndAssertThat(command, "destroy async-event-queue --id=queue1 --if-exists")
+        .statusIsSuccess();
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionTest.java
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionTest.java
new file mode 100644
index 0000000..7caec8c
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/DestroyAsyncEventQueueFunctionTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.geode.management.internal.cli.functions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+
+import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
+import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueImpl;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.management.internal.configuration.domain.XmlEntity;
+import org.apache.geode.test.fake.Fakes;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class DestroyAsyncEventQueueFunctionTest {
+
+  private static final String TEST_AEQ_ID = "Test-AEQ";
+  private AsyncEventQueue mockAEQ;
+  private FunctionContext mockContext;
+  private DestroyAsyncEventQueueFunctionArgs mockArgs;
+  private GemFireCacheImpl cache;
+  private ResultSender resultSender;
+  private ArgumentCaptor<CliFunctionResult> resultCaptor;
+  private DestroyAsyncEventQueueFunction function;
+
+  @Before
+  public void setUp() throws Exception {
+    mockAEQ = mock(AsyncEventQueueImpl.class);
+    mockContext = mock(FunctionContext.class);
+    mockArgs = mock(DestroyAsyncEventQueueFunctionArgs.class);
+    cache = Fakes.cache();
+    function = spy(DestroyAsyncEventQueueFunction.class);
+    resultSender = mock(ResultSender.class);
+
+    when(mockContext.getCache()).thenReturn(cache);
+    when(mockContext.getArguments()).thenReturn(mockArgs);
+    when(mockArgs.getId()).thenReturn(TEST_AEQ_ID);
+    when(mockAEQ.getId()).thenReturn(TEST_AEQ_ID);
+    when(mockContext.getResultSender()).thenReturn(resultSender);
+    resultCaptor = ArgumentCaptor.forClass(CliFunctionResult.class);
+  }
+
+  @Test
+  public void execute_validAeqId_OK() throws Throwable {
+    XmlEntity xmlEntity = mock(XmlEntity.class);
+    doReturn(xmlEntity).when(function).getAEQXmlEntity(anyString(), anyString());
+    when(cache.getAsyncEventQueue(TEST_AEQ_ID)).thenReturn(mockAEQ);
+
+    function.execute(mockContext);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = resultCaptor.getValue();
+
+    assertThat(result.isSuccessful()).isTrue();
+    assertThat(result.getXmlEntity()).isNotNull();
+    assertThat(result.getThrowable()).isNull();
+  }
+
+  @Test
+  public void execute_nonexistentAeqId_returnsError() throws Throwable {
+    when(cache.getAsyncEventQueue(TEST_AEQ_ID)).thenReturn(null);
+
+    function.execute(mockContext);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = resultCaptor.getValue();
+
+    assertThat(result.isSuccessful()).isFalse();
+    assertThat(result.getMessage()).containsPattern(TEST_AEQ_ID + ".*not found");
+  }
+
+  @Test
+  public void execute_nonexistentAeqIdIfExists_returnsSuccess() throws Throwable {
+    when(cache.getAsyncEventQueue(TEST_AEQ_ID)).thenReturn(null);
+    when(mockArgs.isIfExists()).thenReturn(true);
+
+    function.execute(mockContext);
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = resultCaptor.getValue();
+
+    assertThat(result.isSuccessful()).isTrue();
+    assertThat(result.getMessage()).containsPattern("Skipping:.*" + TEST_AEQ_ID + ".*not
found");
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@geode.apache.org" <commits@geode.apache.org>'].

Mime
View raw message