Default Attributes in Chef

Как мы знаем, если мы в Chef используем какой-то произвольный атрибут node.foobar, и если у нас он в этот момент неопределен мы получаем exception.

Это можно обойти несколькими способами:

  • Конструкция вида node.attribute?('foobar') ? node.foobar : 'some_default' или она же завернутая в хелпер-функцию. Это по очевидным причинам довольно неудобно.
  • Просто задаем умолчания (nil) в файле атрибутов для всех атрибутов, которые мы используем за исключением тех, на которых нам обязательно нужно падать. Вариант хороший, у нас всегда есть документация по всем используемым атрибутам, но он начинает работать со скрипом, когда мы дергаем атрибут из другого кукбука, который у нас в ранлисте может встречаться, а может и не встречаться. Переопределять родительский атрибут в своих атрибутах нельзя, т.к. получим неопределенное поведение, приходиться вручную заводить какие-то умолчания для нод или окружений.
  • Для всех таких случаев используем конструкцию (( node.foobar rescue 'some_default' )). Именно так, с двойными скобками, иначе мы не сможем ее передавать параметром внутри определения ресурса.
Пример
1
2
3
4
5
template "/tmp/myfile" do
  source (node.template rescue "template.erb")   # так не пропустит синтаксис ruby
  mode    node.mode     rescue "0644"            # так сработает неправильно (см. ниже)
  owner ((node.owner    rescue "root"))      # <-- так правильно
end

Второй вариант кажется нормальным, но он будет выполняться как (some_other_parameter node.foobar) rescue "xi-xi", что очевидно делает совсем не то, что нам надо — значение по-умолчанию не передается внутрь LWRP в случае exception, как мы здесь ожидаем.

Какой вариант лучше? Все хороши. Я уже давным давно пользуюсь вторым и чуть менее давно — третьим. Заводить функцию под первый вариант не нравится, т.к. придется всюду таскать ее или зависимость на кукбук, который ее определеяет.

Еще есть хороший вариант, предлагаемый Evil Martians — заворачивать в LWRP все что можно, но с этим вариантом проблема такая же как со многими хорошими паттернами программирования: если ты сразу его не применил, придется в какой-то момент останавливаться и делать глобальный рефактор всего.

Comments