Skip to content

ZSTAC-86567: select target-aware MN endpoint#4554

Open
zstack-robot-2 wants to merge 2 commits into
5.5.28from
sync/zstackio/shixin-ZSTAC-86567-impl
Open

ZSTAC-86567: select target-aware MN endpoint#4554
zstack-robot-2 wants to merge 2 commits into
5.5.28from
sync/zstackio/shixin-ZSTAC-86567-impl

Conversation

@zstack-robot-2

Copy link
Copy Markdown
Collaborator

Root cause: KVM AddHost SSH precheck used RESTFacade's default callback URL, initialized from the primary MN address, and therefore sent IPv4 to an IPv6 host.

Change: select configured MN node endpoint by literal target IP family; reject missing same-family endpoints before KVM SSH or Ansible side effects; read HA canonical-node and VIP from zsha2 nested family records; reuse KVM's selected endpoint for callback checks and Ansible pip/yum/trusted_host.

Verification: mvn -pl core,plugin/kvm -am -DskipTests install; test/ mvn test -Djacoco.skip=true -Dtest=org.zstack.test.integration.core.ManagementNetworkIpv6Case (2 tests, 0 failures).

sync from gitlab !10518

Use configured family-specific node and HA endpoints.
Reject missing same-family endpoints before KVM side effects.

Resolves: ZSTAC-86567

Change-Id: I71789399f44edcbb742b77360182299eef00253c
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Could not fetch remote config from http://open.zstack.ai:20001/code-reviews/zstack-cloud.yaml: TimeoutError: The operation was aborted due to timeout
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

新增 HA 与 IPv4/IPv6 管理端点选择模型,Platform 提供目标感知解析,并将选定地址接入 Ansible、KVM 回调及相关集成测试。

Changes

管理端点选择与回调接入

