[英]Chef use cookbook_file in ruby block
我有以下代码来确定 Java 在盒子上的位置。 Java 随我们的应用程序一起提供,并且应用程序中包含的 Java 版本有所不同。
def app_java_home
if Dir.exist?("#{app_home}/jre-server/linux")
Dir.chdir("#{app_home}/jre-server/linux") do
Dir.glob('jdk*').select { |f| File.directory? f }[0]
end
end
end
然后,在我的食谱中,我有
aws_s3_file "#{app_download_path}/#{app_s3['archive_file']}" do
bucket app_s3['bucket']
remote_path app_s3['remote_path']
region aws_region
not_if { ::Dir.exists?(app_bin_dir) }
not_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end
execute 'extract' do
user 'root'
command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
not_if { ::Dir.exists?("#{app_home}/ourapp") }
only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end
execute 'move' do
user 'root'
command "mv #{app_download_path}/ourapp/ #{app_install_path}"
not_if { ::Dir.exists?(app_home) }
end
cookbook_file "#{app_java_home}/jre/lib/security/local_policy.jar" do
source %W[#{app_release}/local_policy.jar default/local_policy.jar]
owner app_user_name
group app_group_name
mode 0755
end
cookbook_file "#{app_java_home}/jre/lib/security/US_export_policy.jar" do
source %W[#{app_release}/US_export_policy.jar default/US_export_policy.jar]
owner app_user_name
group app_group_name
mode 0755
end
但是,这两个cookbook_file
资源失败,因为它找不到目录:
No such file or directory @ dir_chdir - /ourapp/jre-server/linux/
经过大量的谷歌搜索后,我得出的结论是,配方的编译时间和运行时间之间存在“不匹配”(?)。 基本上,如果我理解正确,它会首先尝试运行cookbook_file
资源但失败。 所以永远不要下载、解压和安装应用程序工件。
当目录存在时,我尝试运行app_java_home
,它似乎确实按我想要的方式工作..
我尝试将cookbook_file
资源放在ruby_block
中,但后来我得到了:
undefined method `cookbook_file' for Chef::Resource::RubyBlock
app_java_home
.. function (?) 曾经看起来像这样:
def app_java_home
"#{app_home}/jre-server/linux/#{jdk_version}"
end
jdk_version
来自数据包的位置。 这工作得很好,但是我们的系统中有一个长期存在的错误/功能请求,有时会发生“他们”得到他们放入数据包中的版本错误,导致各种问题.. 所以他们想要一种方法来删除这个依赖,而是动态地“解决这个问题”。
Ruby 和 Chef 不是我的强项,所以我不确定接下来要尝试什么。 我找到了对Chef::Resources::CookbookFile
的引用(如果我理解的话,可以/应该在ruby_block
中使用它),但找不到任何关于它的示例或文档。 RubyDocs 上的链接已损坏。
在此处添加答案以获得更好的解释。
不在任何 Chef 资源中的任何 (Ruby) 代码都将在编译阶段运行
所有资源声明都将按照定义的顺序在 Convergence 阶段运行
值得庆幸的是,如果需要,有一种方法可以使资源在编译阶段运行。 尽管恕我直言,但在特殊情况下应该谨慎行事。
根据您的评论aws_s3_file
和execute
资源是解压应用程序(并创建目录)的资源。 在这种情况下,您似乎希望它们在编译阶段运行。
在 Chef 客户端 16.0 之前
将run_action
选项与应在编译时执行的操作一起使用。 例如execute
资源采取行动:run
:
# Note action ":nothing" and "run_action"
execute 'extract' do
user 'root'
command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
not_if { ::Dir.exists?("#{app_home}/ourapp") }
only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
action :nothing
end.run_action(:run)
Chef 客户端 16.0 及以上版本
我们可以为资源添加一个公共属性。 execute
资源示例:
# Note the extra property "compile_time"
execute 'extract' do
user 'root'
command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
not_if { ::Dir.exists?("#{app_home}/ourapp") }
only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
compile_time true
end
最后回答问题的主题:
厨师在 ruby 块中使用 cookbook_file
这是不可能的。 请参阅顶部的第一点。 如果我们希望 Ruby 代码在收敛期间运行(而不是编译),我们将其放在ruby_block
资源中。 所以它可以包含如下代码(例如):
ruby_block 'get directory' do
block do
def app_java_home
"#{app_home}/jre-server/linux/#{jdk_version}"
end
end
end
在@seshadri_c 的帮助下,我终于设法解决了这个问题,这需要一些努力。 因为我一直误解建议等。
所以这就是我想出的(为了后代):
def jdk_version(required = true)
base_dir = "#{app_home}/jre-server/linux"
if Dir.exist?("#{base_dir}")
Dir.chdir("#{app_home}/jre-server/linux") do
Dir.glob("jdk*").each do |f|
if File.directory?(f)
return "#{f}"
end
end
end
end
end
def app_java_home
return "#{app_home}/jre-server/linux/#{jdk_version}"
end
结果我只需要单独获取版本,所以我重新安排了一些功能。 我确信它可以写得更干净,但这里的诀窍是使用return
而不是puts/print
,嗯,我是一名程序员。 但不是 Ruby 程序员所以不知道这是一个选项..
然后,在食谱中,我在需要的地方添加了.run_action()
。 cookbook_file
我不需要它们,这稍微简化了一些事情:
aws_s3_file "#{app_download_path}/#{app_s3['archive_file']}" do
bucket app_s3['bucket']
remote_path app_s3['remote_path']
region aws_region
not_if { ::Dir.exists?(app_bin_dir) }
not_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end.run_action(:create)
execute 'extract' do
user 'root'
command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
not_if { ::Dir.exists?("#{app_home}/app") }
only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end.run_action(:run)
execute 'move' do
user 'root'
command "mv #{app_download_path}/app/ #{app_install_path}"
not_if { ::Dir.exists?(app_home) }
end.run_action(:run)
# JCE Unlimited Strength Jurisdiction Policy Files
cookbook_file "#{app_java_home}/jre/lib/security/local_policy.jar" do
source %W[#{app_release}/local_policy.jar default/local_policy.jar]
owner app_user_name
group app_group_name
mode 0755
end
cookbook_file "#{app_java_home}/jre/lib/security/US_export_policy.jar" do
source %W[#{app_release}/US_export_policy.jar default/US_export_policy.jar]
owner app_user_name
group app_group_name
mode 0755
end
有了这一切,一切都在他们应该的时候运行,一切似乎都在工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.