# class Chef::Application

### Public Class Methods

destroy_server_connectivity() click to toggle source

    # File lib/chef/application.rb, line 194
    def self.destroy_server_connectivity
      if @chef_zero_server
        @chef_zero_server.stop
        @chef_zero_server = nil
      end
    end

new() click to toggle source
Calls superclass method

    # File lib/chef/application.rb, line 33
    def initialize
      super

      @chef_client = nil
      @chef_client_json = nil
      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

setup_server_connectivity() click to toggle source

    # File lib/chef/application.rb, line 173
    def self.setup_server_connectivity
      if Chef::Config.chef_zero.enabled
        destroy_server_connectivity

        require 'chef_zero/server'
        require 'chef/chef_fs/chef_fs_data_store'
        require 'chef/chef_fs/config'

        chef_fs = Chef::ChefFS::Config.new.local_fs
        chef_fs.write_pretty_json = true
        server_options = {}
        server_options[:data_store] = Chef::ChefFS::ChefFSDataStore.new(chef_fs)
        server_options[:log_level] = Chef::Log.level
        server_options[:port] = Chef::Config.chef_zero.port
        Chef::Log.info("Starting chef-zero on port #{Chef::Config.chef_zero.port} with repository at #{server_options[:data_store].chef_fs.fs_description}")
        @chef_zero_server = ChefZero::Server.new(server_options)
        @chef_zero_server.start_background
        Chef::Config.chef_server_url = @chef_zero_server.url
      end
    end

### Public Instance Methods

auto_log_level?() click to toggle source

    # File lib/chef/application.rb, line 145
    def auto_log_level?
      Chef::Config[:log_level] == :auto
    end

configure_chef() click to toggle source

Parse configuration (options and config file)

    # File lib/chef/application.rb, line 71
    def configure_chef
      parse_options
      load_config_file
    end

configure_logging() click to toggle source

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.

    # File lib/chef/application.rb, line 116
    def configure_logging
      Chef::Log.init(MonoLogger.new(Chef::Config[:log_location]))
      if want_additional_logger?
        configure_stdout_logger
      end
      Chef::Log.level = resolve_log_level
    rescue StandardError => error
      Chef::Log.fatal("Failed to open or create log file at #{Chef::Config[:log_location]}: #{error.class} (#{error.message})")
      Chef::Application.fatal!("Aborting due to invalid 'log_location' configuration", 2)
    end

configure_stdout_logger() click to toggle source

    # File lib/chef/application.rb, line 127
    def configure_stdout_logger
      stdout_logger = MonoLogger.new(STDOUT)
      stdout_logger.formatter = Chef::Log.logger.formatter
      Chef::Log.loggers <<  stdout_logger
    end

load_config_file() click to toggle source

Parse the config file

    # File lib/chef/application.rb, line 77
    def load_config_file
      config_fetcher = Chef::ConfigFetcher.new(config[:config_file], Chef::Config.config_file_jail)
      if config[:config_file].nil?
        Chef::Log.warn("No config file found or specified on command line, using command line options.")
      elsif config_fetcher.config_missing?
        Chef::Log.warn("*****************************************")
        Chef::Log.warn("Did not find config file: #{config[:config_file]}, using command line options.")
        Chef::Log.warn("*****************************************")
      else
        config_content = config_fetcher.read_config
        apply_config(config_content, config[:config_file])
      end
      Chef::Config.merge!(config)
    end

reconfigure() click to toggle source

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

    # File lib/chef/application.rb, line 58
    def reconfigure
      configure_chef
      configure_logging
    end

resolve_log_level() click to toggle source

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

    # File lib/chef/application.rb, line 151
    def resolve_log_level
      if auto_log_level?
        if using_output_formatter?
          :warn
        else
          :info
        end
      else
        Chef::Config[:log_level]
      end
    end

run() click to toggle source

Get this party started

    # File lib/chef/application.rb, line 64
    def run
      reconfigure
      setup_application
      run_application
    end

run_application() click to toggle source

Actually run the application

    # File lib/chef/application.rb, line 169
    def run_application
      raise Chef::Exceptions::Application, "#{self.to_s}: you must override run_application"
    end

run_chef_client(specific_recipes = []) click to toggle source

Initializes Chef::Client instance and runs it

    # File lib/chef/application.rb, line 202
    def run_chef_client(specific_recipes = [])
      Chef::Application.setup_server_connectivity

      override_runlist = config[:override_runlist]
      if specific_recipes.size > 0
        override_runlist ||= []
      end
      @chef_client = Chef::Client.new(
        @chef_client_json,
        :override_runlist => config[:override_runlist],
        :specific_recipes => specific_recipes,
        :runlist => config[:runlist]
      )
      @chef_client_json = nil

      @chef_client.run
      @chef_client = nil

      Chef::Application.destroy_server_connectivity
    end

setup_application() click to toggle source

Called prior to starting the application, by the run method

    # File lib/chef/application.rb, line 164
    def setup_application
      raise Chef::Exceptions::Application, "#{self.to_s}: you must override setup_application"
    end

using_output_formatter?() click to toggle source

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)

    # File lib/chef/application.rb, line 141
    def using_output_formatter?
      Chef::Config[:force_formatter] || (!Chef::Config[:force_logger] && STDOUT.tty?)
    end

want_additional_logger?() click to toggle source

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

    # File lib/chef/application.rb, line 135
    def want_additional_logger?
      ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && (!Chef::Config[:daemonize]) && (Chef::Config[:force_logger])
    end