diff --git a/docs/case/macos_compatibility_tests.md b/docs/case/macos_compatibility_tests.md index 86672dd..3abef36 100644 --- a/docs/case/macos_compatibility_tests.md +++ b/docs/case/macos_compatibility_tests.md @@ -127,6 +127,16 @@ | **修复方案** | 经评估这些基线对 macOS 本机开发部署既不适用也无权限执行,故在 `setup-ai-workspace-all-in-one.sh` 新增 `patch_playbook_common_macos()`(同样走克隆后打补丁),仅在 Darwin 下为整个 `Base | *` 块追加 `ansible_os_family != 'Darwin'` 守卫(共 9 处:7 个任务追加 `when`,2 个已有 `when` 列表追加该条件)。`import_tasks` 的 `when` 会传播到子任务,因此 ssh 加固/fail2ban/limits/firewall 子任务一并跳过。幂等、YAML 合法、Linux 行为不变 | | **备注** | 用户仅点名 `set timezone`,但其后的 Base 任务会以相同原因连环失败,故一并守卫以避免逐个往返 | +## TC-MAC-015: Vault 管理员初始化脚本在 macOS 缺依赖/缺 PATH + +| 项目 | 内容 | +|------|------| +| **触发文件** | `roles/vhosts/vault/tasks/main.yml`(Bootstrap 任务)、`roles/vhosts/vault/files/init_vault_admin.sh`、`roles/vhosts/vault/tasks/macos.yml` | +| **触发报错** | `TASK [vault : Bootstrap Vault admin userpass auth]` 失败(`no_log: true` 隐藏详情)。vault 此时已起(健康检查已过),失败发生在执行 `init_vault_admin.sh` | +| **根因** | 脚本 `require_cmd vault/jq/curl/base64`。macOS 默认**不带 jq**,而安装 jq 的 “Install standalone Vault dependencies”(apt)任务带 `!= 'Darwin'` 守卫被跳过 → jq 缺失;同时 `ansible.builtin.script` 使用最小 PATH,未含 Homebrew 的 `/opt/homebrew/bin`,即使已 `brew install` 的 `vault`/`jq` 也可能找不到 | +| **修复方案** | 扩展 `patch_playbook_vault_macos()`:①在 `macos.yml` 增加 `brew install jq`(`creates: /opt/homebrew/bin/jq`);②给 Bootstrap 任务追加 `environment: PATH: "/opt/homebrew/bin:/usr/local/bin:{{ ansible_env.PATH }}"`,确保脚本能找到 brew 安装的 vault/jq。脚本本身已自带 macOS 适配(`base64 -D` 探测)。补丁幂等、YAML 合法、Linux 不变 | +| **备注** | 若仍失败,可临时将该任务 `no_log` 关掉以查看 `init_vault_admin.sh` 的真实 stderr 再定位 | + --- ## 修复维度总结 @@ -139,6 +149,7 @@ | 目录路径降级 ($HOME vs /home/ubuntu, /opt, /etc) | TC-004, TC-006, TC-009, TC-010, TC-012, TC-013 | | 克隆后补丁注入 (post-clone patch) | TC-013, TC-014 | | Linux 基线整体跳过 (skip Linux baseline on Darwin) | TC-014 | +| brew 补依赖 + PATH 注入 (jq via brew, Homebrew on PATH) | TC-015 | | 包管理器绕过 (skip apt on Darwin) | TC-008, TC-010 | | 模板变量解耦 (remove nvm/nodejs_version) | TC-005 | | 路径空格兼容 (argv vs string) | TC-011 | diff --git a/docs/report/TC-MAC-012-26-06-18-19.md b/docs/report/TC-MAC-012-26-06-18-19.md index a839cfc..4cef87c 100644 --- a/docs/report/TC-MAC-012-26-06-18-19.md +++ b/docs/report/TC-MAC-012-26-06-18-19.md @@ -135,3 +135,19 @@ fatal: timedatectl set-timezone Asia/Shanghai -> [Errno 2] No such file or direc **验证**:`bash -n` 通过;用真实 `common/tasks/main.yml` 跑补丁,YAML 合法、守卫计数 9、二次执行幂等、Linux 段落(Debian/RedHat/addon)不变。 **说明**:用户仅点名 timezone,但为避免逐个往返,已一并守卫同源会失败的 Base 任务。 + +--- + +## 10. 续:Vault 管理员初始化脚本(TC-MAC-015,19:50) + +**进展**:common 守卫后部署推进,vault 已成功启动(健康检查通过),新阻塞点为 `vault : Bootstrap Vault admin userpass auth`(`no_log: true`,详情被隐藏)。 + +**根因**:该任务执行 `files/init_vault_admin.sh`,脚本 `require_cmd vault/jq/curl/base64`。macOS 默认无 `jq`,而安装它的 apt 依赖任务在 Darwin 被跳过;且 `ansible.builtin.script` 的最小 PATH 未含 `/opt/homebrew/bin`,brew 装的 vault/jq 可能找不到。 + +**解法**:扩展 `patch_playbook_vault_macos()`: +1. `macos.yml` 增加 `brew install jq`(`creates: /opt/homebrew/bin/jq`); +2. Bootstrap 任务追加 `environment: PATH: "/opt/homebrew/bin:/usr/local/bin:{{ ansible_env.PATH }}"`。 + +**验证**:`bash -n` 通过;对 vault 角色跑补丁,jq 任务/environment 各 1 处、YAML 合法、二次执行幂等、bootstrap 结构正确(environment 位于脚本参数与 `no_log` 之间)。 + +**兜底**:若仍失败,临时关闭该任务 `no_log` 即可看到脚本真实 stderr 进一步定位。 diff --git a/scripts/setup-ai-workspace-all-in-one.sh b/scripts/setup-ai-workspace-all-in-one.sh index c669ee2..cd35c0f 100755 --- a/scripts/setup-ai-workspace-all-in-one.sh +++ b/scripts/setup-ai-workspace-all-in-one.sh @@ -1155,6 +1155,23 @@ dir_when_old = ( dir_when_new = dir_when_old + " - ansible_os_family != 'Darwin'\n" if dir_when_old in tasks_text and " - ansible_os_family != 'Darwin'\n\n- name: Deploy standalone Vault systemd" not in tasks_text: tasks_text = tasks_text.replace(dir_when_old, dir_when_new, 1) + +# 2b) The admin bootstrap runs files/init_vault_admin.sh, which require_cmd's +# vault/jq/curl/base64. On macOS those live under Homebrew, which is not on the +# minimal PATH ansible.builtin.script uses; prepend the Homebrew bin dirs so the +# helper can find them. +boot_old = ( + ' --ui-url {{ vault_admin_ui_url | quote }}\n' + ' no_log: true\n' +) +boot_new = ( + ' --ui-url {{ vault_admin_ui_url | quote }}\n' + ' environment:\n' + ' PATH: "/opt/homebrew/bin:/usr/local/bin:{{ ansible_env.PATH }}"\n' + ' no_log: true\n' +) +if boot_old in tasks_text and boot_new not in tasks_text: + tasks_text = tasks_text.replace(boot_old, boot_new, 1) tasks_path.write_text(tasks_text) # 3) Create the macOS vault dirs (user-owned) before the launchd plist is laid down. @@ -1173,6 +1190,25 @@ dir_task = ( anchor = "- name: Install HashiCorp Tap\n" if "Ensure macOS Vault directories exist" not in macos_text and anchor in macos_text: macos_text = macos_text.replace(anchor, dir_task + anchor, 1) + +# jq is not preinstalled on macOS and the Linux apt task that installs it is +# Darwin-skipped, yet init_vault_admin.sh requires it. Install it via Homebrew. +vault_brew_old = ( + "- name: Install Vault via Homebrew\n" + " ansible.builtin.command: brew install hashicorp/tap/vault\n" + " args:\n" + " creates: /opt/homebrew/bin/vault\n" + " changed_when: true\n" +) +jq_task = ( + "\n- name: Install jq via Homebrew (required by Vault admin bootstrap)\n" + " ansible.builtin.command: brew install jq\n" + " args:\n" + " creates: /opt/homebrew/bin/jq\n" + " changed_when: true\n" +) +if vault_brew_old in macos_text and "Install jq via Homebrew" not in macos_text: + macos_text = macos_text.replace(vault_brew_old, vault_brew_old + jq_task, 1) macos_path.write_text(macos_text) PY }