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

Client, Knife, Solo

Defined Under Namespace

Classes: Client, Knife, Solo, Wakeup, WindowsService

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeApplication



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

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



152
153
154
155
156
157
158
159
160
161
# File 'lib/chef/application.rb', line 152

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



169
170
171
172
# File 'lib/chef/application.rb', line 169

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



164
165
166
167
# File 'lib/chef/application.rb', line 164

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

Instance Method Details

#configure_chefObject

Parse the configuration file



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

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. If the configured log location is not STDOUT, but stdout is a TTY and we’re not daemonizing, we set up a secondary logger with output to stdout. This way, we magically do the right thing when the user has configured logging to a file but they’re running chef in the shell to debug something.

If the user has configured a formatter, then we skip the magical logger to keep the output pretty.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/chef/application.rb', line 110

def configure_logging
  require 'pp'
  Chef::Log.init(Chef::Config[:log_location])
  if ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && (!Chef::Config[:daemonize]) && (Chef::Config.formatter == "null")
    stdout_logger = Logger.new(STDOUT)
    STDOUT.sync = true
    stdout_logger.formatter = Chef::Log.logger.formatter
    Chef::Log.loggers <<  stdout_logger
  end
  Chef::Log.level = Chef::Config[:log_level]
end

#reconfigureObject

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



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

def reconfigure
  configure_chef
  configure_logging
end

#runObject

Get this party started



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

def run
  reconfigure
  setup_application
  run_application
end

#run_applicationObject

Actually run the application



128
129
130
# File 'lib/chef/application.rb', line 128

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



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

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



123
124
125
# File 'lib/chef/application.rb', line 123

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