推广 HEAT_ENV

https://blueprints.launchpad.net/tripleo/+spec/tripleo-juno-promote-heat-env

将 Heat 环境变量文件中设置的值优先于输入的环境变量。

问题描述

历史上,TripleO 脚本会从环境变量中获取许多配置项。这会带来作用域泄漏的风险,并且所需的环境变量数量通常迫使用户使用脚本来管理他们的环境。因此,人们倾向于使用诸如 Heat 环境变量文件 (HEAT_ENV) 之类的数据文件,这些文件可以通过传递 -e 参数给 Heat 来设置。为了允许此文件提供一个明确的事实来源,必须禁止环境变量覆盖此文件中的值。也就是说,必须转移优先级。

一个关键的区别在于,环境变量的值是从其父进程(直接或通过派生)传递给它的,还是不是。前者将被称为“输入变量”,并且在本规范中被弃用。后者将被称为“本地变量”,并且可以自由引入。包含从多个来源合成的值的变量必须逐个案例处理。

提议的变更

由于更改 I5b7c8a27a9348d850d1a6e4ab79304cf13697828 和 I42a9d4b85edcc99d13f7525e964baf214cdb7cbf,ENV_JSON(由 HEAT_ENV 命名的文件的内容)在 devtest_undercloud.sh 中以如下方式构建

ENV_JSON=$(jq '.parameters = {
  "MysqlInnodbBufferPoolSize": 100
} + .parameters + {
  "AdminPassword": "'"${UNDERCLOUD_ADMIN_PASSWORD}"'",
  "AdminToken": "'"${UNDERCLOUD_ADMIN_TOKEN}"'",
  "CeilometerPassword": "'"${UNDERCLOUD_CEILOMETER_PASSWORD}"'",
  "GlancePassword": "'"${UNDERCLOUD_GLANCE_PASSWORD}"'",
  "HeatPassword": "'"${UNDERCLOUD_HEAT_PASSWORD}"'",
  "NovaPassword": "'"${UNDERCLOUD_NOVA_PASSWORD}"'",
  "NeutronPassword": "'"${UNDERCLOUD_NEUTRON_PASSWORD}"'",
  "NeutronPublicInterface": "'"${NeutronPublicInterface}"'",
  "undercloudImage": "'"${UNDERCLOUD_ID}"'",
  "BaremetalArch": "'"${NODE_ARCH}"'",
  "PowerSSHPrivateKey": "'"${POWER_KEY}"'",
  "NtpServer": "'"${UNDERCLOUD_NTP_SERVER}"'"
}' <<< $ENV_JSON)

这大致相当于“A + B + C”,其中来自 B 的值覆盖来自 A 的值,来自 C 的值覆盖来自 A 或 B 的值。目前,部分 C 包含输入变量和本地变量的混合。建议将当前和未来的环境变量分配如下

  • A 仅包含默认值。

  • B 是 HEAT_ENV 文件(来自用户或之前的运行)。

  • C 仅包含计算值(来自本地变量)。

以下当前位于部分 C 中,但不是本地变量

NeutronPublicInterface (default 'eth0')
UNDERCLOUD_NTP_SERVER (default '')

输入变量将被忽略,默认值将被移动到部分 A

ENV_JSON=$(jq '.parameters = {
  "MysqlInnodbBufferPoolSize": 100,
  "NeutronPublicInterface": "eth0",
  "NtpServer": ""
} + .parameters + {
  ... elided ...
}' <<< $ENV_JSON)

devtest_overcloud.sh 将以类似的方式处理。这些是需要删除的变量及其默认值添加到部分 A

OVERCLOUD_NAME (default '')
OVERCLOUD_HYPERVISOR_PHYSICAL_BRIDGE (default '')
OVERCLOUD_HYPERVISOR_PUBLIC_INTERFACE (default '')
OVERCLOUD_BRIDGE_MAPPINGS (default '')
OVERCLOUD_FLAT_NETWORKS (default '')
NeutronPublicInterface (default 'eth0')
OVERCLOUD_LIBVIRT_TYPE (default 'qemu')
OVERCLOUD_NTP_SERVER (default '')

这些输入变量中只有一个在这些脚本之外使用,因此其余的可以安全地删除。

例外情况是 OVERCLOUD_LIBVIRT_TYPE。该变量由脚本 ‘write-tripleorc’ 保存。由于它现在将保存在 HEAT_ENV 中,因此不需要也由 write-tripleorc 保存,可以从那里删除。


