1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/usr/bin/env ruby
#
# ./chef-client-new - Build a meal with chef
#
# Author:: Adam Jacob (<adam@opscode.com>)
# Copyright:: Copyright (c) 2008 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'optparse'
require 'rubygems'
require 'chef'
require 'chef/client'
require 'chef/daemon'
require 'json'
config = {
:config_file => "/etc/chef/client.rb"
}
opts = OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [-d DIR|-r FILE] (options)"
client_option_hash = {
:config_file=> { :short=>"-c CONFIG", :long=>"--config CONFIG", :description=>"The Chef Config file to use", :proc=>nil },
:user=> { :short=>"-u USER", :long=>"--user USER", :description=>"User to change uid to before daemonizing", :proc=>nil },
:group=> { :short=>"-g GROUP", :long=>"--group GROUP", :description=>"Group to change gid to before daemonizing", :proc=>nil },
:daemonize=> { :short=>"-d", :long=>"--daemonize", :description=>"Daemonize the process", :proc=> lambda { |p| true} },
:interval=> { :short=>"-i SECONDS", :long=>"--interval SECONDS", :description=>"Run chef-client periodically, in seconds", :proc=>nil },
:json_attribs=>{ :short=>"-j JSON_ATTRIBS", :long=>"--json-attributes JSON_ATTRIBS", :description=>"Load attributes from a JSON file", :proc=>nil },
:node_name=> { :short=>"-N NODE_NAME", :long=>"--node-name NODE_NAME", :description=>"The node name for this client", :proc=>nil },
:splay=> { :short=>"-s SECONDS", :long=>"--splay SECONDS", :description=>"The splay time for running at intervals, in seconds", :proc=>nil },
:log_level=> { :short=>"-l LEVEL", :long=>"--loglevel LEVEL", :description=>"Set the log level (debug, info, warn, error, fatal)", :proc=>lambda { |p| p.to_sym} },
:log_location=>{ :short=>"-L LOGLOCATION", :long=>"--logfile LOGLOCATION", :description=>"Set the log file location, defaults to STDOUT - recommended for daemonizing", :proc=>nil },
:validation_token=>{ :short=>"-t TOKEN", :long=>"--token TOKEN", :description=>"Set the openid validation token", :proc=>nil },
}
client_option_hash.each do |opt_key, opt_val|
opts.on(opt_val[:short],opt_val[:long],opt_val[:description]) do |c|
config[opt_key] = (opt_val[:proc] && opt_val[:proc].call(c)) || c
end
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit 0
end
end
opts.parse!(ARGV)
unless File.exists?(config[:config_file]) and File.readable?(config[:config_file])
Chef.fatal!("I cannot find or read the config file: #{config[:config_file]}", 1)
end
if config[:json_attribs]
if File.exists?(config[:json_attribs]) and File.readable?(config[:json_attribs])
config[:json_attribs] = JSON.parse(IO.read(config[:json_attribs]))
else
Chef.fatal!("I cannot find or read #{config[:json_attribs]}", 2)
end
end
Chef::Config.from_file(config[:config_file])
Chef::Config.configure { |c| c.merge!(config) }
if Chef::Config[:daemonize]
unless Chef::Config[:log_location].is_a? IO
Chef::Log.init(Chef::Config[:log_location])
end
Chef::Log.level(Chef::Config[:log_level])
# We want to set the interval to half an hour, if one is not set.
unless Chef::Config[:interval]
Chef::Config[:interval] = 1800
end
Chef::Daemon.daemonize("chef-client")
else
Chef::Log.level(Chef::Config[:log_level])
end
if Chef::Config[:interval]
if Chef::Config[:splay]
delay = Chef::Config[:interval].to_i + rand(Chef::Config[:splay])
else
delay = Chef::Config[:interval].to_i
end
else
delay = 0
end
loop do
begin
c = Chef::Client.new
c.json_attribs = Chef::Config[:json_attribs]
c.validation_token = Chef::Config[:validation_token]
c.node_name = Chef::Config[:node_name]
c.run
if Chef::Config[:interval]
Chef::Log.debug("Sleeping for #{delay} seconds")
sleep delay
else
exit 0
end
rescue SystemExit => e
raise
rescue Exception => e
if Chef::Config[:daemonize]
Chef::Log.error("#{e.class}")
Chef::Log.fatal("#{e}\n#{e.backtrace.join("\n")}")
Chef::Log.fatal("Sleeping for #{delay} seconds before trying again")
sleep delay
retry
else
raise
end
end
end
|