Layer / File(s) Summary
HA 地址族与端点选择模型
utils/src/main/java/org/zstack/utils/zsha2/ZSha2Info.java, utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java, core/src/main/java/org/zstack/core/ManagementEndpointData.java
新增 IPv4/IPv6 HA 配置结构、端点错误码,以及按目标地址族选择 NODE、CANONICAL_NODE 和 VIP 的逻辑。
Platform 管理端点解析
core/src/main/java/org/zstack/core/Platform.java
Platform 通过端点数据选择默认或目标感知的管理节点 IP、VIP 和规范节点 IP,并按配置构建 IPv4/IPv6 地址集合。
部署与 KVM 回调接入
core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java, plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
AnsibleRunner 和 KVMHost 使用目标感知的管理节点 IP 配置部署参数、回调检查器及错误传播流程。
地址族与 HA 选择验证
test/src/test/groovy/org/zstack/test/integration/core/*, test/src/test/groovy/org/zstack/test/integration/kvm/host/DualStackAddKvmHostCase.groovy
新增并调整测试,覆盖地址族隔离、IPv4 默认优先、HA 端点类型、配置校验、Ansible 参数及 IPv6 回调命令。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant KVMHost
  participant Platform
  participant ManagementEndpointData
  participant AnsibleRunner
  KVMHost->>Platform: 按目标 IP 获取管理节点 IP
  Platform->>ManagementEndpointData: selectForTarget
  ManagementEndpointData-->>Platform: 返回目标地址族端点
  Platform-->>KVMHost: 返回 callbackIp
  KVMHost->>AnsibleRunner: 设置管理节点 IP
  AnsibleRunner->>AnsibleRunner: 生成部署地址参数
Loading

Poem

我是兔子蹦蹦跳,
IPv4、IPv6 都收好。
HA 端点排成队,
KVM 回调不迷路。
新逻辑上线,胡萝卜庆祝!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题概括了按目标 IP 选择管理节点端点这一主要改动,且与变更内容一致。
Description check ✅ Passed 描述准确说明了按目标地址族选择管理节点端点、HA 端点读取和 KVM/Ansible 回调改动,并包含验证信息。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sync/zstackio/shixin-ZSTAC-86567-impl

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java (1)

391-410: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

在部署判定前解析管理端点。

Line 393 先执行 isNeedRun();它可能执行远端端口/checker 检查,而返回 false 时 Line 404-410 根本不会运行。未设置 managementNodeIp 的调用方因此不能保证缺失同地址族端点会被提前拒绝。

建议修复
     public void run(ReturnValueCompletion<Boolean> completion) {
         try {
+            String selectedManagementNodeIp = managementNodeIp == null ? restf.getHostName() : managementNodeIp;
+            if (managementNodeIp == null && NetworkUtils.isIpAddress(targetIp)) {
+                ErrorableValue<String> managementNodeEndpoint = Platform.getManagementServerIp(targetIp);
+                if (!managementNodeEndpoint.isSuccess()) {
+                    completion.fail(managementNodeEndpoint.error);
+                    return;
+                }
+                selectedManagementNodeIp = managementNodeEndpoint.result;
+            }
+
             if (!forceRun && !isNeedRun()) {
                 completion.success(false);
                 return;
             }

             int port = new URI(restf.getBaseUrl()).getPort();
-            String selectedManagementNodeIp = managementNodeIp;
-            // existing endpoint selection block
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java` around lines
391 - 410, 在 AnsibleRunner.run 中将管理端点解析逻辑移到 forceRun/isNeedRun() 判定之前,确保未设置
managementNodeIp 且 targetIp 为 IP 时先调用 Platform.getManagementServerIp 并在失败时
completion.fail 后立即返回。保留成功解析后的 selectedManagementNodeIp 供后续流程使用,避免 isNeedRun()
提前返回导致校验被跳过。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/src/main/java/org/zstack/core/ManagementEndpointData.java`:
- Around line 37-50: Update ManagementEndpointData’s HA fallback logic so
nestedHaFamilies.isEmpty() does not globally suppress legacy endpoints when a
family object exists but is disabled or invalid. Make addHaFamily validate
enabled status and IP before registering the family, and apply nodeip/dbvip
fallback per IPv4/IPv6 family so unconfigured families still receive their
legacy endpoints.

In `@core/src/main/java/org/zstack/core/Platform.java`:
- Around line 1280-1295: Update getConfiguredManagementNodeIps to include the
management endpoint from the ZSTACK_MANAGEMENT_SERVER_IP environment variable,
using the existing resolution/normalization behavior and avoiding duplicate
entries when the JVM property is also set. Preserve the existing IPv4 and IPv6
secondary-property handling.

---

Outside diff comments:
In `@core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java`:
- Around line 391-410: 在 AnsibleRunner.run 中将管理端点解析逻辑移到 forceRun/isNeedRun()
判定之前,确保未设置 managementNodeIp 且 targetIp 为 IP 时先调用 Platform.getManagementServerIp
并在失败时 completion.fail 后立即返回。保留成功解析后的 selectedManagementNodeIp 供后续流程使用,避免
isNeedRun() 提前返回导致校验被跳过。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bd9f0d17-3a7f-4f4b-987f-cc6a5f6efab3

📥 Commits

Reviewing files that changed from the base of the PR and between 6e0a2ea and 51da3fd.

📒 Files selected for processing (7)
  • core/src/main/java/org/zstack/core/ManagementEndpointData.java
  • core/src/main/java/org/zstack/core/Platform.java
  • core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java
  • plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java
  • test/src/test/groovy/org/zstack/test/integration/core/ManagementNetworkIpv6Case.groovy
  • utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java
  • utils/src/main/java/org/zstack/utils/zsha2/ZSha2Info.java

Comment on lines +37 to +50
public ManagementEndpointData(Collection<String> nodeIps, ZSha2Info info) {
this.ha = info != null;
for (String ip : nodeIps) {
put(this.nodeIps, ip);
}
if (info != null) {
addHaFamily(IPv6Constants.IPv4, info.getIpv4());
addHaFamily(IPv6Constants.IPv6, info.getIpv6());
if (nestedHaFamilies.isEmpty()) {
addLegacyHaEndpoint(haNodeIps, info.getNodeip());
addLegacyHaEndpoint(haVips, info.getDbvip());
}
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 检查 ZSha2Info 的 ipv4/ipv6 是如何被赋值的(例如反序列化来源),确认未配置时是否严格为 null
rg -n -A5 -B5 'setIpv4|setIpv6' --type=java
rg -n 'ZSha2Info' --type=java -g '!**/test/**' -l

Repository: MatheMatrix/zstack

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the relevant classes and nearby usages
git ls-files | rg 'ManagementEndpointData\.java|ZSha2Info\.java|Sha2Info\.java|ManagementEndpointData|ZSha2'

# Show outlines to target small slices
for f in $(git ls-files | rg 'ManagementEndpointData\.java|ZSha2Info\.java'); do
  echo "==== OUTLINE: $f ===="
  ast-grep outline "$f" --view expanded || true
done

# Search for constructors, getters, setters, and JSON annotations/usage
rg -n -A4 -B4 'class ZSha2Info|getIpv4\(|getIpv6\(|setIpv4\(|setIpv6\(|ipv4|ipv6|nodeip|dbvip|nestedHaFamilies|addHaFamily|addLegacyHaEndpoint' --type=java .

Repository: MatheMatrix/zstack

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '==== ManagementEndpointData (selected lines) ===='
sed -n '1,160p' core/src/main/java/org/zstack/core/ManagementEndpointData.java

echo
echo '==== ZSha2Info (selected lines) ===='
sed -n '1,220p' utils/src/main/java/org/zstack/utils/zsha2/ZSha2Info.java

echo
echo '==== Usages / construction of ZSha2Info ===='
rg -n -A3 -B3 'new ZSha2Info|setIpv4\(|setIpv6\(|getIpv4\(|getIpv6\(|HaAddressFamily' --type=java .

Repository: MatheMatrix/zstack

Length of output: 17387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '==== Constructors / setters for ZSha2Info.HaAddressFamily ===='
rg -n -A4 -B4 'new ZSha2Info\.HaAddressFamily|setEnabled\(|setVirtualIp\(|setNodeIp\(|setPeerIp\(|setIpv4\(|setIpv6\(' --type=java .

echo
echo '==== Any JSON / bean binding hints around ZSha2Info ===='
rg -n -A3 -B3 'ZSha2Info|HaAddressFamily' utils/src/main/java core/src/main/java | sed -n '1,220p'

Repository: MatheMatrix/zstack

Length of output: 23955


不要用 nestedHaFamilies.isEmpty() 统一决定回退
addHaFamily() 只要 ipv4/ipv6 对象存在就会把家族加入 nestedHaFamilies,即使该家族 enabled=false 或 IP 不合法;这会让另一个未配置的家族也跳过 nodeip/dbvip 旧字段回退,导致 HA 端点缺失。建议按家族分别回退,或至少把 nestedHaFamilies.add(...) 放到校验通过之后。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/java/org/zstack/core/ManagementEndpointData.java` around lines
37 - 50, Update ManagementEndpointData’s HA fallback logic so
nestedHaFamilies.isEmpty() does not globally suppress legacy endpoints when a
family object exists but is disabled or invalid. Make addHaFamily validate
enabled status and IP before registering the family, and apply nodeip/dbvip
fallback per IPv4/IPv6 family so unconfigured families still receive their
legacy endpoints.

Comment on lines +1280 to +1295
private static List<String> getConfiguredManagementNodeIps() {
List<String> nodeIps = new ArrayList<>();
String primaryIp = System.getProperty(MANAGEMENT_SERVER_IP_PROPERTY);
if (!StringUtils.isBlank(primaryIp)) {
nodeIps.add(normalizeManagementIp(primaryIp));
}

String ipv4 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP4_PROPERTY, IPv6Constants.IPv4);
if (ipv4 != null) {
nodeIps.add(ipv4);
}
return getManagementServerIpOnManagementInterface(IPv6Constants.IPv4);
String ipv6 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP6_PROPERTY, IPv6Constants.IPv6);
if (ipv6 != null) {
nodeIps.add(ipv6);
}
return nodeIps;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

将环境变量管理端点纳入候选集。

Line 1280 仅读取 JVM 属性,但 Line 1199-1203 明确支持 ZSTACK_MANAGEMENT_SERVER_IP。仅通过该环境变量启动时,新的目标感知选择没有候选端点,KVM/Ansible 会将同地址族主机误判为缺少管理端点并拒绝部署。

建议修复
     private static List<String> getConfiguredManagementNodeIps() {
         List<String> nodeIps = new ArrayList<>();
         String primaryIp = System.getProperty(MANAGEMENT_SERVER_IP_PROPERTY);
         if (!StringUtils.isBlank(primaryIp)) {
             nodeIps.add(normalizeManagementIp(primaryIp));
         }
+
+        String environmentIp = System.getenv(ZSTACK_MANAGEMENT_SERVER_IP_ENV);
+        if (!StringUtils.isBlank(environmentIp)) {
+            nodeIps.add(normalizeManagementIp(environmentIp));
+        }

         String ipv4 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP4_PROPERTY, IPv6Constants.IPv4);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private static List<String> getConfiguredManagementNodeIps() {
List<String> nodeIps = new ArrayList<>();
String primaryIp = System.getProperty(MANAGEMENT_SERVER_IP_PROPERTY);
if (!StringUtils.isBlank(primaryIp)) {
nodeIps.add(normalizeManagementIp(primaryIp));
}
String ipv4 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP4_PROPERTY, IPv6Constants.IPv4);
if (ipv4 != null) {
nodeIps.add(ipv4);
}
return getManagementServerIpOnManagementInterface(IPv6Constants.IPv4);
String ipv6 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP6_PROPERTY, IPv6Constants.IPv6);
if (ipv6 != null) {
nodeIps.add(ipv6);
}
return nodeIps;
private static List<String> getConfiguredManagementNodeIps() {
List<String> nodeIps = new ArrayList<>();
String primaryIp = System.getProperty(MANAGEMENT_SERVER_IP_PROPERTY);
if (!StringUtils.isBlank(primaryIp)) {
nodeIps.add(normalizeManagementIp(primaryIp));
}
String environmentIp = System.getenv(ZSTACK_MANAGEMENT_SERVER_IP_ENV);
if (!StringUtils.isBlank(environmentIp)) {
nodeIps.add(normalizeManagementIp(environmentIp));
}
String ipv4 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP4_PROPERTY, IPv6Constants.IPv4);
if (ipv4 != null) {
nodeIps.add(ipv4);
}
String ipv6 = getManagementServerSecondaryIpProperty(MANAGEMENT_SERVER_IP6_PROPERTY, IPv6Constants.IPv6);
if (ipv6 != null) {
nodeIps.add(ipv6);
}
return nodeIps;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/main/java/org/zstack/core/Platform.java` around lines 1280 - 1295,
Update getConfiguredManagementNodeIps to include the management endpoint from
the ZSTACK_MANAGEMENT_SERVER_IP environment variable, using the existing
resolution/normalization behavior and avoiding duplicate entries when the JVM
property is also set. Preserve the existing IPv4 and IPv6 secondary-property
handling.

Resolves: ZSTAC-86567

Change-Id: Icff182b92f222ded2cbe2466ed104418a6e68497

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/src/test/groovy/org/zstack/test/integration/core/ansible/AnsibleRunnerTargetAwareArgumentsCase.groovy (1)

119-143: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

可选:抽取共享的测试辅助方法以消除重复。

withManagementServerIpPropertiesresetCachedManagementServerIp 在本文件、PlatformManagementEndpointSelectionCaseDualStackAddKvmHostCase 中几乎完全重复。可考虑抽取到一个共享的测试工具类/基类,降低后续维护成本。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@test/src/test/groovy/org/zstack/test/integration/core/ansible/AnsibleRunnerTargetAwareArgumentsCase.groovy`
around lines 119 - 143, 可选地,将
AnsibleRunnerTargetAwareArgumentsCase、PlatformManagementEndpointSelectionCase 和
DualStackAddKvmHostCase 中重复的 withManagementServerIpProperties 与
resetCachedManagementServerIp 抽取到共享测试工具类或基类,并更新各测试复用统一实现,保持现有属性清理、恢复及缓存重置行为不变。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@test/src/test/groovy/org/zstack/test/integration/core/PlatformManagementEndpointSelectionCase.groovy`:
- Around line 11-15: 为 PlatformManagementEndpointSelectionCase 和
AnsibleRunnerTargetAwareArgumentsCase 补上可被 Surefire 执行的入口:将类及对应文件重命名为符合默认发现规则的
*Test 或 *TestCase,或把两个类显式加入现有测试 suite 并调用其测试方法;确保其中的 JUnit 测试实际参与构建执行。

---

Nitpick comments:
In
`@test/src/test/groovy/org/zstack/test/integration/core/ansible/AnsibleRunnerTargetAwareArgumentsCase.groovy`:
- Around line 119-143: 可选地,将
AnsibleRunnerTargetAwareArgumentsCase、PlatformManagementEndpointSelectionCase 和
DualStackAddKvmHostCase 中重复的 withManagementServerIpProperties 与
resetCachedManagementServerIp 抽取到共享测试工具类或基类,并更新各测试复用统一实现,保持现有属性清理、恢复及缓存重置行为不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b156c077-04a5-4174-b052-b7bb5161f83d

📥 Commits

Reviewing files that changed from the base of the PR and between 51da3fd and 1d7aa97.

📒 Files selected for processing (7)
  • core/src/main/java/org/zstack/core/ManagementEndpointData.java
  • core/src/main/java/org/zstack/core/Platform.java
  • core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java
  • test/src/test/groovy/org/zstack/test/integration/core/ManagementNetworkIpv6Case.groovy
  • test/src/test/groovy/org/zstack/test/integration/core/PlatformManagementEndpointSelectionCase.groovy
  • test/src/test/groovy/org/zstack/test/integration/core/ansible/AnsibleRunnerTargetAwareArgumentsCase.groovy
  • test/src/test/groovy/org/zstack/test/integration/kvm/host/DualStackAddKvmHostCase.groovy
🚧 Files skipped from review as they are similar to previous changes (4)
  • core/src/main/java/org/zstack/core/ansible/AnsibleRunner.java
  • test/src/test/groovy/org/zstack/test/integration/core/ManagementNetworkIpv6Case.groovy
  • core/src/main/java/org/zstack/core/ManagementEndpointData.java
  • core/src/main/java/org/zstack/core/Platform.java

Comment on lines +11 to +15
class PlatformManagementEndpointSelectionCase {
private static final String IPV4 = "192.168.1.10"
private static final String IPV6 = "2001:db8::1"

@Test

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 定位 test 模块 pom 并检查 surefire/failsafe include 规则及 SubCase 运行方式
fd -g 'pom.xml' test | xargs rg -n -C4 'surefire|failsafe|<include|<exclude|SubCase' 2>/dev/null
# 检查是否存在集中运行 SubCase 的入口
rg -nP -C3 '\bextends\s+SubCase\b' test/src/test/groovy/org/zstack/test/integration/core -g '*.groovy' | head -n 40

Repository: MatheMatrix/zstack

Length of output: 7734


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) 找到 test 模块的 pom,并查看 surefire/failsafe 的完整配置片段
pom=$(fd -a 'pom.xml' test | head -n 1)
echo "POM=$pom"
sed -n '500,680p' "$pom"

echo
echo "---- file names ----"
# 2) 看看 integration/core 下测试文件命名分布,确认这些类是否仅靠默认 surefire 命名规则就能被发现
fd -a -t f 'test/src/test/groovy/org/zstack/test/integration/core' | sed -n '1,120p'

echo
echo "---- case/test naming ----"
# 3) 统计该目录下 *Case / *Test / *Spec 文件
fd -a -t f 'test/src/test/groovy/org/zstack/test/integration/core' \
  | awk -F/ '{print $NF}' \
  | grep -E '([Tt]est|[Cc]ase|[Ss]pec)\.(groovy|java)$' \
  | sort

echo
echo "---- direct references ----"
# 4) 搜索是否存在显式把 *Case 作为 JUnit/Surefire 入口的配置或聚合入口
rg -n -C3 'PlatformManagementEndpointSelectionCase|AnsibleRunnerTargetAwareArgumentsCase|<includes>|<include>|failsafe|surefire|SubCase|`@RunWith`|`@Suite`' test

Repository: MatheMatrix/zstack

Length of output: 5565


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- pom locations ----"
fd -a 'pom.xml' . | sed -n '1,40p'

echo
echo "---- surefire/failsafe/include refs in all poms ----"
rg -n -C3 'maven-surefire-plugin|maven-failsafe-plugin|<include>|<includes>|<exclude>|<excludes>|includesFile|excludesFile|testFailureIgnore|runOrder|forkCount' . -g 'pom.xml'

echo
echo "---- files under integration/core ----"
fd -a . 'test/src/test/groovy/org/zstack/test/integration/core' | sed -n '1,120p'

echo
echo "---- case/test/spec filenames ----"
fd -a -t f . 'test/src/test/groovy/org/zstack/test/integration/core' \
  | awk -F/ '{print $NF}' \
  | grep -E '\.(groovy|java)$' \
  | sort

echo
echo "---- direct class references and suites ----"
rg -n -C2 'PlatformManagementEndpointSelectionCase|AnsibleRunnerTargetAwareArgumentsCase|extends\s+SubCase|`@RunWith`|`@Suite`|suite\(' test/src/test/groovy test/src/test/java

Repository: MatheMatrix/zstack

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- pom test plugins ----"
rg -n -C2 'maven-surefire-plugin|maven-failsafe-plugin|<includes>|<include>|<excludes>|<exclude>|testng|junit' test/pom.xml

echo
echo "---- target classes ----"
rg -n -C2 'class\s+(PlatformManagementEndpointSelectionCase|AnsibleRunnerTargetAwareArgumentsCase)\b|extends\s+SubCase|`@RunWith`|`@Suite`|suite\(' \
  test/src/test/groovy/org/zstack/test/integration/core \
  -g '*.groovy' \
  --max-count 80

echo
echo "---- exact filenames ----"
fd -a -t f . test/src/test/groovy/org/zstack/test/integration/core \
  | grep -E '(PlatformManagementEndpointSelectionCase|AnsibleRunnerTargetAwareArgumentsCase|Suite|Test)\.groovy$' \
  | sort

Repository: MatheMatrix/zstack

Length of output: 34984


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- CoreLibraryTest.groovy ----"
cat -n test/src/test/groovy/org/zstack/test/integration/core/CoreLibraryTest.groovy

echo
echo "---- BranchCascadeTest.groovy ----"
cat -n test/src/test/groovy/org/zstack/test/integration/core/branchcascade/BranchCascadeTest.groovy

echo
echo "---- target classes annotations/structure ----"
sed -n '1,220p' test/src/test/groovy/org/zstack/test/integration/core/PlatformManagementEndpointSelectionCase.groovy
echo
sed -n '1,220p' test/src/test/groovy/org/zstack/test/integration/core/ansible/AnsibleRunnerTargetAwareArgumentsCase.groovy

Repository: MatheMatrix/zstack

Length of output: 12497


补上这两个 JUnit 测试的执行入口test/src/test/groovy/org/zstack/test/integration/core/PlatformManagementEndpointSelectionCase.groovytest/src/test/groovy/org/zstack/test/integration/core/ansible/AnsibleRunnerTargetAwareArgumentsCase.groovy
test/pom.xml 的 surefire 没有额外 includes,默认规则不会发现这类 *Case 纯 JUnit 类;现有 CoreLibraryTest / BranchCascadeTest 也只会 runSubCases()。要么改名成 *Test/*TestCase,要么显式纳入 suite/执行入口。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@test/src/test/groovy/org/zstack/test/integration/core/PlatformManagementEndpointSelectionCase.groovy`
around lines 11 - 15, 为 PlatformManagementEndpointSelectionCase 和
AnsibleRunnerTargetAwareArgumentsCase 补上可被 Surefire 执行的入口:将类及对应文件重命名为符合默认发现规则的
*Test 或 *TestCase,或把两个类显式加入现有测试 suite 并调用其测试方法;确保其中的 JUnit 测试实际参与构建执行。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant