Skip to end of metadata
Go to start of metadata

Shef: The Chef REPL

Shef is a way to run chef in an Interactive Ruby (IRb) session. Shef currently supports recipe and attribute file syntax, as well as interactive debugging features.

Run Modes

Shef has three run modes:

  • Standalone
    No cookbooks are loaded, and the run list is empty. This mode is the default.
  • Solo
    Shef acts as a chef-solo client. It attempts to load chef-solo's configuration file and JSON attributes. If the JSON attributes set a run list, it will be honored. Cookbooks will be loaded in the same way that chef-solo loads them. Solo mode is activated with the -s or --solo command line option, and JSON attributes are specified in the same way as for chef-solo, with -j /path/to/chef-solo.json.
  • Client
    Shef acts as a chef-client. During startup, it reads the chef client configuration file and contacts the server to get attributes and cookbooks. The run list will be set in the same way as normal chef client runs. Client mode is activated with the -z or --client options. You can also specify the configuration file with -c CONFIG and the server URL with -S SERVER_URL.

"Hello World" in Shef: A Simple Example

For this example, we'll use the standalone mode. (For solo or client modes, you would need to run shef using the -s or -z command line options as specified above, and take into consideration the configuration settings detailed below.)

If chef is installed from gems or your platform's package manager, shef should be in your path already. (If you are running chef from a git clone, shef is in chef/bin/shef.) To start just run shef with no options. You'll see the loading message, then the banner, and then the shef prompt:



Tutorials from the Community


  • Shef Tips and Tricks

Opscode team member Steven Danna has put together a blog post with a number of tricks and tools for productively debugging problems using Shef.

Debug Chef-client runs by stepping through a node’s run list, breaking before or after specific resources in order to inspect the state of the system.

  • Chef Development With Shef

How to use Shef, the interactive chef console, for iterative cookbook development for those times when you just want to experiment without uploading anything to the server. This is a useful workflow oriented blog post by Community Member Jon Cowie.

At any point, you may use the help command to print a list of supported commands.

Use the recipe command to switch to recipe context:

Now your typing will be evaluated the same context as recipes. We can create a file resource:

At this point, shef has created the resource and put it in the run list, but not yet created the file. To initiate the chef run, use the run_chef command:

Shef also lets you switch to the same context as attribute files. You can set an attribute with the familiar syntax:

Now you can switch back to recipe context and use the attribute you set:

Now, run chef again:

Note that the first resource we created, (file[/tmp/ohai2u_shef]) is still in the run list, and gets executed again. Of course, since that file already exists, chef doesn't attempt to create it.

Finally, we can see that the files were created using shef's ls method:

Shef Tutorial

You may want to review Getting Started With Shef for some additional high level examples on its use.

Client and Solo Modes

Shef provides client and solo modes which allow it to emulate running chef-client or chef-solo with additional debugging features. When running in client mode, shef will parse any provided JSON attributes file, then connect to the chef server and synchronize cookbooks. The node will have the same attributes and run list as it would during a chef client run. Solo mode is similar, except that attributes are loaded from a JSON file instead of a Chef server. Solo mode is activated with the -s or --solo command line option. Client mode is activated with the -z or --client options. Shef will load based upon its configuration settings.

Configuring Shef

Shef's configuration file support is new in Chef 0.9.8. (With older versions of chef, use the -c option to specify a configuration file.) Shef chooses the configuration file to load according to the following logic:

  1. If a config file is specified with the -c option, it is used.
  2. When shef is started with a named configuration as an argument, shef will search for a shef.rb file in that directory under ~/.chef. For example, if shef is started as shef production, chef will load a configuration file from ~/.chef/production/shef.rb
  3. If no named configuration is given, shef attempts to load shef.rb from your .chef directory, i.e., ~/.chef/shef.rb
  4. If no shef.rb is found, shef will try to load /etc/chef/client.rb when started in client mode (i.e., -z)
  5. If no shef.rb is found, shef will try to load /etc/chef/solo.rb when started in solo mode.

The shef configuration file

In your shef.rb you can configure shef just as you would configure the chef-client. To configure shef to properly authenticate with your Chef server, you might copy the node_name, client_key, and chef_server_url settings from your knife configuration:

Sample shef.rb

You can also disable ohai plugins to speed up shef's boot process or include any arbitrary ruby code in your shef configuration file.

Running Shef as a Client Using Your Knife Credentials

By default, shef loads in standalone mode that doesn't connect to a server. On your laptop/desktop, you might want to run shef in client mode in order to test a feature that's only available when using Chef in the client-server configuration (i.e., Search or Data Bags).

