15

我是厨师新手,遇到了 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.rbchef-client 时找不到食谱:

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'
4

4 回答 4

12

默认情况下,Chef Client 会在几个目录中查找说明书。其中之一是$CWD/cookbooks我们可以利用该berks vendor cookbooks命令。我发现在我的测试过程中(尤其是使用自动化过程)更容易做到这一点,因为它可以确保我得到一份新的食谱副本,而不是缓存的、陈旧的副本。

如果您只是想简单地启动并运行一个环境,我建议您使用带有vagrant-berkshelf插件的 Vagrantfile。这将自动供应缓存目录中的所有食谱并将其上传到客户机。如果您使用的提供商是云提供商,例如 Amazon、Backspace,它甚至可以工作,因为它将使用 rsync 而不是共享目录。

于 2014-10-25T15:17:04.317 回答
3

我正在使用以下脚本,这允许我将 git repo 与我的食谱一起使用,这些食谱依赖于超市中的食谱但没有厨师服务器。将以下内容放在local-chef-client与您的食谱目录相同级别的文件中。然后,您可以将本地机器与./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
于 2015-10-29T19:09:42.283 回答
1

所有功劳归功于@revau.lt 的回答,因为我只为我自己的使用做了一些调整。这可能需要某个版本的 Berkshelf,但我看到的所有文档都暗示您可以在最后使用“PATH”来告诉它将依赖项放在哪里。这也显式地清理了$tmpdirafter,因为某些文件最终在运行时以 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 并找出它为什么不起作用,结果发现文件夹名称比食谱/食谱名称更重要。

于 2017-11-14T00:29:29.990 回答
0

对于本地开发,本地模式查找config.rbor knife.rb,按以下顺序开始$KNIFE_HOME$PWD, .chef/,最后是$HOME/.chef/*。

  • 来源: lib/chef-config/workstation_config_loader.rbchef-config-13.8.5gem中从gem中的load_config_file()方法调用client.rbchef-13.8.5

cookbook_pathof 无效有'~/.berkshelf/cookbooks'两个原因,(1)首先,您只能~从命令行使用,ENV['HOME']在 ruby​​ 中,以及(2)该位置具有版本化的食谱,例如foo-0.4.6,当厨师运行正在寻找时无法解决foo

对于本地模式,必须将食谱下载到保存在某个地方,例如berks-cookbooks运行后的本地目录berks vendor。如果您使用当前的 chef13 模式 using metadata.rb,那么您必须从您的食谱的元数据中获取对超市食谱的所有引用,将其放入 main Berksfile,然后是供应商食谱,然后berks-cookbooks从您的配置中引用这个新的 ( knife.rb)。

具有 Berks 模式的元数据

在您自己的食谱中,metadata.rb取决于行,例如:

depends 'hostsfile', '~> 3.0.1'

会参考使用这样的Berksfile东西:

source 'https://supermarket.chef.io'
metadata

创建主 Berksfile

您需要创建一个Berksfile引用目录中所有依赖项的cookbooks/文件。我在我的 chef-repo 级别使用了一个 shell 脚本,如下所示:

#!/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引用两个食谱位置的本地开发。

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]

可选(本地开发与厨师服务器)

最后一个提示,有许多方法可以将本地开发人员与厨师服务器工作流程分开。就我个人而言,我使用 git 子模块,其中 chef-repo 位于它自己的 git repo 中,它是自己的.chef.gitignore因为它具有使用 Chef 服务器的凭据)。

在我的开发环境中,我有一个子目录${orgname}-chef-repo,并且我的本地开发 .chef/knife.rb人员配置为使用berks-cookbooks. 当 I 时cd ${orgname}-chef-repo,我运行 shell 脚本,创建Berksfileberks-cookbooks目录,然后运行berks install它使用本地凭据将所有依赖项上传到服务器。然后cd ..回到我的本地开发环境,使用 vagrant、knife-zero 和其他工具做本地开发工作。

于 2018-04-25T18:35:11.467 回答