Jeff Roberts
RHCE #804006066322833
Vim-Fu is now iPhone and Android friendly

Check out the Vim-Fu Store!

Vim-Fu

Patching Chef to support dry-run mode by Darren Dao

Disclaimer: I am not an expert on Chef, nor on Ruby. This post simply shows what works for me. The code haven’t been tested thoroughly. It’s only there to serve as an example.

TL;DR: I ended up monkey-patching each of the Chef providers that we use (e.g. directory, file, template, etc). The method you want to patch is the “action_create” method. You can overwrite this method to output the result to stdout, to a staging area, etc.

Background: At our company, we decided to use Chef for app config management. We set up our Chef cookbooks and recipes in such a way that we can deploy them to different hosts, and depending on what environment the hosts are in (prod vs. qa vs. dev), different configuration files will be generated.

Problem: One of the requirements we were given is the ability to see what config files would be generated on a given Chef run. Another requirement is to be able to provide the diff of the generated config files between two environments. To satisfy those two requirements, we need to run Chef in a staging area, or in dryrun/noop mode. Chef supports neither one. A chef user has opened a ticket since Jan 2009, asking for this feature to be added to Chef (http://tickets.opscode.com/browse/CHEF-13) . However, it doesn’t look like there has been any progress on it. Searching on google for “Chef dryrun” or “Chef noop” only resulted in Puppet users bashing Chef for not having a dryrun/noop mode. Since it looks like Chef developers are not going to address this issue anytime soon, we decide to patch Chef ourselves.

Solution: The key to having Chef dryrun/noop mode is to patch each of the providers that you use in your cookbook. For more information on what a provider is, visit http://wiki.opscode.com/display/chef/Providers. In patching the providers, we overwrite the “action_create” method, so that instead of having the providers carrying out the actual actions, we tell them to either display what the actions are, or perform the actions in a staging area. For example, this is how we patch Chef to have to output the resulting resources to a staging directory (defined as a variable in node.json)

# Overwrite providers to output files to staging area
class Chef
  class Provider
    class Template < Chef::Provider::File
      def action_create
        render_with_context(template_location) do |rendered_template|
          dest = ::File.join(Chef::Config["stage_dir"], @current_resource.path)
          dir = ::File.dirname(dest)
          FileUtils.mkdir_p(dir) unless ::File.exists? dir
          FileUtils.cp(rendered_template.path, dest)
        end
      end
    end
    class Directory < Chef::Provider::File
      def action_create
        ::FileUtils.mkdir_p(::File.join(Chef::Config["stage_dir"], @new_resource.path))
      end
    end
    class File < Chef::Provider
      def action_create
        dest = ::File.join(Chef::Config["stage_dir"], @new_resource.path)
        ::File.open(dest, 'w'){|f| f.write(@new_resource.content)}
      end
    end
    class CookbookFile < Chef::Provider::File
      def action_create
        dest = ::File.join(Chef::Config["stage_dir"], @new_resource.path)
        FileUtils.cp(file_cache_location, dest)
      end
    end
  end
end

You can put that code inside your ruby script, and then have your ruby script load either chef-solo or chef-client, depending on what you use. For us, we use chef-solo, so I ended up created a ruby script called chef-solo.dryrun, inside it, I have the code above, and then I call chef-solo like this:

require 'rubygems'
require 'chef'
require 'fileutils'

# patch code from above goes in here

# Call chef-solo
version = ">= 0"
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end
gem 'chef', version
load Gem.bin_path('chef', 'chef-solo', version)

The downside to this solution is that it is fragile and will break if Chef developers decide to change the methods inside of the providers (e.g. the “action_create” method gets renamed). It is definitely not the best way to add dryrun/noop to Chef, but given the lack of response/progress from Chef developers on this issue, we are happy with this solution.

Resetting root password in MySQL

This is taken directly from MySQL home page:

  1. Log on to your system as the Unix user that the mysqld server runs as (for example, mysql).
  2. Locate the .pid file that contains the server’s process ID. The exact location and name of this file depend on your distribution, host name, and configuration. Common locations are /var/lib/mysql/, /var/run/mysqld/, and /usr/local/mysql/data/. Generally, the file name has an extension of .pid and begins with either mysqld or your system’s host name.You can stop the MySQL server by sending a normal kill (not kill -9) to the mysqld process, using the path name of the .pid file in the following command:
    shell> kill `cat /mysql-data-directory/host_name.pid`

    Use backticks (not forward quotation marks) with the cat command. These cause the output of cat to be substituted into the kill command.

  3. Create a text file containing the following statements. Replace the password with the password that you want to use.
    UPDATE mysql.user SET Password=PASSWORD('MyNewPass') WHERE User='root';
    FLUSH PRIVILEGES;

    Write the  UPDATE and FLUSH statements each on a single line. The UPDATE statement resets the password for all root accounts, and the FLUSH statement tells the server to reload the grant tables into memory so that it notices the password change.

  4. Save the file. For this example, the file will be named /home/me/mysql-init. The file contains the password, so it should not be saved where it can be read by other users.
  5. Start the MySQL server with the special –init-file option:
    shell> mysqld_safe --init-file=/home/me/mysql-init &

    The server executes the contents of the file named by the –init-file option at startup, changing each root account password.

  6. After the server has started successfully, delete /home/me/mysql-init.

OpenSSL-Fu

I needed to do a conversion of an ssl-cert today and I found a very thorough post all about OpenSSL and all of the really usefult things it can do.  I thought about writing my own post, but why re-invent the wheel.  Mr. Heinlen did an excellent job so I am just providing a link to his post:

http://www.madboa.com/geek/openssl/#cert-test

the ball command

Quite often I’ll open up several different file in the vim buffer to be edited.

~$ vim `grep -l v1.2r5 *.pl`

Commands like that can save you a lot of time searching through files looking for a single value or word.

How many files did that load into Vim’s buffer?  Check with:

:ls

Let’s say grep found three files and [...]

Starting Over in VIM using e!

I haven’t posted a trick in a while, so here’s a good one to know.

Ever start working on a file in command mode and then hit the caps key without realizing it.  Wham! All sorts of un-expected things can happen before you know it.  What do you do then? You could use q! to exit [...]

MySQL tuning script

This is really useful script called tuning-primer.sh by Matt Montgomery. [...]

Using Screen to connect to a serial console

Not much to write about here.  You can use screen as a replacement for minicom. Who knew!?!?!  Screen will never stop amazing me with all the cool stuff that it can do.

screen /dev/ttyUSB0

To set the baud rate to 57,600:

screen /dev/ttyUSB0 57600

To enable CTS/RTS handshake:

screen /dev/ttyUSB0 57600,ctsrts

^a,k to end the session.
^a,i to check the status of [...]

Blacklisted Email in Amazon's EC2 Cloud

One of the major problems in having your systems in Amazon’s EC2 cloud is that the ip you get assigned is almost surely blacklisted with every major email blacklist  before you’ve sent a single piece of email (check for this using mxtoolbox.com).  I learned this the hard way when I started hearing the our registration and [...]

Cisco POE and Polycom phones

They just continuously flapped when ever they were powered by the 3550. Adding this line fixed the issue [...]

Cisco's DNS Rewrite - My new best friend

DNS Rewriting is a simple and elegant solution that can save you time and [...]