Skip to content

Instantly share code, notes, and snippets.

@ruffsl
Last active April 10, 2016 19:03
Show Gist options
  • Save ruffsl/f1abb7809a32bc54f2b4eabc9a629f58 to your computer and use it in GitHub Desktop.
Save ruffsl/f1abb7809a32bc54f2b4eabc9a629f58 to your computer and use it in GitHub Desktop.
Chef ROS example
ros 'indigo' do
config 'ros-core'
action :install
end
catkin '/opt/catkin_ws' do
release 'indigo'
action :create
end
FROM ubuntu:14.04
RUN apt-get update && \
apt-get install -y \
git \
wget \
expect
# Install Chef DK
RUN wget https://packages.chef.io/stable/ubuntu/12.04/chefdk_0.12.0-1_amd64.deb && \
dpkg -i chefdk_0.12.0-1_amd64.deb
WORKDIR /root
ADD myapp.exp myapp.exp
RUN expect myapp.exp && \
echo "source \"https://supermarket.chef.io\"\n metadata\n cookbook \"ros\"" > myapp/Berksfile && \
cd myapp && \
berks install
RUN cd myapp && \
berks package && \
cp cookbooks-*.tar.gz .. && \
tar -xf cookbooks-*.tar.gz
WORKDIR /root/cookbooks
ADD default.rb myapp/recipes/default.rb
RUN echo "cookbook_path = \"/root/cookbooks\"" > myapp/recipes/client.rb && \
chef-client --local-mode -c myapp/recipes/client.rb myapp/recipes/default.rb
spawn berks cookbook myapp
expect "Overwrite \/root\/myapp\/chefignore? \(enter \"h\" for help\) "
send "Y"
$ docker build --tag chef:foo .
...
Step 10 : RUN echo "cookbook_path = \"/root/cookbooks\"" > myapp/recipes/client.rb && chef-client --local-mode -c myapp/recipes/client.rb myapp/recipes/default.rb
---> Running in c7ba9a4511de
[2016-04-07T22:22:58+00:00] INFO: Auto-discovered chef repository at /root
[2016-04-07T22:22:59+00:00] INFO: Started chef-zero at chefzero://localhost:8889 with repository at /root
One version per cookbook
[2016-04-07T22:22:59+00:00] INFO: Forking chef instance to converge...
[2016-04-07T22:22:59+00:00] INFO: *** Chef 12.8.1 ***
[2016-04-07T22:22:59+00:00] INFO: Chef-client pid: 18
[2016-04-07T22:22:59+00:00] INFO: HTTP Request Returned 404 Not Found: Object not found: chefzero://localhost:8889/nodes/f0726407848b
[2016-04-07T22:22:59+00:00] INFO: Run List is []
[2016-04-07T22:22:59+00:00] INFO: Run List expands to []
[2016-04-07T22:22:59+00:00] INFO: Starting Chef Run for f0726407848b
[2016-04-07T22:22:59+00:00] INFO: Running start handlers
[2016-04-07T22:22:59+00:00] INFO: Start handlers complete.
[2016-04-07T22:22:59+00:00] INFO: HTTP Request Returned 404 Not Found: Object not found:
[2016-04-07T22:22:59+00:00] INFO: Loading cookbooks []
[2016-04-07T22:22:59+00:00] ERROR: Running exception handlers
[2016-04-07T22:22:59+00:00] ERROR: Exception handlers complete
[2016-04-07T22:22:59+00:00] FATAL: Stacktrace dumped to /root/cookbooks/myapp/recipes/local-mode-cache/cache/chef-stacktrace.out
[2016-04-07T22:22:59+00:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2016-04-07T22:22:59+00:00] ERROR: No resource or method named `ros' for `Chef::Recipe "/root/cookbooks/myapp/recipes/default.rb"'
[2016-04-07T22:23:01+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
The command '/bin/sh -c echo "cookbook_path = \"/root/cookbooks\"" > myapp/recipes/client.rb && chef-client --local-mode -c myapp/recipes/client.rb myapp/recipes/default.rb' returned a non-zero code: 1
@rhass
Copy link

rhass commented Apr 10, 2016

So there are a couple issues I found with the docker example.

  1. The echo statement in the Docker file contains \n, however the resulting file is contains the literal string \n as the echo command needs to be echo -e to tell it to interpret the \n characters as a new line ending.
    Current Output:
$ echo "source \"https://supermarket.chef.io\"\n metadata\n cookbook \"ros\""  
source "https://supermarket.chef.io"\n metadata\n cookbook "ros"

Corrected Output:

$ echo -e "source \"https://supermarket.chef.io\"\nmetadata\ncookbook \"ros\"" 
source "https://supermarket.chef.io"
metadata
cookbook "ros"
  1. The metadata file you are generating does not contain any dependencies. This is an issue because The Berksfile is akin to a Gemfile in Ruby, or a requirements.txt in python. It helps resolve and obtain the dependencies, but it the file and contents themselves do not actually instantiate any objects which utilize the dependencies. In order to tell chef to load the dependencies a compile the resources provided by them, you need to add a line to the metadata.rb such as depends 'ros'.

Example metadata.rb

name             'myapp'
maintainer       'YOUR_NAME'
maintainer_email 'YOUR_EMAIL'
license          'All rights reserved'
description      'Installs/Configures myapp'
long_description 'Installs/Configures myapp'
version          '0.1.0'

depends 'ros'

All this said, I still didn't get it working through docker in this particular way as it is and overly complex means to deploy the cookbook. I think an easier approach is to build the tarball outside the container as it will contain the cookbook and all the dependencies and do an ADD of the tarball. An even better approach you may want to try instead is to use test-kitchen and the kitchen-docker driver to quickly iterate on your cookbook as it will greatly simplify your workflow.

There is a caveat to using docker in all these situations which is Docker containers are not well suited to running init services -- as you get further into the project you will find this specific issue to be very irritating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment