puppet-rspe c - Как передать параметры во вложенные классы профилей во время модульного теста? - PullRequest
1 голос
/ 06 марта 2020

Я пытаюсь построить два профиля Puppet для DCS Hashicorp Consul. Консул может работать как клиент или агент сервера, а режим сервера является надмножеством режима клиента. Это напрямую отражается в конфигурации:

Агентам-агентам Consul обычно требуется расширенный набор конфигурации, требуемый агентами клиентов Consul.

Мой подход к проектированию Puppet основан на этом шаблоне : https://puppet.com/docs/pe/2018.1/the_roles_and_profiles_method.html

Согласно документации Puppet, должно быть возможно (и наиболее вероятно желательно) включить профиль consul_client в профиль consul_server, чтобы избежать дублирования кода:

Профили могут включать другие профили.

Пытаясь реализовать это, я использовал некоторые обязательные параметры для обоих профилей и столкнулся с проблемами во время выполнения автомата c rspe. c модульные тесты.

В файле consul_client модульных тестов consul_client_spec.rb я просто указал следующие обязательные параметры:

let(:params) { {
  'datacenter' => 'unit-test',
  'encrypt' => 'DUMMY',
  'server_agent_nodes' => [ '1.2.3.4' ]
} }

Проблемы, возникающие при попытке запустить consul_server_spec.rb модульный тест. Наивно, я только что передал один дополнительный обязательный параметр профиля consul_server:

let(:params) { {
  'bootstrap_expect' => 3,
} }

Поскольку профиль consul_client равен include ed / require, редактируемый профилем consul_server, проверка завершилась с отсутствующими параметрами для класса профиля consul_client. Похоже, это указывает на некоторые общие структурные проблемы с этим подходом.


Теперь я не уверен, стоит ли мне повторно объявлять все параметры класса профиля consul_client в профиле consul_server класс - который, на мой взгляд, нарушил бы принцип DRY. Кроме того, при использовании данных Hiera в будущем это может привести к ситуации, когда profile::consul_client::* и profile::consul_server::* будут содержать одни и те же дубликаты данных, так как часть данных, связанная с клиентом, должна будет повторяться для обоих profile.

Добавлено примечание: И дублирование параметров в классе consul_server, вероятно, даже не сработает, так как параметры не могут быть переданы явно, но только через данные, чтобы включить определения ресурсов, подобные включению - поэтому эти дублированные параметры не могут быть переданы в класс consul_client.

Напротив, в документации говорится следующее, но я не уверен, относится ли это к включенным классам профилей (поскольку они могут не быть компонентными классами?) а также:

Профили владеют всеми параметрами классов для своих классов компонентов. Если в профиле он отсутствует, это означает, что вам определенно нужно значение по умолчанию; класс компонента не должен использовать значение из данных Hiera. Если вам нужно установить параметр класса, который был пропущен ранее, выполните рефакторинг профиля.


В дополнение к этим соображениям можно также увидеть, как два класса профиля были преобразованы в обычные классы отдельный модуль, который может помочь понять последствия различных подходов к проектированию.


В заключение возникают следующие вопросы:

  • Как следует обрабатывать параметры во вложенных профилях, должны быть установлены исключительно данными hiera отдельно для каждого класса профилей?
  • Как передать параметры во вложенные профили во время модульных тестов? Будет ли правильным способом каким-то образом предоставлять фиктивные данные hiera как часть тестового приспособления?
  • Будет ли лучше использовать моделирование класса профиля consul_client?

1 Ответ

0 голосов
/ 07 марта 2020

Поскольку профиль consul_client имеет значение include ed / require, редактируемое профилем consul_server, проверка завершилась неудачно с отсутствующими параметрами для класса профиля consul_client. Похоже, это указывает на некоторые общие структурные проблемы с этим подходом.

Не особенно.

Следует понимать, что если вы используете объявление типа включения класса, который имеет обязательные параметры тогда эти параметры должны будут получить значения либо через автоматическое связывание данных c, либо через предыдущее объявление ресурса того же класса. Это ни в коем случае не «общая структурная проблема», хотя, в общем, в любом случае следует передавать параметры классам через Hiera (и, таким образом, автоматически c привязку данных).

Это становится немного сложнее в контексте модульного тестирования. Можно настроить данные Hiera для вашего набора тестов, но, вероятно, вместо этого проще написать предварительное условие. Я сделал что-то очень похожее только сегодня, на самом деле. Пример:

describe 'profile::consul_server' do
  # ...
  context "..." do
    let(:pre_condition) do
      'class { "profile::consul_client": param1 => "value1", param2 => "value2" }'
    end
    let(:params) { { bootstrap_expect: 3 } }

    it do
      is_expected.to # ...
    end
  end
end

HOWEVER , хотя здесь нет особых структурных проблем, существует вероятная проблема semanti c. Если ваш профиль consul_server включает ваш профиль consul_client, это означает, что каждый консул-сервер также должен быть консул-клиентом. Я не очень знаком с консулом, поэтому не могу быть уверен, что это не разумно, но, по крайней мере, подозрительно. Если серверы не обязательно являются клиентами, то код, который, как оказалось, совместно используется между двумя профилями, только случайно дублируется, и вытеснение такого случайного дублирования, скорее всего, вызовет проблемы, чем решит их.

Теперь, Я не уверен, стоит ли мне повторно объявлять все параметры класса профиля consul_client в классе профиля consul_server, что, на мой взгляд, нарушит принцип DRY. Кроме того, при использовании данных Hiera в будущем это может привести к ситуации, когда profile::consul_client::* и profile::consul_server::* будут содержать одни и те же дубликаты данных, так как часть данных, связанная с клиентом, должна будет повторяться для обоих профили.

Это разумные проблемы. Лично я минимизирую количество параметров, которые есть в моих профилях. У большинства их вообще нет. Мои классы компонентов параметризованы, и их значения параметров в основном происходят из автоматической привязки данных. Лишь в редких случаях мои профильные классы используют ресурсные объявления классов компонентов, но когда они это делают, он почти всегда определяется идентичностью профиля, а не его параметрами.

Кроме того, вы можете обнаружить, что это он облегчит вашу проблему для рефакторинга. Если между вашими консул-серверами и клиентами имеются подробные сведения о конфигурации, то они, вероятно, подойдут для управления через один или несколько классов компонентов, которые объявляют оба профиля. Тогда нет необходимости дублировать данные, потому что это параметры тех общих классов, к которым вы привязываете данные.

...