Доступ к переменным среды в файле YAML для проекта Ruby (с использованием синтаксиса $ {ENVVAR}) - PullRequest
3 голосов
/ 27 апреля 2019

Я строю проект с открытым исходным кодом, используя 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.

Ответы [ 2 ]

1 голос
/ 27 апреля 2019

Я считаю, что что-то подобное должно работать в большинстве случаев:

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}

Конечно, есть много способов, которые можно улучшить.

0 голосов
/ 27 апреля 2019

Предварительная обработка проста, и я рекомендую вам использовать решение на основе YAML loaderd / dumper, так как замена может потребовать кавычек вокруг скаляра замены.(Например, вы подставляете строку true, если она не была заключена в кавычки, результирующий YAML будет читаться как логическое значение).

Предполагается, что ваш «источник» находится в input.yaml, а ваш env.переменная 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

Обратите внимание, чтоложные кавычки вокруг 'application / text' сохраняются, как и любые комментарии в исходном файле.

Кавычки вокруг замещенного URL не обязательны, но они были бы добавлены, если бы они были.

Подпрограмма substenv рекурсивно пересекает загруженные данные и выполняет замену, даже если подстановка находится в среднем скаляре, и если в одном скаляре больше, чем подстановка.Вы можете «затянуть» тест:

        if isinstance(v, str) and '${' in v:

, если это будет соответствовать слишком большому количеству строк, загруженных из YAML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...