我正在使用Ruby构建一个开源项目来测试HTTP服务:https://github.com/Comcast/http-blackbox-test-tool
我希望能够在我的test-plan.yaml
文件中引用环境变量。我可以使用ERB,但是我不希望支持嵌入任何随机的Ruby代码,对于非红宝石主义者来说ERB语法很奇怪,我只想使用常用的Unix样式${ENV_VAR}
语法访问环境变量。>
例如
order-lunch-app-health:
request:
url: ${ORDER_APP_URL}
headers:
content-type: 'application/text'
method: get
expectedResponse:
statusCode: 200
maxRetryCount: 5
我为Ruby找到的所有示例都使用ERB。有人对处理此问题的最佳方法有建议吗?我愿意使用另一种工具预处理YAML,然后将其发送到Ruby应用程序。
答案 0 :(得分:1)
我相信这样的事情在大多数情况下都应该起作用:
require 'yaml'
def load_yaml(file)
content = File.read file
content.gsub! /\${([^}]+)}/ do
ENV[$1]
end
YAML.load content
end
p load_yaml 'sample.yml'
与我最初的回答相反,这既简单又能很好地处理未定义的ENV变量。
尝试使用此YAML:
# sample.yml
path: ${PATH}
home: ${HOME}
error: ${NO_SUCH_VAR}
有几种方法可以做到这一点。如果要允许用户使用${VAR}
语法,那么一种方法可能是首先将这些变量转换为Ruby字符串替换格式%{VAR}
,然后一起评估所有环境变量。
这里是一个粗略的概念证明:
require 'yaml'
# Transform environments to a hash of { symbol: value }
env_hash = ENV.to_h.transform_keys(&:to_sym)
# Load the file and convert ${ANYTHING} to %{ANYTHING}
content = File.read 'sample.yml'
content.gsub! /\${([^}]+)}/, "%{\\1}"
# Use Ruby string substitution to replace %{VARS}
content %= env_hash
# Done
yaml = YAML.load content
p yaml
例如,将其与此sample.yml
一起使用:
# sample.yml
path: ${PATH}
home: ${HOME}
当然有很多方法可以改进。
答案 1 :(得分:0)
预处理很容易,我建议您使用YAML加载程序/转储程序
基于解决方案的解决方案,因为替换可能需要在
替换标量。 (例如,您将字符串true
替换为
不加引号,则生成的YAML将被读为布尔值。
假设您的“来源”位于input.yaml
和您的环境中。变量
ORDER_APP_URL
设置为https://some.site/and/url
。而以下
expand.py
中的脚本:
import sys
import os
from pathlib import Path
import ruamel.yaml
def substenv(d, env):
if isinstance(d, dict):
for k, v in d.items():
if isinstance(v, str) and '${' in v:
d[k] = v.replace('${', '{').format(**env)
else:
substenv(v, env)
elif isinstance(d, list):
for idx, item in enumerate(d):
if isinstance(v, str) and '${' in v:
d[idx] = item.replace('${', '{').format(**env)
else:
substenv(item, env)
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(Path(sys.argv[1]))
substenv(data, os.environ)
yaml.dump(data, Path(sys.argv[2]))
您可以执行以下操作:
python expand.py input.yaml output.yaml
其中写着output.yaml
:
order-lunch-app-health:
request:
url: https://some.site/and/url
headers:
content-type: 'application/text'
method: get
expectedResponse:
statusCode: 200
maxRetryCount: 5
请注意,“应用程序/文本”周围的虚假引号以及任何注释都将保留 在原始文件中。
被替换的URL周围的引号不是必需的,但是如果需要的话,将被添加。
substenv
例程递归遍历加载的数据,并且即使替换是在中间标量中并且一个标量中有多个替换,它也会进行替换。您可以“加强”测试:
if isinstance(v, str) and '${' in v:
如果可以匹配从YAML加载的太多字符串。