Chef windows_task and Idempotency

I’m writing chef cookbooks for a customer targeting the windows platform. The first out of the gate cookbook is a simple base one to make sure the system is prepped for all that comes after it. The customer already has the windows host bootstrapped.

So first item is to set up the windows scheduled task that calls chef-client on interval. There’s already a windows_task in the opscode windows cookbook. So, that’s all well and good until I started thinking ahead a bit to idempotency for the base recipe. I had three possible tasks for the chef-client scheduled task: create, modify, delete. The modify would just be changing the run interval. The delete would be… yeah, I don’t know why we’d want to leave the chef-zone in a managed environment. So that leaves us with two actions.

Digging through the opscode windows cookbook directory, we get to windows/providers/task.rb and we see the actions :create, :run, :delete, and :change.

We look at :create and do a little dance because we see that it’s inherently idempotent — if a task with the same name exists, it does nothing.

if @current_resource.exists
Chef::Log.info "#{@new_resource} task already exists - nothing to do"

Yay! Kind of. What we don’t get there is the solution to the scenario “okay, I’m running my millionth run, and oh, YOU’VE changed the node attribute for the periodicity of the task, so I need to just change that… unless you don’t have the task installed…”. There are a number of ways to work through this. First, I looked at the :change action in the windows cookbook. The code read that if the task exists, it makes the change, if not, it exits. Part of me here thought “well, it’d be really swell if it CREATED the task at this point rather than just calling it a day.” What is the case FOR ME that I’d be invoking this on a node and NOT wanting the task created? I can’t come up with a plausible one, but I’m sure I could throw out a few absurd ones if I thought about it a bit more. So what if we made such a change to :change? Simply make the code read that if exists, update else create? Sure, easy enough, but is it the right thing to do for this? Or should this be OUTSIDE in a particular recipe?

If we put the decision of task exists/change in the surrounding cookbook, we could create a node attribute that represented that interval. The benefit is that the nodes could be searched on this interval. Not all that compelling. Other upside — I won’t be dicking around with the windows cookbook internals. So, I believe I’ll go that route. Opscode document reference to similar first run scenarios here

How else could we do this?

Leave a Reply

Your email address will not be published. Required fields are marked *