Class: Chef::Client
- Inherits:
-
Object
- Object
- 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.
-
#safe_name ⇒ Object
Returns the value of attribute safe_name.
-
#validation_token ⇒ Object
Returns the value of attribute validation_token.
Instance Method Summary collapse
-
#authenticate ⇒ Object
Authenticates the node via OpenID.
-
#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.
-
#create_registration ⇒ Object
Generates a random secret, stores it in the Chef::Filestore with the “registration” key, and posts our nodes registration information to the server.
- #determine_node_name ⇒ Object
-
#initialize ⇒ Client
constructor
Creates a new Chef::Client.
-
#register ⇒ Object
If this node has been registered before, this method will fetch the current registration data.
-
#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_attribute_files ⇒ Object
Gets all the attribute files included in all the cookbooks available on the server, and executes them.
-
#sync_definitions ⇒ Object
Gets all the definition files included in all the cookbooks available on the server, and loads them.
-
#sync_library_files ⇒ Object
Gets all the library files included in all the cookbooks available on the server, and loads them.
-
#sync_provider_files ⇒ Object
Gets all the provider files included in all the cookbooks available on the server, and loads them.
-
#sync_recipes ⇒ Object
Gets all the recipe files included in all the cookbooks available on the server, and loads them.
-
#sync_resource_files ⇒ Object
Gets all the resource files included in all the cookbooks available on the server, and loads them.
-
#update_file_cache(segment, remote_list) ⇒ Object
Update the file caches for a given cache segment.
Methods included from Mixin::Checksum
Methods included from Mixin::GenerateURL
Constructor Details
#initialize ⇒ Client
Creates a new Chef::Client.
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/chef/client.rb', line 42 def initialize() @node = nil @safe_name = nil @validation_token = nil @registration = nil @json_attribs = nil @node_name = nil @node_exists = true Ohai::Log.logger = Chef::Log.logger @ohai = Ohai::System.new @rest = Chef::REST.new(Chef::Config[:registration_url]) end |
Instance Attribute Details
#json_attribs ⇒ Object
Returns the value of attribute json_attribs.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def json_attribs @json_attribs end |
#node ⇒ Object
Returns the value of attribute node.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def node @node end |
#node_name ⇒ Object
Returns the value of attribute node_name.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def node_name @node_name end |
#ohai ⇒ Object
Returns the value of attribute ohai.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def ohai @ohai end |
#registration ⇒ Object
Returns the value of attribute registration.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def registration @registration end |
#safe_name ⇒ Object
Returns the value of attribute safe_name.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def safe_name @safe_name end |
#validation_token ⇒ Object
Returns the value of attribute validation_token.
39 40 41 |
# File 'lib/chef/client.rb', line 39 def validation_token @validation_token end |
Instance Method Details
#authenticate ⇒ Object
Authenticates the node via OpenID.
Returns
- true
-
Always returns true
236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/chef/client.rb', line 236 def authenticate determine_node_name unless @node_name Chef::Log.debug("Authenticating #{@safe_name} via openid") response = @rest.post_rest('openid/consumer/start', { "openid_identifier" => "#{Chef::Config[:openid_url]}/openid/server/node/#{@safe_name}", "submit" => "Verify" }) @rest.post_rest( "#{Chef::Config[:openid_url]}#{response["action"]}", { "password" => @secret } ) end |
#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
142 143 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 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/chef/client.rb', line 142 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 #{@safe_name}") unless solo begin @node = @rest.get_rest("nodes/#{@safe_name}") rescue Net::HTTPServerException => e unless e. =~ /^404/ raise e end end end unless @node @node_exists = false @node ||= Chef::Node.new @node.name(node_name) end if @json_attribs Chef::Log.debug("Adding JSON Attributes") @json_attribs.each do |key, value| if key == "recipes" || key == "run_list" value.each do |recipe| unless @node.recipes.detect { |r| r == recipe } Chef::Log.debug("Adding recipe #{recipe}") @node.recipes << recipe end end else Chef::Log.debug("JSON Attribute: #{key} - #{value.inspect}") @node[key] = value end end end 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[:tags] = Array.new unless @node.attribute?(:tags) @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
398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/chef/client.rb', line 398 def converge(solo=false) Chef::Log.debug("Compiling recipes for node #{@safe_name}") unless solo Chef::Config[:cookbook_path] = File.join(Chef::Config[:file_cache_path], "cookbooks") end compile = Chef::Compile.new(@node) Chef::Log.debug("Converging node #{@safe_name}") cr = Chef::Runner.new(@node, compile.collection, compile.definitions, compile.cookbook_loader) cr.converge true end |
#create_registration ⇒ Object
Generates a random secret, stores it in the Chef::Filestore with the “registration” key, and posts our nodes registration information to the server.
Returns
- true
-
Always returns true
225 226 227 228 229 230 |
# File 'lib/chef/client.rb', line 225 def create_registration @secret = random_password(500) Chef::FileCache.store(File.join("registration", @safe_name), @secret) @rest.post_rest("registrations", { :id => @safe_name, :password => @secret, :validation_token => @validation_token }) true end |
#determine_node_name ⇒ Object
125 126 127 128 129 130 131 132 |
# File 'lib/chef/client.rb', line 125 def determine_node_name run_ohai unless safe_name && node_name @node_name ||= @ohai[:fqdn] ? @ohai[:fqdn] : @ohai[:hostname] @safe_name = @node_name.gsub(/\./, '_') end @node_name end |
#register ⇒ Object
If this node has been registered before, this method will fetch the current registration data.
If it has not, we register it by calling create_registration.
Returns
- true
-
Always returns true
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/chef/client.rb', line 195 def register determine_node_name unless @node_name Chef::Log.debug("Registering #{@safe_name} for an openid") begin if @rest.get_rest("registrations/#{@safe_name}") @secret = Chef::FileCache.load(File.join("registration", @safe_name)) end rescue Net::HTTPServerException => e case e. when /^404/ create_registration else raise end rescue Chef::Exceptions::FileNotFound Chef::Application.fatal! "A remote registration already exists for #{@safe_name}, however the local shared secret does not exist." + " To remedy this, you could delete the registration via webUI/REST, change the node_name option in config.rb" + " (or use the -N/--node-name option to the CLI) or" + " copy the old shared secret to #{File.join(Chef::Config[:file_cache_path], 'registration', @safe_name)}", 3 end true 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.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/chef/client.rb', line 73 def run start_time = Time.now Chef::Log.info("Starting Chef Run") determine_node_name register authenticate build_node(@node_name) save_node sync_library_files sync_provider_files sync_resource_files sync_attribute_files sync_definitions sync_recipes save_node converge save_node end_time = Time.now Chef::Log.info("Chef Run complete in #{end_time - start_time} seconds") true end |
#run_ohai ⇒ Object
117 118 119 120 121 122 123 |
# File 'lib/chef/client.rb', line 117 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.
104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/chef/client.rb', line 104 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
381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/chef/client.rb', line 381 def save_node Chef::Log.debug("Saving the current state of node #{@safe_name}") if @node_exists @node = @rest.put_rest("nodes/#{@safe_name}", @node) else result = @rest.post_rest("nodes", @node) @node = @rest.get_rest(result['uri']) @node_exists = true end true end |
#sync_attribute_files ⇒ Object
Gets all the attribute files included in all the cookbooks available on the server, and executes them.
Returns
- true
-
Always returns true
318 319 320 321 322 |
# File 'lib/chef/client.rb', line 318 def sync_attribute_files Chef::Log.debug("Synchronizing attributes") update_file_cache("attributes", @rest.get_rest("cookbooks/_attribute_files?node=#{@node.name}")) true end |
#sync_definitions ⇒ Object
Gets all the definition files included in all the cookbooks available on the server, and loads them.
Returns
- true
-
Always returns true
362 363 364 365 |
# File 'lib/chef/client.rb', line 362 def sync_definitions Chef::Log.debug("Synchronizing definitions") update_file_cache("definitions", @rest.get_rest("cookbooks/_definition_files?node=#{@node.name}")) end |
#sync_library_files ⇒ Object
Gets all the library files included in all the cookbooks available on the server, and loads them.
Returns
- true
-
Always returns true
329 330 331 332 333 |
# File 'lib/chef/client.rb', line 329 def sync_library_files Chef::Log.debug("Synchronizing libraries") update_file_cache("libraries", @rest.get_rest("cookbooks/_library_files?node=#{@node.name}")) true end |
#sync_provider_files ⇒ Object
Gets all the provider files included in all the cookbooks available on the server, and loads them.
Returns
- true
-
Always returns true
340 341 342 343 344 |
# File 'lib/chef/client.rb', line 340 def sync_provider_files Chef::Log.debug("Synchronizing providers") update_file_cache("providers", @rest.get_rest("cookbooks/_provider_files?node=#{@node.name}")) true end |
#sync_recipes ⇒ Object
Gets all the recipe files included in all the cookbooks available on the server, and loads them.
Returns
- true
-
Always returns true
372 373 374 375 |
# File 'lib/chef/client.rb', line 372 def sync_recipes Chef::Log.debug("Synchronizing recipes") update_file_cache("recipes", @rest.get_rest("cookbooks/_recipe_files?node=#{@node.name}")) end |
#sync_resource_files ⇒ Object
Gets all the resource files included in all the cookbooks available on the server, and loads them.
Returns
- true
-
Always returns true
351 352 353 354 355 |
# File 'lib/chef/client.rb', line 351 def sync_resource_files Chef::Log.debug("Synchronizing resources") update_file_cache("resources", @rest.get_rest("cookbooks/_resource_files?node=#{@node.name}")) true end |
#update_file_cache(segment, remote_list) ⇒ 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
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/chef/client.rb', line 256 def update_file_cache(segment, remote_list) # We need the list of known good attribute files, so we can delete any that are # just laying about. file_canonical = Hash.new remote_list.each do |rf| cache_file = File.join("cookbooks", rf['cookbook'], 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 rf_url = generate_cookbook_url( rf['name'], rf['cookbook'], segment, @node, current_checksum ? { 'checksum' => current_checksum } : nil ) Chef::Log.debug(rf_url) if current_checksum != rf['checksum'] 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 Chef::FileCache.list.each do |cache_file| if cache_file.match("cookbooks/.+?/#{segment}") 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 |