You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/02/25 09:06:57 UTC

[james-project] 09/12: JAMES-3477 WebAdmin CLI commands to manage global quotas

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit bbb46daa0b9de75224f288ccf90a7923ba8d37ae
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Mon Feb 15 16:20:37 2021 +0700

    JAMES-3477 WebAdmin CLI commands to manage global quotas
---
 server/protocols/webadmin-cli/pom.xml              |  12 +-
 .../java/org/apache/james/cli/WebAdminCli.java     |   2 +
 .../cli/quota/DeleteGlobalQuotaCountCommand.java   |  54 ++++++
 .../cli/quota/DeleteGlobalQuotaSizeCommand.java    |  54 ++++++
 .../cli/quota/GetGlobalQuotaCountCommand.java      |  51 +++++
 .../james/cli/quota/GetGlobalQuotaSizeCommand.java |  52 +++++
 .../apache/james/cli/quota/GlobalQuotaCommand.java |  43 +++++
 .../james/cli/quota/GlobalQuotaCountCommand.java   |  44 +++++
 .../james/cli/quota/GlobalQuotaSizeCommand.java    |  44 +++++
 .../org/apache/james/cli/quota/QuotaCommand.java   |  56 ++++++
 .../cli/quota/SetGlobalQuotaCountCommand.java      |  57 ++++++
 .../james/cli/quota/SetGlobalQuotaSizeCommand.java |  58 ++++++
 .../org/apache/james/httpclient/QuotaClient.java   |  43 +++++
 .../java/org/apache/james/cli/QuotaManageTest.java | 210 +++++++++++++++++++++
 14 files changed, 776 insertions(+), 4 deletions(-)

diff --git a/server/protocols/webadmin-cli/pom.xml b/server/protocols/webadmin-cli/pom.xml
index bdfe312..ee31404 100644
--- a/server/protocols/webadmin-cli/pom.xml
+++ b/server/protocols/webadmin-cli/pom.xml
@@ -45,17 +45,21 @@
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-webadmin-integration-test-common</artifactId>
+            <artifactId>james-server-memory-guice</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
-            <artifactId>testing-base</artifactId>
+            <artifactId>james-server-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-webadmin-integration-test-common</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>${project.groupId}</groupId>
-            <artifactId>james-server-memory-guice</artifactId>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
index 02acc00..817963a 100644
--- a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/WebAdminCli.java
@@ -26,6 +26,7 @@ import java.util.concurrent.Callable;
 
 import org.apache.james.cli.domain.DomainCommand;
 import org.apache.james.cli.mailbox.MailboxCommand;
+import org.apache.james.cli.quota.QuotaCommand;
 import org.apache.james.cli.user.UserCommand;
 import org.apache.james.httpclient.FeignClientFactory;
 import org.apache.james.httpclient.JwtToken;
