You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js使用js-yaml解析Ansible hosts.yaml如何转换为可遍历数组

解决方案

原理说明

Ansible的Inventory YAML规范明确要求,主机组下的主机必须为键值对映射结构,而非数组。因此js-yaml默认将YAML映射解析为JS对象是符合标准的行为,不需要调整解析配置。你无需直接修改解析得到的原始结构,只需要在业务逻辑层做一次格式转换,即可同时满足遍历统计需求和Ansible兼容性要求。

实现步骤

1. 解析YAML并转换为数组格式用于业务处理

const yaml = require('js-yaml');
const fs = require('fs');

// 加载原始hosts.yaml文件
const rawYamlContent = fs.readFileSync('hosts.yaml', 'utf8');
const originalInventory = yaml.load(rawYamlContent);

// 转换为你需要的数组格式,用于遍历、统计、修改配置
const processedInventory = {
  all: {
    // 转换masters组为数组
    masters: Object.entries(originalInventory.all.masters).map(([hostName, hostConfig]) => {
      return { [hostName]: hostConfig };
    }),
    // 转换workers组为数组
    workers: Object.entries(originalInventory.all.workers).map(([hostName, hostConfig]) => {
      return { [hostName]: hostConfig };
    })
  }
};

// 此时你可以直接遍历processedInventory.all.masters、processedInventory.all.workers数组,
// 统计数量直接取数组length属性即可,修改配置直接操作数组内的对象即可

2. 修改完成后转换回原始结构写回文件

// 把数组格式转换回Ansible兼容的键值对结构
const inventoryToSave = {
  all: {
    masters: processedInventory.all.masters.reduce((acc, hostItem) => {
      const [hostName, hostConfig] = Object.entries(hostItem)[0];
      acc[hostName] = hostConfig;
      return acc;
    }, {}),
    workers: processedInventory.all.workers.reduce((acc, hostItem) => {
      const [hostName, hostConfig] = Object.entries(hostItem)[0];
      acc[hostName] = hostConfig;
      return acc;
    }, {})
  }
};

// 写回文件,indent参数指定缩进为2空格,符合Ansible常用的YAML格式规范
fs.writeFileSync('hosts.yaml', yaml.dump(inventoryToSave, { indent: 2 }), 'utf8');

通用优化

如果你的主机组是动态的,不止masters和workers两类,可以用通用转换函数适配所有组:

// 原始结构转数组结构
function convertToArrayFormat(rawInventory) {
  return {
    all: Object.fromEntries(
      Object.entries(rawInventory.all).map(([groupName, hostMap]) => [
        groupName,
        Object.entries(hostMap).map(([hostName, hostConfig]) => ({ [hostName]: hostConfig }))
      ])
    )
  };
}

// 数组结构转原始结构
function convertToRawFormat(arrayInventory) {
  return {
    all: Object.fromEntries(
      Object.entries(arrayInventory.all).map(([groupName, hostArr]) => [
        groupName,
        hostArr.reduce((acc, hostItem) => {
          const [hostName, hostConfig] = Object.entries(hostItem)[0];
          acc[hostName] = hostConfig;
          return acc;
        }, {})
      ])
    )
  };
}

内容的提问来源于stack exchange,提问作者Dreamystify

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:54:02