You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by GitBox <gi...@apache.org> on 2021/02/17 03:26:15 UTC

[GitHub] [james-project] Arsnael commented on a change in pull request #297: JAMES-3400 Add remove and list domain aliases

Arsnael commented on a change in pull request #297:
URL: https://github.com/apache/james-project/pull/297#discussion_r577279603



##########
File path: server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/AddDomainAliasCommand.java
##########
@@ -0,0 +1,64 @@
+/******************************************************************
+ * 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.james.cli.domain;
+
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.DomainClient;
+
+import feign.Response;
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "addAlias",
+    description = "Create a new domain alias")
+public class AddDomainAliasCommand implements Callable<Integer> {
+
+    public static final int CREATED_CODE = 204;
+
+    @CommandLine.ParentCommand DomainCommand domainCommand;
+
+    @CommandLine.Parameters(description = "Destination of the domain alias. This is the domain this alis belongs to.")
+    String destinationDomain;
+
+    @CommandLine.Parameters(description = "Source of the domain alis.")

Review comment:
       s/alis/alias

##########
File path: server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/SetGlobalQuotaCountCommand.java
##########
@@ -0,0 +1,57 @@
+/******************************************************************
+ * 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.james.cli.quota;
+
+import static org.apache.james.cli.domain.DomainDeleteCommand.DELETED_CODE;
+
+import java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.QuotaClient;
+
+import feign.Response;
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "set",
+    description = "Quota counts limit that applies for all users")
+public class SetGlobalQuotaCountCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaCountCommand parentCommand;
+
+    @CommandLine.Parameters
+    Long count;
+
+    @Override
+    public Integer call() {
+        try {
+            QuotaClient quotaClient = parentCommand.parentCommand.quotaCommand.fullyQualifiedURL();
+            Response rs = quotaClient.setQuotaCount(count);
+            if (rs.status() == DELETED_CODE) {

Review comment:
       DELETED_CODE for a set?
   
   I see similar occurences as well... After rechecking the code, it seems those status code are generally declared locally in each class. However, I think they should be extracted and centralized in a proper class.
   
   WDYT?

##########
File path: server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/RemoveDomainAliasCommand.java
##########
@@ -0,0 +1,61 @@
+/******************************************************************
+ * 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.james.cli.domain;
+
+import java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.DomainClient;
+
+import feign.Response;
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "removeAlias",
+    description = "Remove a domain alias")
+public class RemoveDomainAliasCommand implements Callable<Integer> {
+
+    public static final int CREATED_CODE = 204;
+
+    @CommandLine.ParentCommand DomainCommand domainCommand;
+
+    @CommandLine.Parameters(description = "Destination of the domain alias. This is the domain this alis belongs to.")
+    String destinationDomain;
+
+    @CommandLine.Parameters(description = "Source of the domain alis.")

Review comment:
       s/alis/alias

##########
File path: server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/AddDomainAliasCommand.java
##########
@@ -0,0 +1,64 @@
+/******************************************************************
+ * 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.james.cli.domain;
+
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.DomainClient;
+
+import feign.Response;
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "addAlias",
+    description = "Create a new domain alias")
+public class AddDomainAliasCommand implements Callable<Integer> {
+
+    public static final int CREATED_CODE = 204;
+
+    @CommandLine.ParentCommand DomainCommand domainCommand;
+
+    @CommandLine.Parameters(description = "Destination of the domain alias. This is the domain this alis belongs to.")

Review comment:
       s/alis/alias

##########
File path: server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/domain/RemoveDomainAliasCommand.java
##########
@@ -0,0 +1,61 @@
+/******************************************************************
+ * 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.james.cli.domain;
+
+import java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.DomainClient;
+
+import feign.Response;
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "removeAlias",
+    description = "Remove a domain alias")
+public class RemoveDomainAliasCommand implements Callable<Integer> {
+
+    public static final int CREATED_CODE = 204;
+
+    @CommandLine.ParentCommand DomainCommand domainCommand;
+
+    @CommandLine.Parameters(description = "Destination of the domain alias. This is the domain this alis belongs to.")

Review comment:
       s/alis/alias

##########
File path: server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/QuotaManageTest.java
##########
@@ -0,0 +1,210 @@
+/******************************************************************
+ * 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.james.cli;
+
+import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.apache.james.util.Port;
+import org.apache.james.utils.WebAdminGuiceProbe;
+import org.apache.james.webadmin.integration.WebadminIntegrationTestModule;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.google.common.collect.ImmutableList;
+
+public class QuotaManageTest {
+    @RegisterExtension
+    static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
+            .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
+                    .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
+                    .overrideWith(new WebadminIntegrationTestModule())
+                    .overrideWith(new TestJMAPServerModule()))
+            .build();
+
+    private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
+    private final ByteArrayOutputStream errorStreamCaptor = new ByteArrayOutputStream();
+
+    Port port;
+
+    @BeforeEach
+    void setUp(GuiceJamesServer server) {
+        port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+    }
+
+    @AfterEach
+    void tearDown() {
+        System.err.println(new String(errorStreamCaptor.toByteArray(), StandardCharsets.UTF_8));
+    }
+
+    @Nested
+    class Global {
+        @Nested
+        class Count {
+            @Test
+            void getShouldReturnNoneByDefault() {
+                int exitCode = executeFluent("quota", "global", "count", "get");
+
+                SoftAssertions.assertSoftly( softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("No global quota defined".toCharArray());
+                });
+            }
+
+            @Test
+            void getShouldReturnSetValue() {
+                executeFluent("quota", "global", "count", "set", "128");
+
+                int exitCode = executeFluent("quota", "global", "count", "get");
+
+                SoftAssertions.assertSoftly( softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("128".toCharArray());
+                });
+            }
+
+            @Test
+            void getShouldNotReturnDeletedValue() {
+                executeFluent("quota", "global", "count", "set", "128");
+
+                executeFluent("quota", "global", "count", "delete");
+
+                int exitCode = executeFluent("quota", "global", "count", "get");
+
+                SoftAssertions.assertSoftly(softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("No global quota defined".toCharArray());
+                });
+            }
+
+            @Test
+            void deleteShouldBeIdempotent() {
+                executeFluent("quota", "global", "count", "delete");
+                int exitCode = executeFluent("quota", "global", "count", "delete");
+
+                assertThat(exitCode).isEqualTo(0);
+            }
+
+            @Test
+            void setShouldRespectLastWriteWin() {
+                executeFluent("quota", "global", "count", "set", "128");
+                executeFluent("quota", "global", "count", "set", "256");
+
+                int exitCode = executeFluent("quota", "global", "count", "get");
+
+                SoftAssertions.assertSoftly(softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("256".toCharArray());
+                });
+            }
+        }
+
+        @Nested
+        class Size {
+            @Test
+            void getShouldReturnNoneByDefault() {
+                int exitCode = executeFluent("quota", "global", "size", "get");
+
+                SoftAssertions.assertSoftly( softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("No global quota defined".toCharArray());
+                });
+            }
+
+            @Test
+            void getShouldReturnSetValue() {
+                executeFluent("quota", "global", "size", "set", "128");
+
+                int exitCode = executeFluent("quota", "global", "size", "get");
+
+                SoftAssertions.assertSoftly( softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("128 bytes".toCharArray());
+                });
+            }
+
+            @Test
+            void unitsShouldBeSupported() {
+                executeFluent("quota", "global", "size", "set", "128M");
+
+                int exitCode = executeFluent("quota", "global", "size", "get");
+
+                SoftAssertions.assertSoftly( softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("128 MB".toCharArray());
+                });
+            }
+
+            @Test
+            void getShouldNotReturnDeletedValue() {
+                executeFluent("quota", "global", "size", "set", "128");
+
+                executeFluent("quota", "global", "size", "delete");
+
+                int exitCode = executeFluent("quota", "global", "size", "get");
+
+                SoftAssertions.assertSoftly(softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("No global quota defined".toCharArray());
+                });
+            }
+
+            @Test
+            void deleteShouldBeIdempotent() {
+                executeFluent("quota", "global", "size", "delete");
+                int exitCode = executeFluent("quota", "global", "size", "delete");
+
+                assertThat(exitCode).isEqualTo(0);
+            }
+
+            @Test
+            void setShouldRespectLastWriteWin() {
+                executeFluent("quota", "global", "size", "set", "128");
+                executeFluent("quota", "global", "size", "set", "256");
+
+                int exitCode = executeFluent("quota", "global", "size", "get");
+
+                SoftAssertions.assertSoftly(softly -> {
+                    assertThat(exitCode).isEqualTo(0);
+                    assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("256 bytes".toCharArray());
+                });
+            }
+        }
+    }
+
+    int executeFluent(String... args) {

Review comment:
       private? 

##########
File path: server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/DomainManageTest.java
##########
@@ -48,113 +54,183 @@
     private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();
     private final ByteArrayOutputStream errorStreamCaptor = new ByteArrayOutputStream();
 
-    @Test
-    void domainListCommandShouldWShowOnlyDefaultDomain(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+    Port port;
 
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-                "--url", "http://127.0.0.1:" + port.getValue(), "domain", "list");
-        assertThat(exitCode).isEqualTo(0);
-        assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("localhost".toCharArray());
+    @BeforeEach
+    void setUp(GuiceJamesServer server) {
+        port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+    }
+
+    @AfterEach
+    void tearDown() {
+        System.err.println(new String(errorStreamCaptor.toByteArray(), StandardCharsets.UTF_8));
     }
 
     @Test
-    void domainCreateCommandWithValidNameShouldSuccessfully(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+    void domainListCommandShouldWShowOnlyDefaultDomain() {
+        int exitCode = executeFluent("domain", "list");
 
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "create", "linagora.com");
+        SoftAssertions.assertSoftly( softly -> {
+            assertThat(exitCode).isEqualTo(0);
+            assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("localhost".toCharArray());
+        });
+    }
 
-        WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "list");
+    @Test
+    void domainCreateCommandWithValidNameShouldSuccessfully() {
+        int exitCode = executeFluent("domain", "create", "linagora.com");
 
-        assertThat(exitCode).isEqualTo(0);
-        assertThat(outputStreamCaptor.toString()).contains("linagora.com");
+        executeFluent("domain", "list");
+
+        SoftAssertions.assertSoftly( softly -> {
+            assertThat(exitCode).isEqualTo(0);
+            assertThat(outputStreamCaptor.toString()).contains("linagora.com");
+        });
     }
 
     @Test
-    void domainCreateCommandWithInvalidNameShouldFailed(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
-
-        int exitCode1 = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "create", "@linagora.com");
+    void domainCreateCommandWithInvalidNameShouldFailed() {
+        int exitCode1 = executeFluent("domain", "create", "@linagora.com");
 
-        int exitCode2 = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "create", "linagora.com/");
+        int exitCode2 = executeFluent("domain", "create", "linagora.com/");
 
-        int exitCode3 = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "create", "");
+        int exitCode3 = executeFluent("domain", "create", "");
 
         WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
             "--url", "http://127.0.0.1:" + port.getValue(), "domain", "list");
 
-        assertThat(exitCode1).isEqualTo(1);
-        assertThat(exitCode2).isEqualTo(1);
-        assertThat(exitCode3).isEqualTo(1);
-        assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("localhost".toCharArray());
+        SoftAssertions.assertSoftly( softly -> {
+            assertThat(exitCode1).isEqualTo(1);
+            assertThat(exitCode2).isEqualTo(1);
+            assertThat(exitCode3).isEqualTo(1);
+            assertThat(outputStreamCaptor.toString().trim().toCharArray()).containsOnly("localhost".toCharArray());
+        });
     }
 
     @Test
-    void domainDeleteCommandWithValidDomainShouldSucceed(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+    void domainDeleteCommandWithValidDomainShouldSucceed() {
+        executeFluent("domain", "create", "linagora.com");
 
-        WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "create", "linagora.com");
-
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "delete", "linagora.com");
+        int exitCode = executeFluent("domain", "delete", "linagora.com");
 
-        WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "list");
+        executeFluent("domain", "list");
 
-        assertThat(exitCode).isEqualTo(0);
-        assertThat(outputStreamCaptor.toString().contains("linagora.com")).isFalse();
+        SoftAssertions.assertSoftly( softly -> {
+            assertThat(exitCode).isEqualTo(0);
+            assertThat(outputStreamCaptor.toString().contains("linagora.com")).isFalse();
+        });
     }
 
     @Test
-    void domainDeleteCommandWithDefaultDomainShouldFail(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
-
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "delete", "localhost");
+    void domainDeleteCommandWithDefaultDomainShouldFail() {
+        int exitCode = executeFluent("domain", "delete", "localhost");
 
         assertThat(exitCode).isEqualTo(1);
     }
 
     @Test
-    void domainExistCommandWithDefaultDomainShouldExist(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
-
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "exist", "localhost");
+    void domainExistCommandWithDefaultDomainShouldExist() {
+        int exitCode = executeFluent("domain", "exist", "localhost");
 
-        assertThat(exitCode).isEqualTo(0);
-        assertThat(outputStreamCaptor.toString().trim()).isEqualTo("localhost exists");
+        SoftAssertions.assertSoftly( softly -> {
+            assertThat(exitCode).isEqualTo(0);
+            assertThat(outputStreamCaptor.toString().trim()).isEqualTo("localhost exists");
+        });
     }
 
     @Test
-    void domainExistCommandWithNonExistingDomainShouldFail(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
-
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "exist", "linagora.com");
+    void domainExistCommandWithNonExistingDomainShouldFail() {
+        int exitCode = executeFluent("domain", "exist", "linagora.com");
 
         assertThat(exitCode).isEqualTo(0);
         assertThat(outputStreamCaptor.toString().trim()).isEqualTo("linagora.com does not exist");
     }
 
     @Test
-    void domainExistCommandWithAddedDomainShouldSucceed(GuiceJamesServer server) {
-        Port port = server.getProbe(WebAdminGuiceProbe.class).getWebAdminPort();
+    void domainExistCommandWithAddedDomainShouldSucceed() {
+        executeFluent("domain", "create", "linagora.com");
 
-        WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "create", "linagora.com");
+        int exitCode = executeFluent("domain", "exist", "linagora.com");
 
-        int exitCode = WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
-            "--url", "http://127.0.0.1:" + port.getValue(), "domain", "exist", "linagora.com");
+        SoftAssertions.assertSoftly( softly -> {
+            assertThat(exitCode).isEqualTo(0);
+            assertThat(outputStreamCaptor.toString().trim()).isEqualTo("linagora.com exists");
+        });
+    }
 
-        assertThat(exitCode).isEqualTo(0);
-        assertThat(outputStreamCaptor.toString().trim()).isEqualTo("linagora.com exists");
+    @Nested
+    class DomainAliases {
+        @BeforeEach
+        void setUp() {
+            executeFluent("domain", "create", "linagora.com");
+            executeFluent("domain", "create", "linagora-james.com");
+        }
+
+        @Test
+        void listDomainAliasShouldReturnEmptyByDefault() {
+            int exitCode = executeFluent("domain", "listAliases", "linagora.com");
+
+            SoftAssertions.assertSoftly( softly -> {
+                assertThat(exitCode).isEqualTo(0);
+                assertThat(outputStreamCaptor.toString().trim()).hasSize(0);
+            });
+        }
+
+        @Test
+        void addDomainAliasShouldBeIdempotent() {
+            executeFluent("domain", "addAlias", "linagora.com", "linagora-james.com");
+            int exitCode = executeFluent("domain", "addAlias", "linagora.com", "linagora-james.com");
+
+            assertThat(exitCode).isEqualTo(0);
+        }
+
+        @Test
+        void removeDomainAliasShouldBeIdempotent() {
+            int exitCode = executeFluent("domain", "removeAlias", "linagora.com", "linagora-james.com");
+
+            assertThat(exitCode).isEqualTo(0);
+        }
+
+        @Test
+        void listDomainAliasShouldNotReturnRemovedValues() {
+            executeFluent("domain", "addAlias", "linagora.com", "linagora-james.com");
+            executeFluent("domain", "removeAlias", "linagora.com", "linagora-james.com");
+
+            int exitCode = executeFluent("domain", "listAliases", "linagora.com");
+
+            SoftAssertions.assertSoftly( softly -> {
+                assertThat(exitCode).isEqualTo(0);
+                assertThat(outputStreamCaptor.toString().trim()).hasSize(0);
+            });
+        }
+
+        @Test
+        void listDomainAliasShouldReturnAddedValues() {
+            executeFluent("domain", "addAlias", "linagora.com", "linagora-james.com");
+
+            int exitCode = executeFluent("domain", "listAliases", "linagora.com");
+
+            SoftAssertions.assertSoftly( softly -> {
+                assertThat(exitCode).isEqualTo(0);
+                assertThat(outputStreamCaptor.toString().trim()).contains("linagora-james.com");
+            });
+        }
+
+        @Test
+        void addAliasShouldRequireAManageDomain() {
+            int exitCode = executeFluent("domain", "addAlias", "linagora.com", "unknown.com");
+
+            SoftAssertions.assertSoftly( softly -> {
+                assertThat(exitCode).isEqualTo(1);
+                assertThat(errorStreamCaptor.toString().trim()).isEqualTo("{\"statusCode\":404,\"type\":\"InvalidArgument\",\"message\":\"The domain list does not contain: unknown.com\",\"details\":null}");
+            });
+        }
     }
 
+    int executeFluent(String... args) {

Review comment:
       private?




----------------------------------------------------------------
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.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org