@@ -78,6 +79,7 @@ public class WebAdminCli implements Callable<Integer> {
             .addSubcommand(new DomainCommand(out, parent, err))
             .addSubcommand(new UserCommand(out, parent, err))
             .addSubcommand(new MailboxCommand(out, parent, err))
+            .addSubcommand(new QuotaCommand(out, parent, err))
             .execute(args);
     }
 
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/DeleteGlobalQuotaCountCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/DeleteGlobalQuotaCountCommand.java
new file mode 100644
index 0000000..829d88a
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/DeleteGlobalQuotaCountCommand.java
@@ -0,0 +1,54 @@
+/******************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one     *
+ * or more contributor license agreements.  See the NOTICE file   *
+ * distributed with this work for additional information          *
+ * regarding copyright ownership.  The ASF licenses this file     *
+ * to you under the Apache License, Version 2.0 (the              *
+ * "License"); you may not use this file except in compliance     *
+ * with the License.  You may obtain a copy of the License at     *
+ *                                                                *
+ * http://www.apache.org/licenses/LICENSE-2.0                     *
+ *                                                                *
+ * Unless required by applicable law or agreed to in writing,     *
+ * software distributed under the License is distributed on an    *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY         *
+ * KIND, either express or implied.  See the License for the      *
+ * specific language governing permissions and limitations        *
+ * under the License.                                             *
+ ******************************************************************/
+
+package org.apache.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 = "delete",
+    description = "Delete quota counts limit that applies for all users")
+public class DeleteGlobalQuotaCountCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaCountCommand parentCommand;
+
+    @Override
+    public Integer call() {
+        try {
+            QuotaClient quotaClient = parentCommand.parentCommand.quotaCommand.fullyQualifiedURL();
+            Response rs = quotaClient.deleteQuotaCount();
+            if (rs.status() == DELETED_CODE) {
+                return WebAdminCli.CLI_FINISHED_SUCCEED;
+            } else {
+                return WebAdminCli.CLI_FINISHED_FAILED;
+            }
+        } catch (Exception e) {
+            e.printStackTrace(parentCommand.parentCommand.quotaCommand.err);
+            return WebAdminCli.CLI_FINISHED_FAILED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/DeleteGlobalQuotaSizeCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/DeleteGlobalQuotaSizeCommand.java
new file mode 100644
index 0000000..1aecc73
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/DeleteGlobalQuotaSizeCommand.java
@@ -0,0 +1,54 @@
+/******************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one     *
+ * or more contributor license agreements.  See the NOTICE file   *
+ * distributed with this work for additional information          *
+ * regarding copyright ownership.  The ASF licenses this file     *
+ * to you under the Apache License, Version 2.0 (the              *
+ * "License"); you may not use this file except in compliance     *
+ * with the License.  You may obtain a copy of the License at     *
+ *                                                                *
+ * http://www.apache.org/licenses/LICENSE-2.0                     *
+ *                                                                *
+ * Unless required by applicable law or agreed to in writing,     *
+ * software distributed under the License is distributed on an    *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY         *
+ * KIND, either express or implied.  See the License for the      *
+ * specific language governing permissions and limitations        *
+ * under the License.                                             *
+ ******************************************************************/
+
+package org.apache.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 = "delete",
+    description = "Delete quota sizes limit that applies for all users")
+public class DeleteGlobalQuotaSizeCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaSizeCommand parentCommand;
+
+    @Override
+    public Integer call() {
+        try {
+            QuotaClient quotaClient = parentCommand.parentCommand.quotaCommand.fullyQualifiedURL();
+            Response rs = quotaClient.deleteQuotaSize();
+            if (rs.status() == DELETED_CODE) {
+                return WebAdminCli.CLI_FINISHED_SUCCEED;
+            } else {
+                return WebAdminCli.CLI_FINISHED_FAILED;
+            }
+        } catch (Exception e) {
+            e.printStackTrace(parentCommand.parentCommand.quotaCommand.err);
+            return WebAdminCli.CLI_FINISHED_FAILED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GetGlobalQuotaCountCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GetGlobalQuotaCountCommand.java
new file mode 100644
index 0000000..3270e90
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GetGlobalQuotaCountCommand.java
@@ -0,0 +1,51 @@
+/******************************************************************
+ * 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 java.util.Optional;
+import java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.QuotaClient;
+
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "get",
+    description = "Get quota counts limit that applies for all users")
+public class GetGlobalQuotaCountCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaCountCommand parentCommand;
+
+    @Override
+    public Integer call() {
+        try {
+            QuotaClient quotaClient = parentCommand.parentCommand.quotaCommand.fullyQualifiedURL();
+            String message = Optional.ofNullable(quotaClient.getQuotaCount())
+                .map(Object::toString)
+                .orElse("No global quota defined");
+            parentCommand.parentCommand.quotaCommand.out.println(message);
+            return WebAdminCli.CLI_FINISHED_SUCCEED;
+        } catch (Exception e) {
+            e.printStackTrace(parentCommand.parentCommand.quotaCommand.err);
+            return WebAdminCli.CLI_FINISHED_FAILED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GetGlobalQuotaSizeCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GetGlobalQuotaSizeCommand.java
new file mode 100644
index 0000000..24eca51
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GetGlobalQuotaSizeCommand.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.james.cli.quota;
+
+import java.util.Optional;
+import java.util.concurrent.Callable;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.QuotaClient;
+
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "get",
+    description = "Get quota sizes limit that applies for all users")
+public class GetGlobalQuotaSizeCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaSizeCommand parentCommand;
+
+    @Override
+    public Integer call() {
+        try {
+            QuotaClient quotaClient = parentCommand.parentCommand.quotaCommand.fullyQualifiedURL();
+            String message = Optional.ofNullable(quotaClient.getQuotaSize())
+                .map(FileUtils::byteCountToDisplaySize)
+                .orElse("No global quota defined");
+            parentCommand.parentCommand.quotaCommand.out.println(message);
+            return WebAdminCli.CLI_FINISHED_SUCCEED;
+        } catch (Exception e) {
+            e.printStackTrace(parentCommand.parentCommand.quotaCommand.err);
+            return WebAdminCli.CLI_FINISHED_FAILED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaCommand.java
new file mode 100644
index 0000000..0b17c76
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaCommand.java
@@ -0,0 +1,43 @@
+/******************************************************************
+ * 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 java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "global",
+    description = "Quota that applies for all users",
+    subcommands = {
+        GlobalQuotaCountCommand.class,
+        GlobalQuotaSizeCommand.class
+    })
+public class GlobalQuotaCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    QuotaCommand quotaCommand;
+
+    @Override
+    public Integer call() {
+        return WebAdminCli.CLI_FINISHED_SUCCEED;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaCountCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaCountCommand.java
new file mode 100644
index 0000000..bd4ee8d
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaCountCommand.java
@@ -0,0 +1,44 @@
+/******************************************************************
+ * 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 java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "count",
+    description = "Quota counts limit that applies for all users",
+    subcommands = {
+        DeleteGlobalQuotaCountCommand.class,
+        GetGlobalQuotaCountCommand.class,
+        SetGlobalQuotaCountCommand.class
+    })
+public class GlobalQuotaCountCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaCommand parentCommand;
+
+    @Override
+    public Integer call() {
+        return WebAdminCli.CLI_FINISHED_SUCCEED;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaSizeCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaSizeCommand.java
new file mode 100644
index 0000000..e0e77dd
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/GlobalQuotaSizeCommand.java
@@ -0,0 +1,44 @@
+/******************************************************************
+ * 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 java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "size",
+    description = "Quota sizes limit that applies for all users",
+    subcommands = {
+        DeleteGlobalQuotaSizeCommand.class,
+        GetGlobalQuotaSizeCommand.class,
+        SetGlobalQuotaSizeCommand.class
+    })
+public class GlobalQuotaSizeCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaCommand parentCommand;
+
+    @Override
+    public Integer call() {
+        return WebAdminCli.CLI_FINISHED_SUCCEED;
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/QuotaCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/QuotaCommand.java
new file mode 100644
index 0000000..c3bf9b3
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/QuotaCommand.java
@@ -0,0 +1,56 @@
+/******************************************************************
+ * 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 java.io.PrintStream;
+import java.util.concurrent.Callable;
+
+import org.apache.james.cli.WebAdminCli;
+import org.apache.james.httpclient.QuotaClient;
+
+import picocli.CommandLine;
+
+@CommandLine.Command(
+        name = "quota",
+        description = "Manage Quotas",
+        subcommands = {
+            GlobalQuotaCommand.class
+        })
+public class QuotaCommand implements Callable<Integer> {
+
+    protected final WebAdminCli webAdminCli;
+    protected final PrintStream out;
+    protected final PrintStream err;
+
+    public QuotaCommand(PrintStream out, WebAdminCli webAdminCli, PrintStream err) {
+        this.out = out;
+        this.webAdminCli = webAdminCli;
+        this.err = err;
+    }
+
+    @Override
+    public Integer call() {
+        return WebAdminCli.CLI_FINISHED_SUCCEED;
+    }
+
+    public QuotaClient fullyQualifiedURL() {
+        return webAdminCli.feignClientFactory(err).target(QuotaClient.class, webAdminCli.jamesUrl);
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/SetGlobalQuotaCountCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/SetGlobalQuotaCountCommand.java
new file mode 100644
index 0000000..be4bbdc
--- /dev/null
+++ b/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) {
+                return WebAdminCli.CLI_FINISHED_SUCCEED;
+            } else {
+                return WebAdminCli.CLI_FINISHED_FAILED;
+            }
+        } catch (Exception e) {
+            e.printStackTrace(parentCommand.parentCommand.quotaCommand.err);
+            return WebAdminCli.CLI_FINISHED_FAILED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/SetGlobalQuotaSizeCommand.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/SetGlobalQuotaSizeCommand.java
new file mode 100644
index 0000000..9a5f42c
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/cli/quota/SetGlobalQuotaSizeCommand.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.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 org.apache.james.util.Size;
+
+import feign.Response;
+import picocli.CommandLine;
+
+@CommandLine.Command(
+    name = "set",
+    description = "Quota counts limit that applies for all users")
+public class SetGlobalQuotaSizeCommand implements Callable<Integer> {
+    @CommandLine.ParentCommand
+    GlobalQuotaSizeCommand parentCommand;
+
+    @CommandLine.Parameters
+    String size;
+
+    @Override
+    public Integer call() {
+        try {
+            QuotaClient quotaClient = parentCommand.parentCommand.quotaCommand.fullyQualifiedURL();
+            Response rs = quotaClient.setQuotaSize(Size.parse(size).asBytes());
+            if (rs.status() == DELETED_CODE) {
+                return WebAdminCli.CLI_FINISHED_SUCCEED;
+            } else {
+                return WebAdminCli.CLI_FINISHED_FAILED;
+            }
+        } catch (Exception e) {
+            e.printStackTrace(parentCommand.parentCommand.quotaCommand.err);
+            return WebAdminCli.CLI_FINISHED_FAILED;
+        }
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/QuotaClient.java b/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/QuotaClient.java
new file mode 100644
index 0000000..7aa7153
--- /dev/null
+++ b/server/protocols/webadmin-cli/src/main/java/org/apache/james/httpclient/QuotaClient.java
@@ -0,0 +1,43 @@
+/******************************************************************
+ * 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.httpclient;
+
+import feign.RequestLine;
+import feign.Response;
+
+public interface QuotaClient {
+    @RequestLine("GET /quota/count")
+    Long getQuotaCount();
+
+    @RequestLine("GET /quota/size")
+    Long getQuotaSize();
+
+    @RequestLine("PUT /quota/count")
+    Response setQuotaCount(Long count);
+
+    @RequestLine("PUT /quota/size")
+    Response setQuotaSize(Long size);
+
+    @RequestLine("DELETE /quota/count")
+    Response deleteQuotaCount();
+
+    @RequestLine("DELETE /quota/size")
+    Response deleteQuotaSize();
+}
diff --git a/server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/QuotaManageTest.java b/server/protocols/webadmin-cli/src/test/java/org/apache/james/cli/QuotaManageTest.java
new file mode 100644
index 0000000..0cc556f
--- /dev/null
+++ b/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;
+
+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());
+                });
+            }
+        }
+    }
+
+    private int executeFluent(String... args) {
+        return WebAdminCli.executeFluent(new PrintStream(outputStreamCaptor), new PrintStream(errorStreamCaptor),
+            ImmutableList.<String>builder().add("--url", "http://127.0.0.1:" + port.getValue())
+                .addAll(ImmutableList.copyOf(args))
+                .build());
+    }
+}


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