Automate All the Things!

Doug Ireton's blog about Chef, Git, Ruby, Vim, and Infrastructure Automation

Lay Out Your .vimrc Like a Boss

| Comments

I’ve been using Vim for a few years now starting with the excellent Janus distribution of Vim settings and plugins. As excellent as Janus is though, I really wanted to know each and every setting and plugin for myself. I didn’t want any settings I didn’t understand.

About eight months ago I decided to get serious. I stripped down my .vimrc to about 20 settings I understood and could start using. I put my .vimrc and plugins in a Git repo. I slowly added settings one by one as I learned more about Vim.

If you want to take a similar path, what follows is my recommended way of organizing your .vimrc to keep things organized.

Knife Tricks

| Comments

Ohai Chefs!

At work, we have yet to use search extensively in our Chef Recipes, but we do a fair number of ad hoc knife searches. The following are some knife tricks and tips we’ve picked up over the last few months. Most of the credit for these goes to my esteemed co-worker, the Impossibly Hip™ .

Find all nodes in an environment

1
$ knife search node chef_environment:<environment name>

Find all nodes which contain a role

1
2
3
$ knife search node role(s):<role name>

$ knife search node "role:web_server" -a hostname

Use ‘roles’ plural when looking in the expanded run list.

Make Vim’s Goto File Command Open Included Chef Recipes

| Comments

Ohai Chefs!

Last week, we looked at how to get Chef clients grouped by version. This week, we’ll look at something completely different – customizing Vim to jump to included Chef recipes via the Goto File commandgf.

TL;DR

Add this to your .vimrc to be able to jump to included recipes (via include_recipe). Caveat: you can only jump to fully-qualified recipe names, e.g. my_cookbook::my_recipe. Hitting gf on include_recipe 'my_cookbook', won’t jump to my_cookbook::default.

.vimrc autocmd for include_recipe
1
2
3
" Make gf work on Chef include_recipe lines
" Add all cookbooks/*/recipe dirs to Vim's path variable
autocmd BufRead,BufNewFile */cookbooks/*/recipes/*.rb setlocal path+=recipes;/cookbooks/**1

Read on to find out why this works.

Get Chef Clients by Version

| Comments

Ohai Chefs!

At work, we’re being converted to the gospel of Etsy’s Church of Graphs. We’re sending Chef run times and other metrics to a combination of StatsD, Graphite, and . Last week, I wanted to add a graph of chef clients by version. In other words, I wanted to see how many Chef 0.10.8, and 10.12 clients we have left to upgrade.

This week, we’ll see how to get Chef client versions from the Chef Server, including one way which turned out to be more than 30 times faster in my tests.

Creating an LWRP - Part 3

| Comments

Ohai Chefs!

Last week, we started looking at how to create the Provider part of the LWRP, the code which creates, deletes, or changes the Resource on the managed node. We looked at implementing Action methods (:create, :delete), using the load_current_resource method to read in attributes of existing resources, and how to support Chef’s why-run mode.

This week, we’ll complete the Provider by looking at the port_exists?, create_printer_port, and delete_printer_port methods. The load_current_resource method uses the port_exists? method to determine if the printer port already exists. The latter two methods leverage Windows PowerShell to create and delete printer ports respectively. Collectively, these are the private methods in this class, meant to be called only by the :create and :delete Action methods and load_current_resource.

Creating an LWRP, Part 2: The Provider

| Comments

Ohai Chefs!

Last week, we looked at part one of creating an LWRP – the Resource. This week, we’ll look at part two – the Provider. We’ll look at a real Provider which uses Ruby and PowerShell to create and delete printer ports. Since the Provider code is so long, I’ll cover the first half this week, and the second half next week. The first half will cover the :create and :delete Action methods, how to support why_run (dry-run or what-if mode) and how to use the load_current_resource method.

Creating an LWRP, Part 1: The Resource

| Comments

Ohai Chefs!

If you’ve written any Chef recipes at all, you’ve almost certainly used Lightweight Resources and Providers (LWRPs). LWRPs enable you start/stop services, install packages, manage firewalls, deploy apps and many other common configuration tasks. LWRPs combine a simple interface (Resource) with one or more usually OS-specific implementations (Providers). For example this resource installs Windows packages:

Windows Package Resource
1
2
3
4
windows_package "7-Zip 9.20 (x64 edition)" do
  source "http://downloads.sourceforge.net/sevenzip/7z920-x64.msi"
  action :install
end

The windows_package provider, which comes with the Windows cookbook, is 250 lines of code. It handles five different kinds of package types, e.g. msi, inno, nullsoft, etc. LWRPs make it very easy for sysadmins to write Chef recipes with a minimal amount of code because someone has already done the hard work of writing the Resource and Provider.

Even though Opscode has provided many LWRPs “out of the box”, you will still need to write your own at some point. This week we’ll look at how to write an LWRP starting with the Resource part. Next week, we’ll complete the two-part series by learning how to write the corresponding Provider.

Automatically Upgrading Chef Client on Vagrant Up

| Comments

Ohai Chefs!

If you do enough Vagrant testing, you’ll soon run into a Vagrant box with an outdated Chef client. Even the Opscode Test Kitchen boxes come with Chef 10.14.4, not the latest 10.16.2 version. In this post I’ll show you how to automatically upgrade the Chef client on vagrant up. The trick is to use two config.vm.provision blocks in your Vagrantfile.

How to Include the Windows Cookbook Helper Methods in Your Chef Recipe

| Comments

Ohai Chefs!

We’ve been writing a lot of Windows Cookbooks and Recipes lately and it’s been very helpful to be able to use the helper methods in the Opscode Windows cookbook. In this post I’ll show you how to include and use those helper methods. You can generalize this to library methods from any cookbook, even your own cookbooks.

What are the helper methods?

The Windows cookbook includes several nice helper methods for dealing with windows paths and the registry. Unfortunately, it’s not obvious how to use these helper methods in a recipe. At first I tried the standard Ruby require statement in a recipe, but this doesn’t work. My Talented and Gifted ™ teammate Kevin was able to explain why to me, but now I can’t remember the reason.

How do I use them in a recipe?

Just use ::Chef::Recipe.send(:include, Windows::Helper) like this:

::Chef::Recipe.send(:include, Windows::Helper)
1
2
3
4
5
6
7
8
9
10
11
# include Windows::Helper from Opscode Windows Cookbook
::Chef::Recipe.send(:include, Windows::Helper)

# now you can call helper methods like win_friendly_path directly
my_batch_file = win_friendly_path(
                     ::File.join( node['cookbook']['batch_dir'],'foo.bat'))

execute "My batch file" do
  command my_batch_file
  creates "e:/logs/my_batch_file.log"
end