Class: PoolParty::Chef

Inherits:
Base show all
Defined in:
lib/poolparty/chef.rb

Direct Known Subclasses

ChefClient, ChefSolo

Constant Summary

BOOTSTRAP_PACKAGES =
%w( ruby ruby1.8-dev libopenssl-ruby1.8 rdoc
ri irb build-essential wget ssl-cert rubygems git-core rake
librspec-ruby libxml-ruby zlib1g-dev libxml2-dev )
BOOTSTRAP_GEMS =

thin couchdb

%w( chef )
BOOTSTRAP_BINS =

we dont specifically install these binaries, they installed by packages and gems above, but we check for them

%w( gem chef-solo chef-client )
BOOTSTRAP_DIRS =
%w( /var/log/chef /var/cache/chef /var/run/chef )

Instance Attribute Summary

Attributes inherited from Base

#name

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods inherited from Base

#after_initialized, #initialize, #run

Constructor Details

This class inherits a constructor from PoolParty::Base

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(m, *args, &block) (private)



207
208
209
210
211
212
213
# File 'lib/poolparty/chef.rb', line 207

def method_missing(m,*args,&block)
  if cloud.respond_to?(m)
    cloud.send(m,*args,&block)
  else
    super
  end
end

Class Method Details

+ (Object) get_chef(type, cloud, &block)



23
24
25
# File 'lib/poolparty/chef.rb', line 23

def self.get_chef(type,cloud,&block)
  ("Chef" + type.to_s.capitalize).constantize(PoolParty).send(:new,type,:cloud => cloud,&block)
end

+ (Object) types



19
20
21
# File 'lib/poolparty/chef.rb', line 19

def self.types
  return [:solo,:client]
end

Instance Method Details

- (Object) _recipes(action = nil)



181
182
183
184
185
186
# File 'lib/poolparty/chef.rb', line 181

def _recipes action = nil
  action = action.to_sym unless action.nil?
  @_recipes ||= {:default => [] }
  key = action || _current_action
  @_recipes[key] ||= []
end

- (Object) attributes(hsh = {}, &block)

Chef



28
29
30
# File 'lib/poolparty/chef.rb', line 28

def attributes(hsh={}, &block)
  @attributes ||= ChefAttribute.new(hsh, &block)
end

- (Object) compile!



15
16
17
# File 'lib/poolparty/chef.rb', line 15

def compile!
  build_tmp_dir
end

- (Object) node_bootstrap!(remote_instance, force = false)



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/poolparty/chef.rb', line 157

def node_bootstrap!(remote_instance, force=false)
return if !force && node_bootstrapped?(remote_instance)

# TODO: this should not be hardcoded (like in node_run)
deb_gem_bin='/var/lib/gems/1.8/bin'
gem_src='http://gems.opscode.com'

bootstrap_cmds =
  [
   'apt-get update',
   'apt-get autoremove -y',
   'apt-get install -y %s' % BOOTSTRAP_PACKAGES.join(' '),
   "gem source -l | grep -q #{gem_src} || gem source -a #{gem_src} ",
   'gem install %s --no-rdoc --no-ri' % 
      (BOOTSTRAP_GEMS + remote_instance.bootstrap_gems).join(' '),
   "apt-get install -y %s" % BOOTSTRAP_PACKAGES.join(' '),
   "[ -d #{deb_gem_bin} ] && ln -sf #{deb_gem_bin}/* /usr/local/bin",
   "mkdir -p %s" % BOOTSTRAP_DIRS.join(' ')
  ]

remote_instance.ssh(bootstrap_cmds)
end

- (Boolean) node_bootstrapped?(remote_instance, quiet = true)



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/poolparty/chef.rb', line 137

def node_bootstrapped?(remote_instance, quiet=true)
  # using which command instead of calling gem directly.  On
  # ubuntu, calling a command from package not installed
  # 'helpfully' prints message, which result confuses detection
  #
  cmd = "which %s" % BOOTSTRAP_BINS.join(' ') +
    " && dpkg -l %s " % BOOTSTRAP_PACKAGES.join(' ') +
    BOOTSTRAP_GEMS.map{ |gem|
      "&& gem search '^#{gem}$' | grep -v GEMS | wc -l | grep -q 1"
    }.join(' ') +
    BOOTSTRAP_DIRS.map{ |dir|
      "&& [[ -d #{dir} ]] "
    }.join(' ') +
    (quiet ? " >/dev/null " : "" ) +
    " && echo OK || echo MISSING"

  r = remote_instance.ssh(cmd, :do_sudo => false )
  r.split("\n").to_a.last.chomp == "OK"
end

- (Object) node_configure!(remote_instance)



133
134
135
# File 'lib/poolparty/chef.rb', line 133

def node_configure!(remote_instance)
  # nothing in the superclass
end

- (Object) node_run!(remote_instance)



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/poolparty/chef.rb', line 116

def node_run!(remote_instance)
  node_stop!(remote_instance)
  node_configure!(remote_instance)

  envhash = {
    :GEM_BIN => %q%$(gem env | grep "EXECUTABLE DIRECTORY" | awk "{print \\$4}")%
  }
  cmds = chef_cmd
  cmds = [cmds] unless cmds.respond_to? :each

  remote_instance.ssh(cmds.map{|c| c.strip.squeeze(' ')}, :env => envhash )
end

- (Object) node_stop!(remote_instance)



129
130
131
# File 'lib/poolparty/chef.rb', line 129

def node_stop!(remote_instance)
  remote_instance.ssh("killall -q chef-client chef-solo; [ -f /etc/init.d/chef-client ] && invoke-rc.d chef-client stop")
end

- (Object) on_step(action, &block)

Description

Provides the ability to specify steps that can be run via chef

pool "mycluster" do

cloud "mycloud" do

    on_step :download_install do
        recipe "myrecipes::download"
        recipe "myrecipes::install"
    end

    on_step :run => :download_install do
        recipe "myrecipes::run"
    end
end

end

Then from the command line you can do

cloud-configure --step=download_install

to only do the partial job or

cloud-configure --step=run

to do everything



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/poolparty/chef.rb', line 66

def on_step action, &block
  if action.is_a? Hash
    t = action
    action = t.keys[0]
    depends = t.values[0]
  else
    depends = nil
  end
  change_attr :@_current_action, action do
    yield
    if depends
      # Merge the recipes of the dependency into
      # the current recipes
      _recipes(depends).each do |r|
        recipe r
      end
    end
  end
end

- (Object) override_attributes(hsh = {}, &block)



32
33
34
# File 'lib/poolparty/chef.rb', line 32

def override_attributes(hsh={}, &block)
  @override_attributes ||= ChefAttribute.new(hsh, &block)
end

- (Object) recipe(recipe_name, hsh = {})

Adds a chef recipe to the cloud

The hsh parameter is inserted into the override_attributes. The insertion is performed as follows. If the recipe name = "foo::bar" then effectively the call is

override_attributes.merge! { :foo => { :bar => hsh } }



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/poolparty/chef.rb', line 93

def recipe(recipe_name, hsh={})
  _recipes << recipe_name unless _recipes.include?(recipe_name)

  head = {}
  tail = head
  recipe_name.split("::").each do |key|
    unless key == "default"
      n = {}
      tail[key] = n
      tail = n
    end
  end
  tail.replace hsh

  override_attributes.merge!(head) unless hsh.empty?
end

- (Object) recipes(*recipes)



110
111
112
113
114
# File 'lib/poolparty/chef.rb', line 110

def recipes(*recipes)
  recipes.each do |r|
    recipe(r)
  end
end