为了让用户知道他们需要开始通过 HEAT_ENV 而不是输入变量来设置这些值,进一步建议在一段时间内,每个脚本在 STDERR 上回显一条消息,如果设置了弃用的输入变量。例如

for OLD_VAR in OVERCLOUD_NAME; do
  if [ ! -z "${!OLD_VAR}" ]; then
    echo "WARNING: ${OLD_VAR} is deprecated, please set this in the" \
         "HEAT_ENV file (${HEAT_ENV})" 1>&2
  fi
done

为了进一步分离用户输入和生成的值,建议将用户值读取到一个新的文件 - USER_HEAT_ENV。这将默认为 {under,over}cloud-user-env.json。一个新的命令行参数,–user-heat-env,将被添加到这两个脚本中,以便可以更改它。

  1. ENV_JSON 首先使用默认值初始化。

  2. ENV_JSON 被 HEAT_ENV 覆盖。

  3. ENV_JSON 被 USER_HEAT_ENV 覆盖。

  4. ENV_JSON 被计算值覆盖。

  5. ENV_JSON 被保存到 HEAT_ENV。

有关如何实现此操作的示例,请参阅 http://paste.openstack.org/show/83551/。简而言之

ENV_JSON=$(cat ${HEAT_ENV} ${USER_HEAT_ENV} | jq -s '
  .[0] + .[1] + {"parameters":
    ({..defaults..} + .[0].parameters + {..computed..} + .[1].parameters)}')
cat > "${HEAT_ENV}" <<< ${ENV_JSON}

选择将用户数据移动到一个新文件中,而不是将合并的数据移动到文件中,使得 USER_HEAT_ENV 是可选的。如果用户希望,他们可以继续在 HEAT_ENV 中提供他们的值。互补解决方案要求用户从 HEAT_ENV 中清除预计算的值,否则他们可能会无意中阻止这些值被重新计算。

在用户值之后加载计算值会牺牲用户控制权以换取正确性。考虑到任何 devtest 用户都必须相当精通技术,如果计算不正确,他们可以修复或至少修改计算本身。

替代方案

与其完全删除输入变量,可以使用一种临时形式

ENV_JSON=$(jq '.parameters = {
  "MysqlInnodbBufferPoolSize": 100,
  "NeutronPublicInterface": "'"${NeutronPublicInterface}"'",
  "NtpServer": "'"${UNDERCLOUD_NTP_SERVER}"'"
} + .parameters + {
  ...
}

但是,只有当 HEAT_ENV 中不存在它们影响的键时,输入变量才会生效。由于每次 devtest 运行时都会写入 HEAT_ENV,因此除非每次都删除该文件(使其毫无意义),否则这些键通常会存在。因此,这种形式更有可能造成困惑,而不是帮助过渡。


jq 包含一个“替代运算符”,//,它旨在提供默认值

A filter of the form a // b produces the same results as a, if a produces
results other than false and null. Otherwise, a // b produces the same
results as b.

出于两个原因,该运算符未在本提案中使用

  1. 它仅适用于单个键,而不适用于整个映射。

  2. 它不适用于 jq 1.2,仍然包含在 Ubuntu 13.04 (Saucy) 中。

安全影响

无。

其他最终用户影响

更改合并后将在邮件列表中发布公告。这加上如果设置了弃用的变量所发出的警告,应该提供足够的通知。

由于每次 devtest 执行时都会重写 HEAT_ENV,因此我们可以放心地假设它与上次使用的环境匹配。但是,使用脚本切换环境的用户可能会感到惊讶。总体而言,这项更改对这些用户应该是有益的,因为他们可以使用两个单独的 HEAT_ENV 文件(传递 –heat-env 以指定要激活的文件)而不是需要维护脚本来设置他们的环境并冒着设置从一个泄漏到另一个的风险。

性能影响

无。

其他部署者影响

无。

开发人员影响

无。

实现

负责人

lxsli

工作项

  • 将 USER_HEAT_ENV 添加到两个脚本。

  • 移动两个脚本中的变量。

  • 将弃用变量警告添加到两个脚本。

  • 从 write-tripleorc 中删除 OVERCLOUD_LIBVIRT_TYPE。

依赖项

无。

测试

更改将与脚本的其余部分隔离测试。

文档影响

  • 使用环境变量弃用警告更新用法文档。

  • 更新用法文档以推荐 HEAT_ENV。

参考资料

  1. http://stedolan.github.io/jq/manual/ - JQ 手册

  2. http://jqplay.herokuapp.com/ - JQ 交互式演示