2015-07-22 1 views
0

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

Файл загружен с сервера jenkins и проанализирован в блоке ruby, чтобы получить значение - пока это так хорошо. Однако, если я попытаюсь назначить это атрибуту node, это не сработает. Я думал, что нашел ответ здесь: How to lazily evaluate an arbitrary variable with Chef, но ни один из методов, упомянутых здесь, не работает для меня. Что я делаю не так?

ruby_block "get build number" do 
    block do 
    f = File.open("/tmp/MyappJenkinsBuildInfo.txt") 
    f.each {|line| 
     line_arr = line.split('=') 
     if line_arr[0] == 'jenkins.build.number' 
     node.default['myapp']['jenkins']['build'] = line_arr[1] 
     break 
     end 
    } 
    f.close 
    end 
end 

build = DelayedEvaluator.new { node['myapp']['jenkins']['build'] } 

release_dir = "#{node['myapp']['dir']['main']}/releases/#{build.call}" 

Это «работает» в том, что нет синтаксических ошибок, но значение # {build.call} является пустой строкой. Файл определенно существует, и я уже тестировал, что строка line_arr [1] внутри блока ruby ​​получает правильное значение (с выражением puts внутри RB). Я также пытался использовать лямбда вместо DelayedEvaluator.new.

ответ

1

Проблема здесь состоит в том, что ваша release_dir = линия становится выполняться во время компиляции, перед тем код в вашем ruby_block побежал. Очевидно, что в этот момент build.call просто вернет пустую строку, потому что код, который устанавливает node['myapp']['jenkins']['build'], еще не запущен.

Другими словами, код в рецепте становится выполняется так:

# Compile time 

ruby_block "get build number" do 
    block do 
    # Random stuff here that will get executed at converge time 
    end 
end 

build = DelayedEvaluator.new { node['myapp']['jenkins']['build'] } 

release_dir = "#{node['myapp']['dir']['main']}/releases/#{build.call}" 

# ... 

# Okay, everything's compiled. Now we converge... 

f = File.open("/tmp/MyappJenkinsBuildInfo.txt") 
f.each {|line| 
    line_arr = line.split('=') 
    if line_arr[0] == 'jenkins.build.number' 
    node.default['myapp']['jenkins']['build'] = line_arr[1] 
    break 
    end 
} 
f.close 

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

+0

Ах, я понимаю - я ожидал, что # {build.call} автоматически получит новое значение. Тем не менее, под строкой build = ... я добавил оператор журнала (который запускается во время сближения), и это тоже получилось пустым. например - 'log 'Build is # {build.call}« do level: info end »создал журнал [Build is] на выходе – linxit

+0

@linxit Сам журнал работает во время схождения, но не в коде Ruby, который его конфигурирует. 'log 'Build is # {build.call}" 'действительно ничем не отличается от' some_variable = build.call; log «Build is # {some_varaible}» 'с точки зрения интерпретатора Ruby. – Ajedi32

+0

Хмм, невозможно установить переменную во время компиляции, поэтому я в основном превратил весь рецепт в ruby_block. Уродливый, но он работает сейчас! – linxit

Смежные вопросы