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

Returns a new instance of Application.



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

Returns:

  • (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)

Returns:

  • (Boolean)


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?

Returns:

  • (Boolean)


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