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.
-
#safe_name ⇒ Object
Returns the value of attribute safe_name.
-
#validation_token ⇒ Object
Returns the value of attribute validation_token.
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.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# 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 Mixlib::Authentication::Log.logger = Ohai::Log.logger = Chef::Log.logger @ohai = Ohai::System.new @ohai_has_run = false if File.exists?(Chef::Config[:client_key]) @rest = Chef::REST.new(Chef::Config[:chef_server_url]) else @rest = 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.
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
#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
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 |
# File 'lib/chef/client.rb', line 146 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 @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 |
# File 'lib/chef/client.rb', line 309 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 |
#determine_node_name ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/chef/client.rb', line 124 def determine_node_name run_ohai unless safe_name && 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 @safe_name = @node_name.gsub(/\./, '_') end @node_name end |
#register ⇒ Object
Returns
- rest<Chef::REST>
-
returns Chef::REST connection object
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/chef/client.rb', line 181 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") @vr = Chef::REST.new(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]) @vr.register(@node_name, Chef::Config[:client_key]) end # We now have the client key, and should use it from now on. @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 94 |
# 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 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
116 117 118 119 120 121 122 |
# File 'lib/chef/client.rb', line 116 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.
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/chef/client.rb', line 103 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
292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/chef/client.rb', line 292 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_cookbooks ⇒ Object
Synchronizes all the cookbooks from the chef-server.
Returns
- true
-
Always returns true
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/chef/client.rb', line 271 def sync_cookbooks Chef::Log.debug("Synchronizing cookbooks") cookbook_hash = @rest.get_rest("nodes/#{@safe_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; it's 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
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 263 264 265 |
# File 'lib/chef/client.rb', line 200 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 |