#ruby #chef-infra #metadata #chef-recipe
#ruby #шеф-повар-инфра #метаданные #шеф-повар-рецепт
Вопрос:
У меня есть кулинарная книга-оболочка, которая использует ресурсы из других кулинарных книг, но у них разные ограничения. Я попытался определить свои metadata.rb следующим образом :
name 'yp_linko'
maintainer 'The Authors'
maintainer_email 'devops@yp.ca'
license 'all_rights'
description 'Installs/Configures yp_linko'
long_description 'Installs/Configures yp_linko'
version '1.3.4'
depends 'apt'
if chef_version '<= 12' then
depends 'ypg_tomcat'
else
depends 'yp_tomcat'
end
Это не сработало, поскольку chef захватил обе кулинарные книги во время конвергенции. Я попробовал пару разных синтаксисов (only_if, если только и т.д.), И ни один из них не сработал. У кого-нибудь есть идеи по решению этой проблемы?
Комментарии:
1. как насчет переноса логики в рецепт?
Ответ №1:
TL; DR
Вы используете ограничение из Chef DSL таким образом, что оно не предназначено для использования. Вам нужно выполнять ветвление на основе логического выражения, а не ограничения метаданных. Я предоставляю пару способов сделать это, используя строку#to_f в качестве примеров (не рекомендуется, если вас интересуют уровни исправлений в семантическом управлении версиями), а также более точный, но часто упускаемый из виду Gem::Version.
Не используйте ограничение для ветвления
if chef_version '<= 12'
Вы пытаетесь использовать ограничение из DSL. Это ограничение имеет конкретную цель: объявить версии chef-client, поддерживаемые cookbook, а не обеспечивать логическое ветвление. Не глядя на базовый код Chef для DSL, я бы сказал, что маловероятно, что выражение передает ваше выражение if-then так, как вы ожидаете. Оставляя в стороне на данный момент, является ли это правильным шаблоном для всех, вы можете попробовать использовать текущую версию ваших инструментов Chef несколькими различными способами:
-
Ветвление в версии chef-client, вероятно, приведенное в виде числа с плавающей точкой (обычно это строка). Например:
if Chef::VERSION.to_f <= 12
-
Получите значение узла из ohai с помощью чего-то вроде:
if node['chef_packages']['chef']['version'].to_f <= 12
-
Проанализируйте значение непосредственно у клиента, например:
depends %x(chef-client --version).split[1].to_f <= 12 ? 'ypg_tomcat' : 'yp_tomcat'
Однако во всех случаях вам придется иметь дело с тем фактом, что вам передается строка, содержащая семантическое управление версиями, а не значение с плавающей точкой или целое число. Итак, вам нужно будет выяснить, как вы действительно хотите анализировать информацию, которая потенциально подвержена ошибкам (см. Ниже трюк с использованием Gem::Version, хотя). В любом случае, как только вы проанализируете его так, как хотите, вы можете сопоставить его с помощью оператора сравнения, чтобы получить желаемое поведение ветвления.
Лучшие варианты
Вместо того, чтобы пытаться заставить ограничение метаданных содержать бизнес-логику, вам, вероятно, следует перенести данные в атрибут. Рассмотрим такой атрибут, как node['yp_linko']['tomcat_cookbook']
, который вы можете установить на основе некоторого другого обнаруживаемого значения узла, отличного от семантического управления версиями.
Другим подходом было бы объявить обе кулинарные книги зависимостью, а затем включить ту, которую вы хотите включить в рецепт в вашей кулинарной книге yp_linko. Например, предполагая, что вы не объявили несовместимые версии chef-client в поваренных книгах Tomcat:
# metadata.rb
depends 'yp_tomcat'
depends 'ypg_tomcat'
# default.rb
if Chef::VERSION <= Gem::Version.new(12)
include ypg_tomcat::default
else
include yp_tomcat::default
end
И, наконец, вам следует подумать, действительно ли имеет смысл запускать разные версии ваших клиентов Chef в инфраструктуре в первую очередь. Это может быть бизнес-необходимостью, но это реальная проблема, которую вы на самом деле пытаетесь решить. Ветвление в ваших кулинарных книгах — это простое решение проблемы инфраструктуры. Кажется вероятным, что у вас были бы другие поваренные книги с похожими проблемами, поэтому, по крайней мере, стоит подумать, имеет ли смысл использовать для всех ваших клиентов одну и ту же версию, а не решать проблему на уровне поваренной книги.
Комментарии:
1. Спасибо за ваш действительно проницательный ответ. Мы находимся в процессе перевода всех узлов в среде на последнюю версию chef, чтобы обойти это. В настоящее время я возглавляю проект, но это длительная работа, поскольку у нас более 1000 узлов. Между тем, ваше первое решение (с использованием динамического атрибута) представляется наилучшим вариантом, потому что наличие зависимостей в метаданных приводит к инициализации поваренной книги во время конвергенции, что приводит к сбою конвергенции на этапе компиляции, поскольку некоторые методы, используемые в более старой версии, вообще не работают с chef > 13. Еще раз спасибо!