开发效率 - Quarkus CLI
人们很少意识到,Quarkus CLI 自 2019 年 Quarkus 首次公开版本发布以来就已可用。它最初只允许创建项目和操作扩展。以下命令显示了支持的命令列表。
quarkus --help
Usage: quarkus <command> [<args>]
These are the common quarkus commands used in various situations
Options:
-h, --help
quarkus commands:
list-extensions List extensions for a project
add-extension Adds extensions to a project
create-project Creates a base Quarkus maven project
如今,在 3.1.2.Final
版本中,它包含近 30 个命令,分布在 6 个主要类别中。其中 3 个类别是 3.0 路线图的一部分,将是本文的重点。特别是,本文将介绍使用 Quarkus CLI 构建容器镜像、部署和扩展 Quarkus CLI。
使用 Quarkus CLI 构建容器镜像
提供一种简单的 Quarkus 容器镜像创建方式并非新鲜事。自早期以来,Quarkus 就提供了处理容器镜像构建的扩展,使用了诸如以下技术:
使用这些扩展需要将它们添加到项目中,例如:
quarkus ext add quarkus-container-image-docker
此外,还需要额外的配置选项来触发容器镜像构建。
./mvnw package -Dquarkus.container-image.build=true
虽然这可以很好地工作,但用户仍然需要了解这些扩展以及启用它们所需的特殊配置选项。换句话说,用户需要方便地链接到 Quarkus 容器镜像文档,以查看可用选项及其使用方法。
此外,用户每次需要切换扩展时都需要修改项目配置。这很简单,但应该是可选的,因为实际应用程序不依赖于容器镜像的构建方式。此外,这可能会增加版本控制日志中的噪音。
使用 Quarkus CLI 构建容器镜像
Quarkus 3.0 引入了一种使用 Quarkus CLI 构建容器镜像的替代方法。在 CLI 的最新版本中,提供了新的子命令来构建和推送容器镜像。这些命令列在 quarkus --help
的输出中。
quarkus --help | grep image
image Build or push project container image.
build Build a container image.
docker Build a container image using Docker.
buildpack Build a container image using Buildpack.
jib Build a container image using Jib.
openshift Build a container image using Openshift.
push Push a container image.
例如,为了执行 docker 构建:
quarkus image build docker
请注意,该命令不要求用户以任何方式编辑其构建文件(例如 pom.xml 或 build.gradle),并且可以在任何项目中运行,而无需任何特定的扩展。甚至可以在空的 Quarkus 项目中运行。
quarkus create app hello
cd hello
quarkus image build docker
无需额外配置,即使用户决定切换到不同的容器镜像技术,如 jib。
quarkus image build jib
最后但同样重要的是,CLI 确实提供了额外的帮助,例如代码补全和帮助消息。
quarkus image build jib --help
部署应用程序
以与构建容器镜像类似的方式,Quarkus 允许将应用程序部署到 Kubernetes 和 OpenShift 等平台。同样,这需要使用扩展和额外的构建选项来启用部署。例如,要在 Kubernetes 上部署应用程序,需要显式地将扩展添加到项目中,并使用 quakrus.kubernetes.deploy
属性启用部署。
quarkus ext add quarkus-kubernetes
./mvnw package -Dquarkus.kubernetes.deploy=true
使用 Quarkus CLI 进行部署
在 Quarkus 3.0 中,CLI 包含 deploy
子命令,这是与部署相关的命令的入口点。使用 quarkus --help
可以列出所有相关命令。
quarkus --help | grep deploy
deploy Deploy application.
kubernetes Perform the deploy action on kubernetes.
openshift Perform the deploy action on openshift.
knative Perform the deploy action on knative.
kind Perform the deploy action on kind.
minikube Perform the deploy action on minikube.
这些命令允许开发人员轻松地将 Quarkus 应用程序从一个平台部署到另一个平台,而无需弄乱其项目文件。
设想一个团队,一些开发人员使用 kind,另一些开发人员使用 minikube。在 3.0 之前,他们每次需要从版本控制中拉取更改时,都必须暂存并应用他们选择的扩展。或者,他们可以配置构建配置文件。通过使用 CLI,用户可以部署到他们选择的平台,即使在与项目配置中的平台不一致的情况下也是如此。例如,如果项目包含 Quarkus Kubernetes 扩展,但用户更喜欢使用 kind 扩展并利用针对 kind 的优化清单。
quarkus deploy kind
需要注意的是,通过为每个平台提供一个命令,用户可以在执行这些命令时轻松地设置特定于平台的配置(请参阅 --help
输出)。
总结镜像构建和部署命令
Quarkus 3.0 引入了新的 CLI 命令来构建容器镜像和进行部署。这些命令通过消除与项目设置和配置相关的步骤来改善开发人员体验。它们允许开发人员轻松地试验不同的技术,并通过提供帮助消息、提示和补全来指导他们。
Quarkus 的未来版本将把这个概念扩展到 Quarkus Azure Functions 和 Quarkus Amazon Lambda 等领域。
CLI 插件
CLI 为开发人员带来了一些非常有趣的功能,但可惜的是,它不能无限增长,因为它需要保持合理的大小。这种需求促使为 CLI 实现了插件系统,该系统允许以插件的形式动态添加命令。
什么是插件?
插件通过以下方式之一实现命令:
-
作为任意可执行文件
-
作为 Java 源代码文件
-
作为 jar(带 main 方法)
-
作为 Maven 构件
-
作为 JBang 别名
插件通过显式使用 Quarkus CLI 或隐式添加扩展到项目来添加到 CLI。
让我们看看 CLI 中有哪些与插件相关的可用命令。
quarkus --help | grep plug
plugin, plug Configure plugins of the Quarkus CLI.
list, ls List CLI plugins.
add Add plugin(s) to the Quarkus CLI.
remove Remove plugin(s) to the Quarkus CLI.
最初,没有安装任何插件,因此 quarkus plug list
返回一个空列表。
quarkus plug list
No plugins installed!
To include the installable plugins in the list, append --installable to the command.
它还返回一个提示,建议使用 --installable
,但什么是 installable
插件?
quarkus plug list --installable
Name Type Scope Location Description
fmt jbang user quarkus-fmt@quarkusio
kill jbang user quarkus-kill@quarkusio
quarkus jbang user quarkus@quarkusio
列出的插件是 JBang 别名,这些别名在 quarkus.io JBang 目录(默认启用)中可用。可以使用 JBang 二进制文件添加更多目录。
编写插件
让我们看看如何为 Quarkus CLI 创建插件。开箱即用地,Quarkus CLI 提供了 3 种创建项目的方式:
-
Web 应用
-
命令行应用程序
-
Quarkus 扩展
quarkus --help | grep -A3 create
create Create a new project.
app Create a Quarkus application project.
cli Create a Quarkus command-line project.
extension Create a Quarkus extension project
我们将创建一个 create
插件,使用 Quarkus Quickstarts 创建新应用程序。这就像编写一个从 GitHub 克隆存储库并复制所选快速入门的脚本一样简单。为了增加一些额外价值,我们还将使用 稀疏检出,并将深度限制为 1。这最大限度地减少了传输的数据量并加快了速度。此外,回忆 稀疏检出 的实际步骤并不容易,因此将其作为脚本非常方便。
#!/bin/bash
DIRECTORY=$1
REPO_URL="https://github.com/quarkusio/quarkus-quickstarts.git"
# Create a new directory for your Git repo and navigate into it
mkdir $DIRECTORY
cd $DIRECTORY
# Initialize a new Git repository here
git init
# Add the repository from GitHub as a place your local Git repo can fetch from
git remote add origin $REPO_URL
git config core.sparseCheckout true
echo "$DIRECTORY" >> .git/info/sparse-checkout
# Fetch just the history of the specific directory
git fetch --depth 1 origin main:$DIRECTORY
# Checkout the specific directory
git checkout $DIRECTORY
mv $DIRECTORY/* .
rm -rf $DIRECTORY
rm -rf .git
让我们将上面的脚本保存在名为 quarkus-create-from-quickstart
的文件中,并将其添加到 PATH。quarkus-
是必需的前缀,create
是插件将被安装的命令名称。下次运行 quarkus plug list --installable
时,它会拾取该脚本。
quarkus plug list --installable
Name Type Scope Location Description
create-from-quickstart executable user /home/iocanel/bin/quarkus-create-from-quickstart
fmt jbang user quarkus-fmt@quarkusio
kill jbang user quarkus-kill@quarkusio
quarkus jbang user quarkus@quarkusio
Use the 'plugin add' subcommand and pass the location of any plugin listed above, or any remote location in the form of URL / GACTV pointing to a remote plugin.
现在可以使用以下命令安装插件:
quarkus plug add create-from-quickstart
Added plugin:
Name Type Scope Location Description
* create-from-quickstart executable user /home/iocanel/bin/quarkus-create-from-quickstart
插件现在出现在 quarkus --help
的 create
命令下。
quarkus --help | grep -A4 create
create Create a new project.
app Create a Quarkus application project.
cli Create a Quarkus command-line project.
extension Create a Quarkus extension project
from-quickstart
它可以像常规命令一样使用。让我们用它来从 Hibernate ORM Panache Quickstart 创建应用程序。
quarkus create from-quickstart hibernate-orm-panache-quickstart
利用您的 Java 技能编写插件
使用 Shell 脚本或任意二进制文件(用任何语言编写)是编写插件的一种方式。Java 开发人员也可以利用他们的 Java 技能。包含 main 方法的任何源文件或定义了 main 类的任何 jar 都可以通过传递其位置(路径或 URL)直接使用。对于 jar,也支持 Maven 坐标形式的 GACTV(<组 ID>:<Artifact ID>:<Classifier>:<Type>:<Version>)。
让我们用 Java 重写 create-from-github
,看看如何将 Java 源文件插入 Quarkus CLI。实现将使用 jgit 和 commons.io。为了简化依赖管理,源文件包含 JBang 元注释,它定义了前面提到的依赖项。
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r
//DEPS commons-io:commons-io:2.11.0
//JAVA_OPTIONS -Djava.io.tmpdir=/tmp
import org.eclipse.jgit.api.*;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.transport.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Set;
import org.apache.commons.io.FileUtils;
public class CreateFromQuickstart {
private static final String REPO_URL = "https://github.com/quarkusio/quarkus-quickstarts.git";
private static final String FETCH = "+refs/heads/*:refs/remotes/origin/*";
public static void main(String[] args) {
String directory = args[0];
Set<String> paths = Set.of(directory);
try {
Path cloneDir = Files.createTempDirectory("create-from-quickstart-");
Git git = Git.init().setDirectory(cloneDir.toFile()).call();
StoredConfig config = git.getRepository().getConfig();
config.setString("remote", "origin", "url", REPO_URL);
config.setString("remote", "origin", "fetch", FETCH);
config.setBoolean("core", null, "sparseCheckout", true);
config.setBoolean("core", null, "sparseCheckout", true);
config.save();
Path file = cloneDir.resolve(".git").resolve("info").resolve("sparse-checkout");
file.getParent().toFile().mkdirs();
Files.write(file, directory.getBytes());
FetchResult result = git.fetch().setRemote("origin").setRefSpecs(new RefSpec(FETCH)).setThin(false).call();
git.checkout().setName("origin/main").call();
File source = cloneDir.resolve(directory).toFile();
File destination = new File(directory);
FileUtils.copyDirectory(source, destination);
FileUtils.deleteDirectory(cloneDir.toFile());
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
要将此源文件添加为 Quarkus CLI 插件:
quarkus plug add /path/to/CreateFromQuickstart.java
Added plugin:
Name Type Scope Location Description
* CreateFromQuickstart java user /path/to/CreateFromQuickstart.java
请注意,名称是从实际文件/类名派生的,它使用 驼峰式命名法,因此不匹配 create
子命令。相反,它被添加为 create
的同级。
quarkus --help
Commands:
create Create a new project.
app Create a Quarkus application project.
cli Create a Quarkus command-line project.
extension Create a Quarkus extension project
# more commands here
CreateFromQuickstart
截至 3.1.2.Final
,没有直接的方法可以为插件设置别名。但是,JBang 支持别名。以下是如何使用别名:
jbang alias add --name quarkus-create-from-quickstart ~/path/to/CreateFromQuickstart.java
[jbang] Alias 'quarkus-create-from-quickstart' added to '/home/user/.jbang/jbang-catalog.json'
quarkus plug add create-from-quickstart
Added plugin:
Name Type Scope Location Description
* create-from-quickstart jbang user quarkus-create-from-quickstart
项目特定插件
在迄今为止的所有示例中,插件被列为 用户范围
。这意味着插件对用户是全局的。但是,也可以有 项目范围
的插件。这很重要,因为它允许:
-
拥有项目特定插件
-
按项目覆盖版本
-
共享插件目录(通过版本控制)
-
支持扩展提供的插件
当 quarkus plug add
命令在项目内调用时,插件会被添加到项目目录中,除非使用了 --user
选项。插件目录保存在项目根目录的 .quarkus
中。通过将此文件夹添加到版本控制,项目插件目录会在项目用户之间共享。在这种情况下,最好还将实际的插件源文件包含在版本控制中,或者使用共享的 JBang 目录。
让我们创建一个脚本,允许用户在其 ArgoCD 开发实例中设置其项目。ArgoCD 是 Kubernetes 的 GitOps 持续交付工具。以下示例演示了其设置过程可以作为 Quarkus CLI 插件自动化。
更具体地说,该插件执行以下操作:
-
安装 ArgoCD 二进制文件
-
将 ArgoCD 资源安装到目标集群
-
生成项目的 Kubernetes 清单
-
将生成的资源添加到版本控制
-
将项目设置为 ArgoCD
即使上述某些步骤只需要执行一次(例如,将清单添加到版本控制),其余步骤也必须为每个开发人员环境执行。因此,与其将脚本永远添加到某个共享文件夹或存储库中而被遗忘,不如将其作为 CLI 插件放在项目内部是有意义的。脚本的来源可以是这样的:
#!/bin/bash
set -e
ARGOCD_VERSION="v2.7.4"
check_requirements() {
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "Error: The current folder is not under version control."
exit 1
fi
if [ ! -f "target/kubernetes/kubernetes.yml" ]; then
mvn quarkus:deploy -Dquarkus.kubernetes.deploy=false
if [ ! -f "target/kubernetes/kubernetes.yml" ]; then
echo "Error: The target/kubernetes/kubernetes.yml file does not exist."
exit 1
fi
fi
}
install_argocd_binary() {
OS="`uname`"
case $OS in
'Linux')
OS='linux'
;;
'Darwin')
OS='darwin'
;;
*) ;;
esac
if ! command -v argocd &> /dev/null
then
curl -sSL -o $HOME/bin/argocd https://github.com/argoproj/argo-cd/releases/download/${ARGOCD_VERSION}/argocd-${OS}-amd64
chmod +x $HOME/bin/argocd
fi
}
install_argocd_resources() {
if ! kubectl get namespace | grep -q 'argocd'; then
kubectl create namespace argocd
fi
if ! kubectl get pods -n argocd | grep -q 'argocd-server'; then
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/${ARGOCD_VERSION}/manifests/install.yaml
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=argocd-server -n argocd --timeout=120s
fi
}
wait_for_port() {
local PORT=$1
local TIMEOUT=5
local START_TIME=$SECONDS
while :
do
if nc -v $1 &> /dev/null; then
nc -z localhost $PORT && return
fi
if (( SECONDS - START_TIME >= TIMEOUT )); then
return
fi
sleep 1
done
}
cleanup() {
kill $PORT_FORWARD_PID
}
create_app() {
NAMESPACE=`kubectl config view --minify --output 'jsonpath={..namespace}'`
GIT_URL=`git remote get-url origin | sed -s "s/git@github.com:/https:\/\/github.com\//"`
GIT_BRANCH=`git branch -l | grep "*" | awk '{print $2}'`
APP_DIR=`git rev-parse --show-toplevel`
APP_NAME=`git rev-parse --show-toplevel | xargs basename`
ARGOCD_PASSWORD=`argocd admin initial-password argo -n argocd | head -n1`
if [ -f "$APP_DIR/.argocd" ]; then
mkdir $APP_DIR/.argocd
fi
cp target/kubernetes/kubernetes.yml $APP_DIR/.argocd/
if [ -n "$(git status --porcelain | grep -v '?')" ]; then
git add $APP_DIR/.argocd
git commit -m "Add generated manifests to argocd" && git push origin $BRANCH
fi
kubectl port-forward svc/argocd-server -n argocd 9443:443 > /dev/null 2>&1 &
PORT_FORWARD_PID=$!
trap "cleanup" EXIT SIGINT SIGTERM
wait_for_port 9443
argocd login localhost:9443 --username admin --password $ARGOCD_PASSWORD --insecure
argocd app create $APP_NAME --repo $GIT_URL --path .argocd --dest-server https://kubernetes.default.svc --dest-namespace default
argocd app sync $APP_NAME
}
check_requirements
install_argocd_binary
install_argocd_resources
create_app
让我们将文件保存在 bin/quarkus-argocd-setup
下,并将其添加为插件。
quarkus plug add bin/quarkus-argocds-setup
现在,通过调用 quarkus argocd-setup
,应用程序已设置为与 ArgoCD 一起使用。
扩展提供的插件
Quarkus 扩展可以为项目提供的 CLI 插件做出贡献。目前,以下 Quarkiverse 扩展提供插件:
让我们看看当此类扩展添加到项目时,事情是如何工作的。以下命令添加了 Quarkus Helm 扩展,以及经常一起使用的 Kubernetes 和 docker 扩展。
quarkus ext add quarkus-helm quarkus-kubernetes quarkus-container-image-docker
[SUCCESS] ✅ Extension io.quarkiverse.helm:quarkus-helm:1.0.7 has been installed
[SUCCESS] ✅ Extension io.quarkus:quarkus-kubernetes has been installed
[SUCCESS] ✅ Extension io.quarkus:quarkus-container-image-docker has been installed
下次使用 CLI 时,`helm
插件应该会自动添加。
quarkus --help
Plugin catalog last updated on: 07/06/2023 10:29:05. Syncing!
Looking for the newly published extensions in registry.quarkus.io
Options:
# option details
Commads:
# commands
helm
quarkus helm install
另请参阅
如果您想了解更多关于新的 Quarkus CLI 功能的信息,请务必查看以下 Quarkus Insights 系列。它们演示了新功能,并有望激发您创建自己插件的想法。