<commit_before>
require 'json'
require 'chef'

require 'chef/azure/heartbeat'
require 'chef/azure/status'

class AzureChefClient
  include Chef::Mixin::ShellOut
  CHEF_BINS_PATH = "C:\\opscode\\chef\\bin;C:\\opscode\\chef\\embedded\\bin"

  def initialize(extension_root, *chef_client_args)
    @chef_extension_root = extension_root
    @chef_client_args = chef_client_args
    @exit_code = 0
  end

  def run
    load_handler_env

    report_heart_beat_to_azure

    run_chef_client

    return @exit_code

  end

  private
  def load_handler_env
    Chef::Log.info "Loading Handler environment..."
    # Load environment from @chef_extension_root/HandlerEnvironment.json
    handler_env = JSON.parse(File.read("#{@chef_extension_root}\\HandlerEnvironment.json"))
    @azure_heart_beat_file = handler_env[0]["handlerEnvironment"]["heartbeatFile"]
    @azure_status_folder = handler_env[0]["handlerEnvironment"]["statusFolder"]
    @azure_plugin_log_location = handler_env[0]["handlerEnvironment"]["logFolder"]
    @azure_config_folder = handler_env[0]["handlerEnvironment"]["configFolder"]
    Chef::Log.info "#{@azure_config_folder} --> #{@azure_status_folder} --> #{@azure_heart_beat_file} --> #{@azure_plugin_log_location}"
    # Get name of status file by finding the latest sequence number from runtime settings file
    sequence = 0
    settingsFiles = Dir.entries(@chef_extension_root + "\\RuntimeSettings").sort
    if(settingsFiles.size) > 2
      sequence = settingsFiles[settingsFiles.size-1].split(".")[0]
    end
    @azure_status_file = @azure_status_folder + "\\" + sequence + ".status"
    Chef::Log.info "Status file name: #{@azure_status_file}"
  end

  def report_heart_beat_to_azure
    # update @azure_heart_beat_file
    Chef::Log.info "Reporting heartbeat..."
    AzureHeartBeat.update(@azure_heart_beat_file, AzureHeartBeat::READY, 0, "chef-service is running properly")
  end

  def run_chef_client
    # The chef client will be started in a new process. We have used shell_out to start the chef-client.
    # We need to add the --no-fork, as by default it is set to fork=true.
    begin
      # Pass config params to the new process
      config_params = @chef_client_args.join(" ") + " --no-fork"

      # set path so original chef-client is picked up
      ENV["PATH"] = "#{CHEF_BINS_PATH};#{ENV["PATH"]}"

      Chef::Log.info "running chef-client with: Args = [#{config_params}], Path = [#{ENV["PATH"]}]"

      # Starts chef-client from original chef and waits till the process exits
      @exit_code = 0
      last_run_result = shell_out("chef-client #{config_params}")
      last_run_result.error!
      report_status_to_azure "Chef-client run success", "success"

    rescue Mixlib::ShellOut::ShellCommandFailed => e
      Chef::Log.warn "Error running chef-client (#{e})"
      report_status_to_azure "#{e} - Check log file for details", "error"
      @exit_code = 1
    rescue => e
      Chef::Log.error e
      report_status_to_azure "#{e} - Check log file for details", "error"
      @exit_code = 1
    ensure
      # Once process exits, we log the current process' pid
      Chef::Log.info "Process completed (pid: #{Process.pid})"
    end
  end

  def report_status_to_azure (message, status_type)
    AzureExtensionStatus.log(@azure_status_file, message, status_type)
  end

end
<commit_msg>use shared helper methods.<commit_after>
require 'chef'
require 'chef/azure/helpers/shared'

class AzureChefClient
  include Chef::Mixin::ShellOut
  include ChefAzure::Config
  include ChefAzure::reporting

  def initialize(extension_root, *chef_client_args)
    @chef_extension_root = extension_root
    @chef_client_args = chef_client_args
    @exit_code = 0
  end

  def run
    load_env

    report_heart_beat

    run_chef_client

    return @exit_code

  end

  private
  def load_env
    @azure_heart_beat_file, @azure_status_folder, @azure_plugin_log_location, @azure_config_folder, @azure_status_file = read_config(@chef_extension_root)
  end

  def report_heart_beat
    # update @azure_heart_beat_file
    report_heart_beat_to_azure(@azure_heart_beat_file, AzureHeartBeat::READY, 0, "chef-service is running properly")
  end

  def run_chef_client
    # The chef client will be started in a new process. We have used shell_out to start the chef-client.
    # We need to add the --no-fork, as by default it is set to fork=true.
    begin
      # Pass config params to the new process
      config_params = @chef_client_args.join(" ") + " --no-fork"

      # set path so original chef-client is picked up
      path = append_to_path(chef_bin_path)
      
      Chef::Log.info "running chef-client with: Args = [#{config_params}], Path = [#{path}]"

      # Starts chef-client from original chef and waits till the process exits
      @exit_code = 0
      last_run_result = shell_out("chef-client #{config_params}")
      last_run_result.error!
      report_status_to_azure "Chef-client run success", "success"

    rescue Mixlib::ShellOut::ShellCommandFailed => e
      Chef::Log.warn "Error running chef-client (#{e})"
      report_status_to_azure "#{e} - Check log file for details", "error"
      @exit_code = 1
    rescue => e
      Chef::Log.error e
      report_status_to_azure "#{e} - Check log file for details", "error"
      @exit_code = 1
    ensure
      # Once process exits, we log the current process' pid
      Chef::Log.info "Process completed (pid: #{Process.pid})"
    end
  end

end

{'fraction_non_alphanumeric': 0.10560146923783287, 'fraction_numerical': 0.003305785123966942, 'mean_word_length': 3.7563318777292576, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3709349', 'n_tokens_mistral': 1776, 'n_tokens_neox': 1726, 'n_words': 443}