If you've already configured Knife on your box, you can borrow knife's credentials to connect to the server. In order for this to work, you need to create a node with the same name that your knife client uses to authenticate. This is the node_name configuration parameter in your knife.rb file (typically located at ~/.chef/knife.rb – you can find this with grep node_name ~/.chef/knife.rb. Then, run knife node create $YOUR_KNIFE_NODE_NAME to create a node with this name (the node attributes aren't important unless you need them for some other pupose).

Once you've done this, you can run shef in client mode, where it will connect to the server via the config value with 'chef_server_url'. By passing it your knife.rb, it will connect to the server via the config value.

No Longer Needed for Chef REST api interaction

As of chef 0.9.8, you no longer need to take this approach if you just want to be able to access the Chef REST api from within shef. Just configure your shef.rb similar to the example in the previous section.

Managing Chef Server with Shef

When properly configured to access your Chef Server, shef can list, show, search for, and edit cookbooks, clients, nodes, roles, and databags.

These commands all have a syntax of the form items.command so to list nodes, you use nodes.list:

The list command can take a code block, which is applied (but not saved) to each object returned from the server. You can list all of your nodes and their run lists:

To find a specific node, use nodes.show:

You can also use search from within shef. To search for nodes, use nodes.find:

Again, you can give a code block to "format" the results:

Debugging Recipes with Shef

Shef gives you the ability to manipulate your current position in the run list during a chef run. To use this feature, you'll need at least one breakpoint in one recipe in the client's run list.

The Breakpoint Resource

Breakpoints are implemented as a chef resource. The breakpoint resource has no custom attributes. Its default action is break. When the break action is called on the breakpoint provider, the provider tests if it is running under shef, or a normal chef-client (or solo) run. If it's running under chef-client or chef-solo, no action is taken; if it's running under shef, the chef run will be paused.

Stepping Through the Run List

To explore how breakpointing and manually controlling chef execution works, create a simple recipe in shef:

Now, run chef:

We can see that chef ran the first resource before the breakpoint, file[/tmp/before-breakpoint], but it stopped after executing the breakpoint. We also see that chef attempted to name the breakpoint resource after its position in the source file, but we confused it by entering the resource interactively.

From here, we can tell shef to finish the chef run using chef_run.resume

If we list our /tmp directory, we see that both files were created:

We can also rewind the chef run and step through it:

From the output, we see that we rewound the run list, but when we executed the resources again, they repeated their checks for the existence of the files and found that they now exist, so chef skipped creating them. If we delete the files:

Then we can rewind and resume the chef run and get the expected results:

Debugging existing recipes

You may also find it helpful to use Shef to debug existing recipes. First you will need to add the recipe to the run_list for the node so it is cached when starting shef. Once this is done, you can use the recipes for debugging. You can see which recipes it cached when starting, as it will output these when loading shef:

If you just want to just load one recipe from the run_list, you can do this by going into recipe mode and using the "include_recipe" command:

If you wanted to load all of the recipes from the run_list, you could do this in recipe mode by using this code:

Once the recipes you want to debug have been loaded, you can use the run_chef command to run them.

Turn Debugging up to 11

In shef, it's possible get get extremely verbose debugging using irb's tracing feature. Shef provides a shortcut to turn tracing on and off, using tracing on and tracing off.

For example, here's the output from turning tracing on and off:

Shef Help

You can see the help in Shef by using the command "help". There is different help information posted if you are in recipe or attributes mode.

Use Case Scenario

To get a list of nodes with recipe postfix I'm using search(:node,"recipe:postfix"), but in this case I actually only want nodes with the postfix sub-recipe "delivery" (postfix::delivery). How do I express that correctly in the search syntax? (just putting in "postfix::delivery" returns an error)

One approach would be to use shef:

Single vs. double quotes is significant here since you want to include a backslash in the string instead of having ruby interpret it as an escape.






Labels
  • None
  1. Jan 14, 2010

    Could someone throw in some example usages? Just so one can get oriented enough to start exploring shef?
    For instance how and where do you run this? Can you run it in a dev environment (ie not a target chef client, but where you develop your chef cookbooks) and supply a run_list or other way to create an environment that the shef instance runs in?

    Or do you only run this on a node and it takes in the node's environment?

    Can you load up some roles and reciepes and then explore them? If so how?

    Some basic idea of why and when and what to do once you enter attributes mode or recipe mode?

    How do you set a "Current Recipe"?

    It looks like this tool would help a lot to interactively answer questions that come up when developing recipes, So any effort to show how to use Shef would be a big lever in helping people use Chef in general.

    1. Jan 16, 2010

      Thanks Daniel that is a great first step.

      Is there a way to load roles, cookbooks, attribute files and/or recipes in standalone mode?

      Would you only use client mode on a client node? (I'm trying to understand how you would use shef while developing cookbooks like one would us irb while developing ruby code as apposed to debugging a client node).

      1. Jan 16, 2010

        Hi Robert,

        There's currently no easy way to load cookbooks or roles or anything in standalone mode. That's probably a good feature to add, so feel free to create a ticket for that.

        For client mode, it needs to run on a client with valid authentication credentials. This could be your laptop, a VM setup for this purpose, or any client node you feel comfortable developing recipes on. There are some irb plugins that launch your $EDITOR and can ferry code back and forth from irb to the editor. These /should/ work with shef, though I have not yet tried them with it.

        We're still learning how people want to use shef, so any feedback you have to offer about how you're using it or would like to use it is appreciated.

        HTH, let me know if you have any more questions.

        1. Jan 25, 2010

          Any way to use the search interface while in Shef? It would be really nice to be able to try out different search queries while in the context of attributes or recipes.

          1. Feb 10, 2010

            Hi Robert,
            I haven't tried that yet, but it should work in client mode. Have you tried it and it didn't work? Of course, feel free to bug us on IRC about it if you can't get it working.

            UPDATE: I've done this now and it works fine (in client mode, of course). Using data bags also works.