Created
June 18, 2013 22:40
-
-
Save ssimeonov/5810145 to your computer and use it in GitHub Desktop.
Chef LWRP subclassing example: rake resource subclasses rvm_shell.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Chef | |
class ResourceFactory | |
class Rake | |
def self.create(*args, &block) | |
register | |
Chef::Resource::Rake.new(*args, &block) | |
end | |
def self.register | |
@klass ||= begin | |
Chef::Resource.const_set('Rake', Class.new(Chef::Resource::RvmShell) do | |
identity_attr :task | |
def self.resource_name | |
'rake' | |
end | |
def self.default_action | |
:run | |
end | |
def initialize(name, run_context=nil) | |
super | |
@provider = Chef::Provider::RvmShell | |
@allowed_actions = [:nothing, :run] | |
@task = name | |
@arguments = [] | |
@bundler = true | |
@trace = true | |
@runner = nil | |
end | |
def task(arg=nil) | |
set_or_return(:task, arg, :kind_of => [String]) | |
end | |
def arguments(*args) | |
set_or_return(:arguments, args.empty? ? nil : args, :kind_of => [Array]).tap do |result| | |
if (index = result.find_index(nil)) | |
raise "argument ##{index} cannot be nil. (Arguments: #{result.inspect})" | |
end | |
end | |
end | |
def bundler(arg=nil) | |
set_or_return(:bundler, arg, :kind_of => [TrueClass, FalseClass]) | |
end | |
def trace(arg=nil) | |
set_or_return(:trace, arg, :kind_of => [TrueClass, FalseClass]) | |
end | |
def runner(arg=nil) | |
set_or_return(:runner, arg, :kind_of => [String, Symbol, NilClass]) | |
end | |
def code(arg=nil) | |
raise 'code attribute of rake resource is read-only' if arg | |
code_to_run = [ | |
runner ? "#{runner} run" : nil, | |
bundler ? 'bundle exec' : nil, | |
arguments.empty? ? | |
"rake #{task}" : | |
"rake #{task}[#{arguments.join(',').shellescape}]", | |
trace ? '--trace' : nil | |
].compact.join(' ') | |
super code_to_run | |
end | |
end) | |
end | |
end | |
end | |
end | |
end | |
def rake(*args, &block) | |
Chef::ResourceFactory::Rake.register | |
method_missing(:rake, *args, &block) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if defined? ChefSpec | |
module ChefSpec | |
module Matchers | |
RSpec::Matchers.define :execute_rake do |code| | |
match do |chef_run| | |
chef_run.resources.any? do |resource| | |
resource_type(resource).to_s == 'rake' and code === resource.code | |
end | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Cookbook Name:: rake-chef | |
# Recipe:: spec | |
# | |
# Copyright (C) 2013 YOUR_NAME | |
# | |
# All rights reserved - Do Not Redistribute | |
# | |
rake 'db:seed' do | |
runner :foreman | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'spec_helper' | |
describe 'rake-chef::spec' do | |
let (:chef_run) { ChefSpec::ChefRunner.new.converge 'rake-chef::spec' } | |
specify { expect(chef_run).to execute_rake 'foreman run bundle exec rake db:seed --trace' } | |
describe 'rake resource' do | |
subject { Chef::ResourceFactory::Rake.create('my:task') } | |
it { should be_kind_of Chef::Resource::LWRPBase } | |
its(:task) { should == 'my:task' } | |
its(:arguments) { should == [] } | |
its(:bundler) { should be_true } | |
its(:trace) { should be_true } | |
its(:runner) { should be_nil } | |
its(:code) { should == 'bundle exec rake my:task --trace'} | |
it 'does not allow nil arguments' do | |
expect { subject.arguments 1, nil, 'hi' }.to raise_error /cannot be nil/ | |
end | |
it 'does not allow setting the command attribute' do | |
expect { subject.code 'rake -T' }.to raise_error /read-only/ | |
end | |
context 'with arguments 1 & "hello" and no bundler' do | |
before do | |
subject.arguments 1, 'hello there' | |
subject.bundler false | |
end | |
its(:arguments) { should == [1, 'hello there'] } | |
its(:bundler) { should be_false } | |
its(:code) { should == 'rake my:task[1,hello\ there] --trace'} | |
end | |
context 'with foreman runner and no trace' do | |
before do | |
subject.runner :foreman | |
subject.trace false | |
end | |
its(:runner) { should == :foreman } | |
its(:code) { should == 'foreman run bundle exec rake my:task'} | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment