厨师在ruby块中使用cookbook_文件

厨师在ruby块中使用cookbook_文件,ruby,chef-infra,cookbook,Ruby,Chef Infra,Cookbook,我有以下代码来确定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]

我有以下代码来确定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\u文件
资源失败,因为它找不到目录:

No such file or directory @ dir_chdir - /ourapp/jre-server/linux/
经过大量的谷歌搜索,我得出结论,这是一个。。配方的编译时和运行时之间的“错配”(?)。基本上,如果我理解正确,它会首先尝试运行
cookbook\u文件
resource,但失败了。因此,永远不要下载、解压和安装应用程序人工制品

当目录存在时,我试着运行
app\u java\u home
,它似乎按照我想要的方式工作

我尝试将
cookbook\u文件
资源放入
ruby\u块
,但结果是:

undefined method `cookbook_file' for Chef::Resource::RubyBlock
app\u java\u主页
。。函数(?)通常如下所示:

def app_java_home
  "#{app_home}/jre-server/linux/#{jdk_version}"
end
其中,
jdk_版本
来自数据包。这很好,但我们的系统中有一个长期存在的bug/特性请求,有时“他们”将其放入数据库的版本弄错,从而导致各种各样的问题。。因此,他们希望找到一种方法来消除这种依赖性,而不是动态地“解决这个问题”


Ruby和Chef不是我的强项,所以我不确定下一步该怎么做。我找到了对
Chef::Resources::CookbookFile
的引用(如果我理解的话,可以/应该在
ruby_block
s中使用),但找不到任何关于它的示例或文档。RubyDocs上的链接已断开。

请在此处添加答案以获得更好的解释

  • 任何不在Chef资源中的(Ruby)代码都将在编译阶段运行

  • 所有资源声明将按照定义的顺序在聚合阶段运行

谢天谢地,如果需要的话,有一种方法可以使资源在编译阶段运行。尽管我认为在特殊情况下,这项工作应该谨慎进行

根据您的评论,
aws_s3_文件
execute
资源是解包应用程序(并创建目录)的资源。在本例中,您似乎希望它们在编译阶段运行


厨师长客户端16.0之前的版本

run_action
选项与应在编译时执行的操作一起使用。例如
execute
资源执行操作
:run

#注意动作:无”和“运行动作”
执行'extract'do
用户“根”
命令“解压#{app_download_path}/#{app_s3['archive_file']}>/dev/null”
如果{::Dir.存在,则不存在(“{app_home}/ourapp”)}
只有{::File.exists?(“{app_download_path}/{app_s3['archive_File']}”)}
行动:没什么
结束。运行\u操作(:运行)

厨师长客户端16.0版以后的版本

我们可以在资源中添加一个。使用
execute
资源的示例:

#注意额外的属性“compile_time”
执行'extract'do
用户“根”
命令“解压#{app_download_path}/#{app_s3['archive_file']}>/dev/null”
如果{::Dir.存在,则不存在(“{app_home}/ourapp”)}
只有{::File.exists?(“{app_download_path}/{app_s3['archive_File']}”)}
编译时间为true
结束

最后回答问题的主题:

厨师在ruby块中使用cookbook_文件

这是不可能的。参考顶部的第一点。如果我们希望Ruby代码在converge期间运行(而不是编译),我们将其放在
Ruby_块
资源中。因此,它可以包含如下代码(例如):

ruby_块'get directory'do
布洛克道
def app_java_主页
“#{app_home}/jre server/linux/#{jdk_version}”
结束
结束
结束

在@seshadri_c的帮助下,我终于解决了这个问题!这需要一些努力,因为我一直误解这些建议等等

这就是我(为后代)想到的:

事实证明,我只需要单独获取版本,所以我重新安排了一些函数。我相信它可以写得更干净,但这里的技巧是使用
返回
,而不是
放置/打印
!嗯,我是个程序员,但不是Ruby程序员,所以我不知道这是一个选择

然后,在食谱中,我在需要的地方添加了
.run\u action()
。我不需要它们作为
烹饪书\u文件
,这简化了一些事情:

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

有了这些,所有的东西都在它们应该运行的时候运行,而且一切似乎都在工作。

这本食谱是
app\u java\u home
的一部分吗?如何运行它?我将代码放入Ruby shell并运行它。在创建目录之前和之后,它都可以工作。当它出现在烹饪书(libraries/attributes.rb)中时,问题在于它似乎是在“错误的时间”运行的。从所发布的简明错误中无法判断,但是
@dir\u chdir
似乎表明
app\u java\u home
方法中的
dir.chdir
存在问题。
cookbook\u文件
资源不需要更改目录。
{app_home}
是由配方中的代码创建的吗?没错。问题是
cookbook\u文件
aws\u s3\u文件
和两个
execute
之前运行,这两个
execute将解包并安装应用程序。因此,当
cookbook\u文件运行时,该目录还不存在。Ok。因此,当您在编译时运行recipe-
app\u java\u home
home运行以获取返回值时,就会发生这种情况。配方中声明的所有资源都将在converge阶段按照定义的顺序运行。只有在
aws\u s3\u文件
上面有
cookbook\u文件
资源时,它才会在它前面运行,否则就不会运行。如果我在两个
execute
aws\u s3\u文件
中放入
compile\u time true
,我会得到
未定义的方法
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