Can't resolve chef external cookbook dependency in local mode

I'm making my first recipes in chef. I created a cookbook i called common with just one recipe (default.rb):

apt_repository "mariadb-repo" do
  uri "http://tedeco.fi.upm.es/mirror/mariadb/repo/10.1/ubuntu"
  distribution "trusty"
  components ["main"]
  arch "amd64"
  keyserver "keyserver.ubuntu.com"
  key "CBCB082A"
end

I added "depends 'apt'" at the end of my metadata.rb. If i run:

Starting Chef Client, version 12.5.1
resolving cookbooks for run list: ["common"]

================================================================================
Error Resolving Cookbooks for Run List:
================================================================================

Missing Cookbooks:
------------------
No such cookbook: apt

Expanded Run List:
------------------
* common


Running handlers:
[2016-01-28T13:07:17+00:00] ERROR: Running exception handlers
Running handlers complete
[2016-01-28T13:07:17+00:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated in 01 seconds
[2016-01-28T13:07:17+00:00] FATAL: Stacktrace dumped to /home/vagrant/.chef/local-mode-cache/cache/chef-stacktrace.out
[2016-01-28T13:07:17+00:00] ERROR: 412 "Precondition Failed"
[2016-01-28T13:07:17+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)

Ok, so i added to my Berksfile:

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

cookbook 'apt'

metadata

Then tried installing apt cookbook to several locations:

$ berks install # installs to ~/.berkshelf/cookbooks/
$ berks vendor --except=common berks-cookbooks/

First thing i notice is that the second command packages both cookbooks, apt and my common, to the directory i specify (even passing --except=common). Nevermind: If i now try to run:

$ sudo chef-client --local-mode --runlist 'recipe[common]'

From my cookbook's (the one i called common) directory AND from the berks-cookbooks directory. None of both worked, the error above persist. I tried also with the following client.rb at my cookbook's directory:

cookbook_path = "./berks-cookbooks"
chef_repo_path = "#{cookbook_path}"

And some variations of these...

What am i missing? What's the way to get those dependencies correctly satisfied with chef-client in local mode?

What's the way of satisfying that dependencies?

'''EDIT 1''': Running without sudo does not work.


Chef client in local mode reads knife.rb as its config file, not client.rb. This makes sense when using it on a workstation with things like chef-provisioning, but can be quite unexpected when you are trying to use local-mode in production.

In general with local-mode you should use berks vendor to handle the export. Rather than running chef-client from the cookbook(s) folder, make a /root/local_mode_repo or similar, and run berks vendor /root/local_mode_repo/cookbooks. Then you can run chef-client --local-mode inside that folder. The specific folder names within the repo like roles/ and cookbooks/ are generally not configurable.


For local development, chef-client local-mode looks for config.rb or knife.rb, starting in the following order $KNIFE_HOME, $PWD, .chef/, and finally $HOME/.chef/*.

  • source: lib/chef-config/workstation_config_loader.rb in chef-config-13.8.5 gem called from load_config_file() method from client.rbin chef-13.8.5 gem

In your config.rb or knife.rb, you want your cookbooks_path to include both location of your cookbooks and berks_cookbooks:

cookbook_path = ["./cookbooks", "./berks-cookbooks"]

One trick I used scoop up all the dependencies is a small shell script that creates a Berksfile and then creates the berks-cookbooks directory.

#!/usr/bin/env bash
cat <<-EOF > Berksfile
source 'https://supermarket.chef.io'
$(grep -Rh 'depends' cookbooks/* | sed 's/depends/cookbook/')
EOF

berks vendor
berks install

Note that berks install will install the external cookbooks into your Chef Server so they are available to remote nodes, while berks vendor is what you can use for local development with the berks-cookbooks.

One tip, I keep my local dev one level up, and my chef-repo/.chef to have config for chef server:

    .
    ├── .chef
    │   └── knife.rb
    ├── my-chef-repo
    │   ├── berks-cookbooks
    │   ├── .chef
    │   │   └── knife.rb
    │   ├── cookbooks
    │   ├── data_bags
    │   ├── environments
    │   ├── nodes
    │   └── roles
    └── .vagrant
        └── machines