Class: Splash::CommandWrapper

Inherits:
Object
  • Object
show all
Includes:
Backends, Config, Exiter, Helpers, Templates, Transports
Defined in:
lib/splash/commands.rb

Constant Summary collapse

@@registry =
Prometheus::Client.registry
@@metric_exitcode =
Prometheus::Client::Gauge.new(:errorcode, docstring: 'SPLASH metric batch errorcode')
@@metric_time =
Prometheus::Client::Gauge.new(:exectime, docstring: 'SPLASH metric batch execution time')

Constants included from Constants

Splash::Constants::AUTHOR, Splash::Constants::BACKENDS_STRUCT, Splash::Constants::CONFIG_FILE, Splash::Constants::COPYRIGHT, Splash::Constants::DAEMON_LOGMON_SCHEDULING, Splash::Constants::DAEMON_PID_FILE, Splash::Constants::DAEMON_PID_PATH, Splash::Constants::DAEMON_PROCESS_NAME, Splash::Constants::DAEMON_STDERR_TRACE, Splash::Constants::DAEMON_STDOUT_TRACE, Splash::Constants::EMAIL, Splash::Constants::EXECUTION_TEMPLATE, Splash::Constants::EXECUTION_TEMPLATE_TOKENS_LIST, Splash::Constants::LICENSE, Splash::Constants::LOGGERS_STRUCT, Splash::Constants::PROMETHEUS_PUSHGATEWAY_HOST, Splash::Constants::PROMETHEUS_PUSHGATEWAY_PORT, Splash::Constants::TRACE_PATH, Splash::Constants::TRANSPORTS_STRUCT, Splash::Constants::VERSION

Constants included from Exiter

Exiter::EXIT_MAP

Instance Method Summary collapse

Methods included from Transports

#get_default_client, #get_default_subscriber

Methods included from Config

#get_config

Methods included from ConfigUtilities

#checkconfig, #setupsplash

Methods included from Helpers

#daemonize, #get_process, #group_root, #install_file, #is_root?, #make_folder, #make_link, #run_as_root, #search_file_in_gem, #user_root, #verify_file, #verify_folder, #verify_link, #verify_service

Methods included from Exiter

#splash_exit

Methods included from Loggers

#change_logger, #get_logger

Methods included from Backends

#get_backend

Constructor Details

#initialize(name) ⇒ CommandWrapper

Returns a new instance of CommandWrapper.



18
19
20
21
22
23
24
25
# File 'lib/splash/commands.rb', line 18

def initialize(name)
  @config  = get_config
  @url = "http://#{@config.prometheus_pushgateway_host}:#{@config.prometheus_pushgateway_port}"
  @name = name
  unless @config.commands.keys.include? @name.to_sym then
    splash_exit case: :not_found, more: "command #{@name} is not defined in configuration"
  end
end

Instance Method Details

#ackObject



27
28
29
30
# File 'lib/splash/commands.rb', line 27

def ack
  get_logger.info "Sending ack for command : '#{@name}'"
  notify(0,0)
end

#call_and_notify(options) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/splash/commands.rb', line 45

def call_and_notify(options)
  log = get_logger
  acase = { :case => :quiet_exit }
  exit_code = 0
  if @config.commands[@name.to_sym][:delegate_to] then
    return { :case => :options_incompatibility, :more => '--hostname forbidden with delagate commands'} if options[:hostname]
    log.send "Remote command : #{@name} execution delegate to : #{@config.commands[@name.to_sym][:delegate_to][:host]} as : #{@config.commands[@name.to_sym][:delegate_to][:remote_command]}"
    begin
      transport = get_default_client
      if transport.class == Hash  and transport.include? :case then
        return transport
      else
        res = transport.execute({ :verb => :execute_command,
          payload: {:name => @config.commands[@name.to_sym][:delegate_to][:remote_command].to_s},
          :return_to => "splash.#{Socket.gethostname}.return",
          :queue => "splash.#{@config.commands[@name.to_sym][:delegate_to][:host]}.input" })
        exit_code = res[:exit_code]
        log.receive "return with exitcode #{exit_code}"

      end
    end
  else
    log.info "Executing command : '#{@name}' "
    start = Time.now
    start_date = DateTime.now.to_s
    unless options[:trace] then
      log.item "Traceless execution"
      if @config.commands[@name.to_sym][:user] then
        log.item "Execute with user : #{@config.commands[@name.to_sym][:user]}."
        system("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
      else
        system("#{@config.commands[@name.to_sym][:command]} > /dev/null 2>&1")
      end
      time = Time.now - start
      exit_code = $?.exitstatus
    else
      log.item "Tracefull execution"
      if @config.commands[@name.to_sym][:user] then
        log.item "Execute with user : #{@config.commands[@name.to_sym][:user]}."
        stdout, stderr, status = Open3.capture3("sudo -u #{@config.commands[@name.to_sym][:user]} #{@config.commands[@name.to_sym][:command]}")
      else
        stdout, stderr, status = Open3.capture3(@config.commands[@name.to_sym][:command])
      end
      time = Time.now - start
      tp = Template::new(
        list_token: @config.execution_template_tokens,
        template_file: @config.execution_template_path)
      data = Hash::new
      data[:start_date] = start_date
      data[:end_date] = DateTime.now.to_s
      data[:cmd_name] = @name
      data[:cmd_line] = @config.commands[@name.to_sym][:command]
      data[:desc] = @config.commands[@name.to_sym][:desc]
      data[:status] = status.to_s
      data[:stdout] = stdout
      data[:stderr] = stderr
      data[:exec_time] = time.to_s
      backend = get_backend :execution_trace
      key = @name
      backend.put key: key, value: data.to_yaml
      exit_code = status.exitstatus
    end
    log.ok "Command executed"
    log.arrow "exitcode #{exit_code}"
    if options[:notify] then
      acase = notify(exit_code,time.to_i)
    else
      log.item "Without Prometheus notification"
    end
  end

  if options[:callback] then
    on_failure = (@config.commands[@name.to_sym][:on_failure])? @config.commands[@name.to_sym][:on_failure] : false
    on_success = (@config.commands[@name.to_sym][:on_success])? @config.commands[@name.to_sym][:on_success] : false
    if on_failure and exit_code > 0 then
      log.item "On failure callback : #{on_failure}"
      if @config.commands.keys.include?  on_failure then
        @name = on_failure.to_s
        call_and_notify options
      else
        acase = { :case => :configuration_error , :more => "on_failure call error : #{on_failure} command inexistant."}
      end
    end
    if on_success and exit_code == 0 then
      log.item "On success callback : #{on_success}"
      if @config.commands.keys.include?  on_success then
        @name = on_success.to_s
        call_and_notify options
      else
        acase = { :case => :configuration_error , :more => "on_success call error : #{on_failure} command inexistant."}
      end
    end
  else
    log.item "Without callbacks sequences"
  end
  acase[:exit_code] = exit_code
  return acase
end

#notify(value, time) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/splash/commands.rb', line 32

def notify(value,time)
  unless verify_service host: @config.prometheus_pushgateway_host ,port: @config.prometheus_pushgateway_port then
    return { :case => :service_dependence_missing, :more => "Prometheus Notification not send."}
  end
  @@metric_exitcode.set(value)
  @@metric_time.set(time)
  hostname = Socket.gethostname
  Prometheus::Client::Push.new(@name, hostname, @url).add(@@registry)
  get_logger.ok "Prometheus Gateway notified."
  return { :case => :quiet_exit}
end