我是厨师的新手,遇到了berkshelf和厨师 - 客户的问题。我想拥有自己的食谱与依赖并应用它。我最初的食谱看起来像这样:
.
├── Berksfile
├── Berksfile.lock
├── chefignore
├── client.rb
├── Gemfile
├── Gemfile.lock
├── metadata.rb
├── README.md
└── recipes
└── default.rb
#./Berksfile
source 'https://supermarket.getchef.com'
metadata
cookbook 'znc'
#./client.rb
cookbook_path '~/.berkshelf/cookbooks'
当我运行sudo bundle exec chef-client -z -o znc --config=client.rb
时,厨师 - 客户找不到食谱:
Starting Chef Client, version 11.16.4
[2014-10-25T15:34:59+02:00] WARN: Run List override has been provided.
[2014-10-25T15:34:59+02:00] WARN: Original Run List: []
[2014-10-25T15:34:59+02:00] WARN: Overridden Run List: [recipe[znc]]
resolving cookbooks for run list: ["znc"]
================================================================================
Error Resolving Cookbooks for Run List:
================================================================================
Missing Cookbooks:
------------------
No such cookbook: znc
Expanded Run List:
------------------
* znc
Running handlers:
[2014-10-25T15:34:59+02:00] ERROR: Running exception handlers
Running handlers complete
[2014-10-25T15:34:59+02:00] ERROR: Exception handlers complete
[2014-10-25T15:34:59+02:00] FATAL: Stacktrace dumped to /home/sebastian/.chef/local-mode-cache/cache/chef-stacktrace.out
Chef Client failed. 0 resources updated in 3.474758165 seconds
[2014-10-25T15:34:59+02:00] ERROR: 412 "Precondition Failed "
[2014-10-25T15:34:59+02:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
还要注意:
ls ~/.berkshelf/cookbooks
build-essential-2.1.2 znc-0.0.1
为什么无法找到食谱的任何建议?
感谢您的快速回答。解决方案就像John Bellone对bundle exec berks vendor
说的那样,并将我的client.rb
配置更改为:
# ./client.rb
cookbook_path File.dirname(File.expand_path(__FILE__)) + '/berks-cookbooks'
答案 0 :(得分:12)
默认情况下,Chef Client会查找一些目录。其中一个是我们可以利用$CWD/cookbooks
命令的berks vendor cookbooks
。我发现在测试期间(特别是使用自动化过程)更容易实现这一点,因为它确保我获得了新的烹饪书副本而不是缓存的陈旧副本。
如果您希望简单地启动并运行环境,我建议您使用带有vagrant-berkshelf插件的Vagrantfile。这将自动供应缓存目录中的所有cookbook并将其上载到来宾计算机。如果您使用的提供商是云提供商,例如,它甚至可以工作。亚马逊,Backspace,因为它将使用rsync而不是共享目录。
答案 1 :(得分:2)
我使用以下脚本,这允许我使用git repo和我的烹饪书,这些食谱依赖于超市里的食谱而没有厨师服务器。将以下内容放在名为local-chef-client
的文件中,与您的cookboks目录处于同一级别。然后,您可以将本地计算机与./local-chef-client "recipe[some::default]"
聚合在一起。
#!/bin/bash
cmd="berks vendor -b $(pwd)/cookbooks/Berksfile"
pushd /tmp
rm -rf cookbooks
$cmd
mv berks-cookbooks cookbooks
sudo chef-client -z -r "$@"
popd
答案 2 :(得分:1)
所有归功于@ revau.lt的回答,因为我只为自己的使用做了一些调整。这可能需要某个版本的Berkshelf,但我见过的所有文档都暗示你可以使用" PATH"最后告诉它在哪里放置依赖项。这也明确地清除了$tmpdir
,因为一些文件最终以运行方式作为root拥有。
我通过./local-chef-client my_cookbook_name
或./local-chef-client path/to/chef-repos/specific_repo
的任何主厨食谱回购路径运行此路径,其中路径由pwd -P
解析,cookbook
为basename
脚本中引用的$1
。
#!/bin/bash -x
: ${1:?"Usage: $0 ./path/to/cookbook [doit]"}
case $1 in
.) cookbook=$(basename $(pwd -P $1));repodir=$(dirname $(pwd -P $1));;
*) cookbook=$(basename $1);repodir=$(pwd -P $1);;
esac
case $2 in
doit) whyrun="";;
*) whyrun="-W ";;
esac
realcookbook=$(grep '^name' $repodir/$cookbook/metadata.rb | sed "s/'//g" | awk '{ print $2 }')
# echo "cookbook is $cookbook"
# echo "realcookbook is $realcookbook"
# echo "repodir is $repodir"
cmd="berks vendor -b $repodir/$cookbook/Berksfile cookbooks"
tmpdir=$(mktemp -d)
pushd $tmpdir
$cmd
sudo chef-client $whyrun -z -o "$realcookbook"
popd
sudo rm -rf $tmpdir
if [ ! "${whyrun}x" == "x" ]; then echo "Append 'doit' after the recipe name to really apply, eg $0 $1 doit"; fi
这应该处理有人从内部仓库运行它的情况,或几乎任何回购路径。我有一天必须写一些BATS测试来证明这一点,但是现在它的工作非常出色。
我更新了它以处理与食谱名称不匹配的文件夹,以防存储库名称不匹配或某人克隆到自定义路径。我实际上有人在我的指导下尝试这个,然后不得不深入了解Chef并找出它为什么不起作用,结果文件夹名称比食谱/食谱名称稍微重要。
答案 3 :(得分:0)
对于本地开发,本地模式会查找config.rb
或knife.rb
,从以下顺序开始$KNIFE_HOME
,$PWD
,.chef/
,最后{ {1}} *。
$HOME/.chef/
lib/chef-config/workstation_config_loader.rb
来自chef-config-13.8.5
load_config_file()
client.rb
chef-13.8.5
方法
cookbook_path
的{{1}}无效,原因有两个:(1)首先,您只能使用命令行中的'~/.berkshelf/cookbooks'
,来自ruby中的~
,以及( 2)该位置具有版本化的烹饪书,例如ENV['HOME']
,当主厨正在寻找foo-0.4.6
时,它无法解决。
对于本地模式,必须在运行foo
后在某处保存下载的食谱,例如本地berks-cookbooks
目录。如果你使用berks vendor
使用当前的chef13模式,那么你必须从你的食谱中获取超市食谱的所有参考资料。元数据,将其放在主metadata.rb
,然后是供应商食谱,然后从您的配置(Berksfile
)中引用这个新的berks-cookbooks
。
在您自己的食谱中,knife.rb
依赖于行,例如:
metadata.rb
depends 'hostsfile', '~> 3.0.1'
会使用以下内容引用它:
Berksfile
您需要创建一个引用source 'https://supermarket.chef.io'
metadata
目录中所有依赖项的Berksfile
。我在chef-repo级别使用shell脚本,如下所示:
cookbooks/
这会在同一级别创建#!/usr/bin/env bash
cat <<-EOF > Berksfile
source 'https://supermarket.chef.io'
$(grep -Rh 'depends' cookbooks/* | sed 's/depends/cookbook/')
EOF
berks vendor
。
现在您需要berks-cookbooks
或config.rb
来引用本地开发的两个食谱位置。
knife.rb
作为最后一个提示,有许多方法可以将本地开发与主厨服务器工作流分开。就个人而言,我使用git子模块,其中chef-repo在其自己的git仓库中,并且拥有自己的chef_repo = File.join(File.dirname(__FILE__), '/path/to/chef-repo')
site_cookbooks = "#{chef_repo}/cookbooks"
berks_cookbooks = "#{chef_repo}/berks-cookbooks"
cookbook_path [site_cookbooks, berks_cookbooks]
(由于它具有使用Chef服务器的凭据,因此在.chef
中)。
在我的开发环境中,我有一个子目录.gitignore
和我的本地开发 ${orgname}-chef-repo
配置为使用.chef/knife.rb
。当我berks-cookbooks
时,我运行shell脚本,创建cd ${orgname}-chef-repo
和Berksfile
目录,然后运行berks-cookbooks
,使用本地凭据将所有依赖项上传到服务器。然后berks install
返回我的本地开发环境,并使用vagrant,knife-zero和其他工具执行 local dev 。