Class: Chef::Application

Inherits:
Object show all
Includes:
Mixlib::CLI
Defined in:
lib/chef/application.rb,
lib/chef/application/windows_service.rb

Direct Known Subclasses

Apply, Client, Knife, Solo

Defined Under Namespace

Classes: Apply, Client, Knife, Solo, Wakeup, WindowsService

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeApplication



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
# File 'lib/chef/application.rb', line 35

def initialize
  super

  @chef_client = nil
  @chef_client_json = nil
  trap("TERM") do
    Chef::Application.fatal!("SIGTERM received, stopping", 1)
  end

  trap("INT") do
    Chef::Application.fatal!("SIGINT received, stopping", 2)
  end

  unless Chef::Platform.windows?
    trap("QUIT") do
      Chef::Log.info("SIGQUIT received, call stack:\n  " + caller.join("\n  "))
    end

    trap("HUP") do
      Chef::Log.info("SIGHUP received, reconfiguring")
      reconfigure
    end
  end

  # Always switch to a readable directory. Keeps subsequent Dir.chdir() {}
  # from failing due to permissions when launched as a less privileged user.
end

Class Method Details

.debug_stacktrace(e) ⇒ Object



202
203
204
205
206
207
208
209
210
211
# File 'lib/chef/application.rb', line 202

def debug_stacktrace(e)
  message = "#{e.class}: #{e}\n#{e.backtrace.join("\n")}"
  chef_stacktrace_out = "Generated at #{Time.now.to_s}\n"
  chef_stacktrace_out += message

  Chef::FileCache.store("chef-stacktrace.out", chef_stacktrace_out)
  Chef::Log.fatal("Stacktrace dumped to #{Chef::FileCache.load("chef-stacktrace.out", false)}")
  Chef::Log.debug(message)
  true
end

.exit!(msg, err = -1)) ⇒ Object



219
220
221
222
# File 'lib/chef/application.rb', line 219

def exit!(msg, err = -1)
  Chef::Log.debug(msg)
  Process.exit err
end

.fatal!(msg, err = -1)) ⇒ Object

Log a fatal error message to both STDERR and the Logger, exit the application



214
215
216
217
# File 'lib/chef/application.rb', line 214

def fatal!(msg, err = -1)
  Chef::Log.fatal(msg)
  Process.exit err
end

Instance Method Details

#auto_log_level?Boolean



154
155
156
# File 'lib/chef/application.rb', line 154

def auto_log_level?
  Chef::Config[:log_level] == :auto
end

#configure_chefObject

Parse the configuration file



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
# File 'lib/chef/application.rb', line 77

def configure_chef
  parse_options

  begin
    case config[:config_file]
    when /^(http|https):\/\//
      Chef::REST.new("", nil, nil).fetch(config[:config_file]) { |f| apply_config(f.path) }
    else
      ::File::open(config[:config_file]) { |f| apply_config(f.path) }
    end
  rescue Errno::ENOENT => error
    Chef::Log.warn("*****************************************")
    Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.")
    Chef::Log.warn("*****************************************")

    Chef::Config.merge!(config)
  rescue SocketError => error
    Chef::Application.fatal!("Error getting config file #{Chef::Config[:config_file]}", 2)
  rescue Chef::Exceptions::ConfigurationError => error
    Chef::Application.fatal!("Error processing config file #{Chef::Config[:config_file]} with error #{error.message}", 2)
  rescue Exception => error
    Chef::Application.fatal!("Unknown error processing config file #{Chef::Config[:config_file]} with error #{error.message}", 2)
  end

end

#configure_loggingObject

Initialize and configure the logger.

Loggers and Formatters

In Chef 10.x and previous, the Logger was the primary/only way that Chef communicated information to the user. In Chef 10.14, a new system, “output formatters” was added, and in Chef 11.0+ it is the default when running chef in a console (detected by ‘STDOUT.tty?`). Because output formatters are more complex than the logger system and users have less experience with them, the config option `force_logger` is provided to restore the Chef 10.x behavior.

Conversely, for users who want formatter output even when chef is running unattended, the ‘force_formatter` option is provided.

Auto Log Level

When ‘log_level` is set to `:auto` (default), the log level will be `:warn` when the primary output mode is an output formatter (see using_output_formatter?) and `:info` otherwise.

Automatic STDOUT Logging

When ‘force_logger` is configured (e.g., Chef 10 mode), a second logger with output on STDOUT is added when running in a console (STDOUT is a tty) and the configured log_location isn’t STDOUT. This accounts for the case that a user has configured a log_location in client.rb, but is running chef-client by hand to troubleshoot a problem.



127
128
129
130
131
132
133
# File 'lib/chef/application.rb', line 127

def configure_logging
  Chef::Log.init(Chef::Config[:log_location])
  if want_additional_logger?
    configure_stdout_logger
  end
  Chef::Log.level = resolve_log_level
end

#configure_stdout_loggerObject



135
136
137
138
139
140
# File 'lib/chef/application.rb', line 135

def configure_stdout_logger
  stdout_logger = Logger.new(STDOUT)
  STDOUT.sync = true
  stdout_logger.formatter = Chef::Log.logger.formatter
  Chef::Log.loggers <<  stdout_logger
end

#reconfigureObject

Reconfigure the application. You’ll want to override and super this method.



64
65
66
67
# File 'lib/chef/application.rb', line 64

def reconfigure
  configure_chef
  configure_logging
end

#resolve_log_levelObject

if log_level is ‘:auto`, convert it to :warn (when using output formatter) or :info (no output formatter). See also using_output_formatter?



160
161
162
163
164
165
166
167
168
169
170
# File 'lib/chef/application.rb', line 160

def resolve_log_level
  if auto_log_level?
    if using_output_formatter?
      :warn
    else
      :info
    end
  else
    Chef::Config[:log_level]
  end
end

#runObject

Get this party started



70
71
72
73
74
# File 'lib/chef/application.rb', line 70

def run
  reconfigure
  setup_application
  run_application
end

#run_applicationObject

Actually run the application



178
179
180
# File 'lib/chef/application.rb', line 178

def run_application
  raise Chef::Exceptions::Application, "#{self.to_s}: you must override run_application"
end

#run_chef_clientObject

Initializes Chef::Client instance and runs it



183
184
185
186
187
188
189
190
191
192
# File 'lib/chef/application.rb', line 183

def run_chef_client
  @chef_client = Chef::Client.new(
    @chef_client_json, 
    :override_runlist => config[:override_runlist]
  )
  @chef_client_json = nil

  @chef_client.run
  @chef_client = nil
end

#setup_applicationObject

Called prior to starting the application, by the run method



173
174
175
# File 'lib/chef/application.rb', line 173

def setup_application
  raise Chef::Exceptions::Application, "#{self.to_s}: you must override setup_application"
end

#using_output_formatter?Boolean

Use of output formatters is assumed if ‘force_formatter` is set or if `force_logger` is not set and STDOUT is to a console (tty)



150
151
152
# File 'lib/chef/application.rb', line 150

def using_output_formatter?
  Chef::Config[:force_formatter] || (!Chef::Config[:force_logger] && STDOUT.tty?)
end

#want_additional_logger?Boolean

Based on config and whether or not STDOUT is a tty, should we setup a secondary logger for stdout?



144
145
146
# File 'lib/chef/application.rb', line 144

def want_additional_logger?
  ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && (!Chef::Config[:daemonize]) && (Chef::Config[:force_logger])
end