Class: Chef::Client
- Includes:
- Mixin::Checksum, Mixin::GenerateURL
- Defined in:
- lib/chef/client.rb
Instance Attribute Summary collapse
-
#json_attribs ⇒ Object
Returns the value of attribute json_attribs.
-
#node ⇒ Object
Returns the value of attribute node.
-
#node_name ⇒ Object
Returns the value of attribute node_name.
-
#ohai ⇒ Object
Returns the value of attribute ohai.
-
#registration ⇒ Object
Returns the value of attribute registration.
-
#rest ⇒ Object
Returns the value of attribute rest.
Instance Method Summary collapse
-
#build_node(node_name = nil, solo = false) ⇒ Object
Builds a new node object for this client.
-
#converge(solo = false) ⇒ Object
Compiles the full list of recipes for the server, and passes it to an instance of Chef::Runner.converge.
- #determine_node_name ⇒ Object
-
#initialize ⇒ Client
constructor
Creates a new Chef::Client.
-
#register ⇒ Object
Returns rest<Chef::REST>:: returns Chef::REST connection object.
-
#run ⇒ Object
Do a full run for this Chef::Client.
- #run_ohai ⇒ Object
-
#run_solo ⇒ Object
Similar to Chef::Client#run, but instead of talking to the Chef server, simply runs in a standalone (“solo”) mode.
-
#save_node ⇒ Object
Updates the current node configuration on the server.
-
#sync_cookbooks ⇒ Object
Synchronizes all the cookbooks from the chef-server.
-
#update_file_cache(cookbook_name, parts) ⇒ Object
Update the file caches for a given cache segment.
Methods included from Mixin::Checksum
Methods included from Mixin::GenerateURL
#generate_cookbook_url, #generate_cookbook_url_from_uri
Constructor Details
#initialize ⇒ Client
Creates a new Chef::Client.
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/chef/client.rb', line 43 def initialize() @node = nil @registration = nil @json_attribs = nil @node_name = nil @node_exists = true @ohai = Ohai::System.new Chef::Log.verbose = Chef::Config[:verbose_logging] Mixlib::Authentication::Log.logger = Ohai::Log.logger = Chef::Log.logger @ohai_has_run = false @rest = if File.exists?(Chef::Config[:client_key]) Chef::REST.new(Chef::Config[:chef_server_url]) else Chef::REST.new(Chef::Config[:chef_server_url], nil, nil) end end |
Instance Attribute Details
#json_attribs ⇒ Object
Returns the value of attribute json_attribs.
40 41 42 |
# File 'lib/chef/client.rb', line 40 def json_attribs @json_attribs end |
#node ⇒ Object
Returns the value of attribute node.
40 41 42 |
# File 'lib/chef/client.rb', line 40 def node @node end |
#node_name ⇒ Object
Returns the value of attribute node_name.
40 41 42 |
# File 'lib/chef/client.rb', line 40 def node_name @node_name end |
#ohai ⇒ Object
Returns the value of attribute ohai.
40 41 42 |
# File 'lib/chef/client.rb', line 40 def ohai @ohai end |
#registration ⇒ Object
Returns the value of attribute registration.
40 41 42 |
# File 'lib/chef/client.rb', line 40 def registration @registration end |
#rest ⇒ Object
Returns the value of attribute rest.
40 41 42 |
# File 'lib/chef/client.rb', line 40 def rest @rest end |
Instance Method Details
#build_node(node_name = nil, solo = false) ⇒ Object
Builds a new node object for this client. Starts with querying for the FQDN of the current host (unless it is supplied), then merges in the facts from Ohai.
Parameters
- node_name<String>
-
The name of the node to build - defaults to nil
Returns
- node<Chef::Node>
-
Returns the created node object, also stored in @node
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/chef/client.rb', line 144 def build_node(node_name=nil, solo=false) node_name ||= determine_node_name raise RuntimeError, "Unable to determine node name from ohai" unless node_name Chef::Log.debug("Building node object for #{@node_name}") unless solo @node = begin rest.get_rest("nodes/#{@node_name}") rescue Net::HTTPServerException => e raise unless e. =~ /^404/ end end unless @node @node_exists = false @node ||= Chef::Node.new @node.name(node_name) end @node.consume_attributes(@json_attribs) ohai.each do |field, value| Chef::Log.debug("Ohai Attribute: #{field} - #{value.inspect}") @node[field] = value end platform, version = Chef::Platform.find_platform_and_version(@node) Chef::Log.debug("Platform is #{platform} version #{version}") @node[:platform] = platform @node[:platform_version] = version @node end |
#converge(solo = false) ⇒ Object
Compiles the full list of recipes for the server, and passes it to an instance of Chef::Runner.converge.
Returns
- true
-
Always returns true
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/chef/client.rb', line 309 def converge(solo=false) Chef::Log.debug("Compiling recipes for node #{@node_name}") unless solo Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks") Chef::Log.warn("Node #{@node_name} has an empty run list.") if @node.run_list.empty? else # Check for cookbooks in the path given # Chef::Config[:cookbook_path] can be a string or an array # if it's an array, go through it and check each one, raise error at the last one if no files are found Chef::Log.debug "loading from cookbook_path: #{Array(Chef::Config[:cookbook_path]).map { |path| File.(path) }.join(', ')}" Array(Chef::Config[:cookbook_path]).each_with_index do |cookbook_path, index| if directory_not_empty?(cookbook_path) break else msg = "No cookbook found in #{Chef::Config[:cookbook_path].inspect}, make sure cookboook_path is set correctly." Chef::Log.fatal(msg) raise Chef::Exceptions::CookbookNotFound, msg if is_last_element?(index, Chef::Config[:cookbook_path]) end end end compile = Chef::Compile.new(@node) Chef::Log.debug("Converging node #{@node_name}") Chef::Runner.new(@node, compile.collection, compile.definitions, compile.cookbook_loader).converge true end |
#determine_node_name ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/chef/client.rb', line 123 def determine_node_name run_ohai unless node_name if Chef::Config[:node_name] @node_name = Chef::Config[:node_name] else @node_name ||= ohai[:fqdn] ? ohai[:fqdn] : ohai[:hostname] Chef::Config[:node_name] = @node_name end end @node_name end |
#register ⇒ Object
Returns
- rest<Chef::REST>
-
returns Chef::REST connection object
179 180 181 182 183 184 185 186 187 188 |
# File 'lib/chef/client.rb', line 179 def register if File.exists?(Chef::Config[:client_key]) Chef::Log.debug("Client key #{Chef::Config[:client_key]} is present - skipping registration") else Chef::Log.info("Client key #{Chef::Config[:client_key]} is not present - registering") Chef::REST.new(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]).register(@node_name, Chef::Config[:client_key]) end # We now have the client key, and should use it from now on. self.rest = Chef::REST.new(Chef::Config[:chef_server_url]) end |
#run ⇒ Object
Do a full run for this Chef::Client. Calls:
* build_node - Get the last known state, merge with local changes
* register - Make sure we have an openid
* authenticate - Authenticate with our openid
* sync_library_files - Populate the local cache with all the library files
* sync_provider_files - Populate the local cache with all the provider files
* sync_resource_files - Populate the local cache with all the resource files
* sync_attribute_files - Populate the local cache with all the attribute files
* sync_definitions - Populate the local cache with all the definitions
* sync_recipes - Populate the local cache with all the recipes
* do_attribute_files - Populate the local cache with all attributes, and execute them
* save_node - Store the new node configuration
* converge - Bring this system up to date, based on the local cache
* save_node - Store the node again, in case convergence altered future state
Returns
- true
-
Always returns true.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/chef/client.rb', line 78 def run start_time = Time.now Chef::Log.info("Starting Chef Run") determine_node_name register build_node(@node_name) save_node sync_cookbooks converge save_node end_time = Time.now Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds") true end |
#run_ohai ⇒ Object
115 116 117 118 119 120 121 |
# File 'lib/chef/client.rb', line 115 def run_ohai if ohai.keys ohai.refresh_plugins else ohai.all_plugins end end |
#run_solo ⇒ Object
Similar to Chef::Client#run, but instead of talking to the Chef server, simply runs in a standalone (“solo”) mode.
Someday, we’ll have chef_chewbacca.
Returns
- true
-
Always returns true.
102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/chef/client.rb', line 102 def run_solo start_time = Time.now Chef::Log.info("Starting Chef Solo Run") determine_node_name build_node(@node_name, true) converge(true) end_time = Time.now Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds") true end |
#save_node ⇒ Object
Updates the current node configuration on the server.
Returns
- true
-
Always returns true
289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/chef/client.rb', line 289 def save_node Chef::Log.debug("Saving the current state of node #{@node_name}") @node = begin if @node_exists rest.put_rest("nodes/#{@node_name}", @node) else result = rest.post_rest("nodes", @node) @node_exists = true rest.get_rest(result['uri']) end rescue nil end end |
#sync_cookbooks ⇒ Object
Synchronizes all the cookbooks from the chef-server.
Returns
- true
-
Always returns true
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/chef/client.rb', line 268 def sync_cookbooks Chef::Log.debug("Synchronizing cookbooks") cookbook_hash = rest.get_rest("nodes/#{@node_name}/cookbooks") Chef::Log.debug("Cookbooks to load: #{cookbook_hash.inspect}") Chef::FileCache.list.each do |cache_file| if cache_file =~ /^cookbooks\/(.+?)\// unless cookbook_hash.has_key?($1) Chef::Log.info("Removing #{cache_file} from the cache; its cookbook is no longer needed on this client.") Chef::FileCache.delete(cache_file) end end end cookbook_hash.each do |cookbook_name, parts| update_file_cache(cookbook_name, parts) end end |
#update_file_cache(cookbook_name, parts) ⇒ Object
Update the file caches for a given cache segment. Takes a segment name and a hash that matches one of the cookbooks/_attribute_files style remote file listings.
Parameters
- segment<String>
-
The cache segment to update
- remote_list<Hash>
-
A cookbooks/_attribute_files style remote file listing
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/chef/client.rb', line 197 def update_file_cache(cookbook_name, parts) Chef::Log.debug("Synchronizing cookbook #{cookbook_name}") file_canonical = Hash.new [ "recipes", "attributes", "definitions", "libraries", "resources", "providers" ].each do |segment| remote_list = parts.has_key?(segment) ? parts[segment] : [] # segement = cookbook segment # remote_list = list of file hashes # # We need the list of known good attribute files, so we can delete any that are # just laying about. remote_list.each do |rf| cache_file = File.join("cookbooks", cookbook_name, segment, rf['name']) file_canonical[cache_file] = true # For back-compat between older clients and new chef servers rf['checksum'] ||= nil current_checksum = nil if Chef::FileCache.has_key?(cache_file) current_checksum = checksum(Chef::FileCache.load(cache_file, false)) end if current_checksum != rf['checksum'] rf_url = generate_cookbook_url( rf['name'], cookbook_name, segment, @node, current_checksum ? { 'checksum' => current_checksum } : nil ) changed = true begin raw_file = rest.get_rest(rf_url, true) rescue Net::HTTPRetriableError => e if e.response.kind_of?(Net::HTTPNotModified) changed = false Chef::Log.debug("Cache file #{cache_file} is unchanged") else raise e end end if changed Chef::Log.info("Storing updated #{cache_file} in the cache.") Chef::FileCache.move_to(raw_file.path, cache_file) end end end end Chef::FileCache.list.each do |cache_file| if cache_file =~ /^cookbooks\/#{cookbook_name}\/(recipes|attributes|definitions|libraries|resources|providers)\// unless file_canonical[cache_file] Chef::Log.info("Removing #{cache_file} from the cache; it is no longer on the server.") Chef::FileCache.delete(cache_file) end end end end |