How to run tests from the ChefDK in Docker
It can be really helpful to run your local ChefDK setup using Docker, rather than installing it on your workstation, to ensure that everything works with a clean ChefDK.
I'll be taking you through this process, while avoiding editing the existing upstream image, instead overriding specific functionality using command-line flags on the host.
Getting it running
Let us assume that we're using ChefDK version v3.5.13, but this should be valid for any other ChefDK version. We can start this off by checking the versions of the core ChefDK tools by running:
$ docker run --rm -ti chef/chefdk:3.5.13 chef --version
Chef Development Kit Version: 3.5.13
chef-client version: 14.7.17
delivery version: master (6862f27aba89109a9630f0b6c6798efec56b4efe)
berks version: 7.0.6
kitchen version: 1.23.2
inspec version: 3.0.52
Running our unit tests + linting
We'll use the Java cookbook in this example, as it's got all aspects of cookbook workflow to try out.
Assuming we have the following directory structure:
$ pwd
~/cookbooks
$ ls ~/cookbooks
java
We make sure that we mount our cookbook into a known path, such as /cookbook
, which helps with mapping a consistent structure:
$ docker run --rm -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 ls /cookbook
attributes CODE_OF_CONDUCT.md LICENSE resources TESTING.md
Berksfile CONTRIBUTING.md metadata.rb spec
CHANGELOG.md Dangerfile README.md templates
chefignore libraries recipes test
As we're mounting the cookbook into a new folder, we want to set Docker's WORKDIR
to automagically cd
into that directory, instead of us running that each time:
$ docker run --rm -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 ls
attributes CODE_OF_CONDUCT.md LICENSE resources TESTING.md
Berksfile CONTRIBUTING.md metadata.rb spec
CHANGELOG.md Dangerfile README.md templates
chefignore libraries recipes test
Cookstyle
Now we have our setup ready, we want to run our code style checks through cookstyle
:
$ docker run --rm -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 cookstyle
Inspecting 68 files
....................................................................
68 files inspected, no offenses detected
FoodCritic
For our Chef-specific linting, we run foodcritic
:
$ docker run --rm -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 foodcritic .
Checking 11 files
...........
ChefSpec
If we want to check that our unit tests pass successfully, we'd run rspec
:
$ docker run --rm -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 rspec
..........................................WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.WARNING: you must specify a 'platform' and optionally a 'version' for your ChefSpec Runner and/or Fauxhai constructor, in the future omitting the platform will become a hard error. A list of available platforms is available at https://github.com/chefspec/fauxhai/blob/master/PLATFORMS.md
.....
Finished in 0.69453 seconds (files took 2.4 seconds to load)
56 examples, 0 failures
Test Kitchen
Depending on which driver you're using, this step may or not be possible - for instance, getting a Vagrant instance running from a Docker image may not be possible.
Kitchen-EC2
Depending on how you have the EC2 driver for Test-Kitchen, kitchen-ec2 configured, you may have a configuration file in your home directory (~/.kitchen/config.yml
) which has configuration such as default tags for an instance. This will need to be mounted into the image:
$ docker run --rm -w=/cookbook -v ~/.kitchen/config.yml:/root/.kitchen/config.yml -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 kitchen test
Note that this all should work as long as the docker image can access the EC2 metadata endpoint (see Not using the proxy for the EC2 Metadata Endpoint below), you're good to go!
Hey, what about internal setups?
You may be running in an environment where your services are not publicly accessible, or are having to route through a proxy. The following changes may be required:
Trusting Internal Certificates
Following the steps in Trusting Self-Signed Certificates from the Chef Development Kit, we would want to modify Chef's certificates to trust the internal certificate. However, if we want to use our upstream images as-is, we can instead mount a custom CA certs bundle into the image, otherwise we would receive an error similar to:
$ docker run --rm -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 berks
[2018-12-05T19:00:28+00:00] ERROR: SSL Validation failure connecting to host: supermarket.example.com - SSL_connect returned=1 errno=0 state=error: certificate verify failed
#<Thread:0x00000000023ae308@/opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/berkshelf-7.0.6/lib/berkshelf/installer.rb:21 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
8: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/berkshelf-7.0.6/lib/berkshelf/installer.rb:24:in `block (2 levels) in build_universe'
7: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/berkshelf-7.0.6/lib/berkshelf/source.rb:85:in `build_universe'
6: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/berkshelf-7.0.6/lib/berkshelf/api_client/connection.rb:47:in `universe'
5: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/berkshelf-7.0.6/lib/berkshelf/ridley_compat.rb:37:in `get'
4: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-14.7.17/lib/chef/http.rb:115:in `get'
3: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-14.7.17/lib/chef/http.rb:149:in `request'
2: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-14.7.17/lib/chef/http.rb:365:in `send_http_request'
1: from /opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-14.7.17/lib/chef/http.rb:408:in `retrying_http_errors'
/opt/chefdk/embedded/lib/ruby/gems/2.5.0/gems/chef-14.7.17/lib/chef/http.rb:451:in `rescue in retrying_http_errors': SSL Error connecting to https://supermarket.example.com/universe - SSL_connect returned=1 errno=0 state=error: certificate verify failed (OpenSSL::SSL::SSLError)
OpenSSL::SSL::SSLError SSL Error connecting to https://supermarket.example.com/universe - SSL_connect returned=1 errno=0 state=error: certificate verify failed
Assuming you have followed the steps in Trusting Self-Signed Certificates from the Chef Development Kit, you should be able to mount your trusted_certs
folder:
# with our pre-downloaded trusted certificates
$ docker run --rm -w=/cookbook -v ~/.chef/trusted_certs:/root/.chef/trusted_certs -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 berks
Fetching cookbook index from https://supermarket.example.com...
Installing homebrew (5.0.8)
Using java (3.1.2) from source at .
Installing windows (5.2.2)
Using test (0.1.0) from source at test/fixtures/cookbooks/test
Not using proxy for internal hosts
If we've got an internal Supermarket and are operating behind a proxy, we'd want to follow the steps within SSLError
When Running Berkshelf Behind a Proxy and add our Supermarket's FQDN to our no_proxy
. I.e. when we're running our ChefSpec tests:
$ docker run --rm -e no_proxy=supermarket.example.com -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 rspec
Not using the proxy for the EC2 Metadata Endpoint
If you're using i.e. kitchen-ec2 as a Test Kitchen driver, you'll also need to add the EC2 metadata endpoint to your no_proxy
list:
$ docker run --rm -e no_proxy=169.254.169.254 -w=/cookbook -v $PWD/java:/cookbook -ti chef/chefdk:3.5.13 kitchen test
Without this, you'll receive errors around not being able to access credentials.