class Op5util::Monitor
Foo
Foo
Foo
Foo
Foo
Foo
Foo
Foo
Top level documentation
Foo
Foo
Foo
Foo
Public Class Methods
new(monitor, username, password)
click to toggle source
debug_output $stdout
# File lib/op5util/monitor.rb, line 18 def initialize(monitor, username, password) @monitor = monitor @auth = { username: username, password: password } @base_uri = "https://#{@monitor}/api/" url = 'status/status?format=json' response = self.class.get(@base_uri + url, basic_auth: @auth, verify: false) raise AuthenticationError if !response.nil? && !response.code.nil? && response.code == 401 raise CommunicationError if response.nil? || response.code.nil? || response.code != 200 self end
Public Instance Methods
acknowledge_all_alarms(options)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 25 def acknowledge_all_alarms(options) response = self.class.get(@base_uri + 'config/host?format=json', basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 JSON.parse!(response.body).map { |h| h['name'] }.each do |host| acknowledge_host_alarms(host, options) end end
acknowledge_host_alarms(host, options)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 6 def acknowledge_host_alarms(host, options) host_states = host_status(host) if host_states[:host] > 0 puts 'Acknowledge host alarm for host ' + host ack_host_alarm(host, options) else puts 'No alarm for host ' + host + ', not acking host' end if host_states[:services].count > 0 host_states[:services].each do |s| ack_host_service(host, s, options) puts "Service \"#{s}\" acknowledged" if options[:verbose] end puts 'All service alarms for host ' + host + ' acknowledged' else puts "No service alarms to acknowledge for host #{host}" end end
add_host(host, options)
click to toggle source
# File lib/op5util/add_host.rb, line 13 def add_host(host, options) body = build_add_host_request_body(host, options) response = self.class.post(@base_uri + 'config/host', headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError, "Response code: #{response.code}, Message: #{response.body}" if response.code != 201 commit_op5_config unless options['no-commit'.to_sym] end
add_hostgroups(host, hostgroups, no_commit_config)
click to toggle source
# File lib/op5util/add_hostgroups.rb, line 8 def add_hostgroups(host, hostgroups, no_commit_config) hostgroups.each do |group| members = get_hostgroup_members(group) if !members.grep(host).empty? puts "Host #{host} is already a member of hostgroup #{group}" else raise NoSuchHostError, host unless host_exist?(host) members << host update_hostgroup(group, members) end end commit_op5_config unless no_commit_config end
autocomplete()
click to toggle source
# File lib/op5util/autocomplete.rb, line 6 def autocomplete s = ' # Add this to suitable shell startup file to get tab autocomplete for op5util. # op5util autocomplete >> ~/.bashrc # ZSH-users should uncomment the line below # autoload -U +X bashcompinit && bashcompinit _op5util() { local cur prev opts base COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}" op5command="${COMP_WORDS[1]}" opts="acknowledge add add_hostgroups downtime help hostgroups schedule status" case "${op5command}" in acknowledge) COMPREPLY=( $(compgen -W "-c --comment=Work_in_Progress -p --persistent --no-persistent -v --verbose --no-verbose $(op5util hosts)" -- ${cur}) ) ;; add) COMPREPLY=( $(compgen -W "-a --alias=\" -c --contactgroups=\" -g --hostgroups=\" -i --ipaddr=\" HOST_TO_ADD $(op5util hostgroups)" -- ${cur}) ) ;; add_hostgroups) COMPREPLY=( $(compgen -W "-g --hostgroup= $(op5util hosts)" -- ${cur}) ) ;; autocomplete) COMPREPLY=( $(compgen -W "ENTER" -- ${cur}) ) ;; downtime) COMPREPLY=( $(compgen -W "-t --time=n_hour_duration_of_downtime -w --wait=n_hours_before_downtime_start -c --comment= $(op5util hosts)" -- ${cur}) ) ;; hostgroups) COMPREPLY=( $(compgen -W "-l --long $(op5util hostgroups)" -- ${cur}) ) ;; schedule) COMPREPLY=( $(compgen -W "-v --verbose $(op5util hosts)" -- ${cur}) ) ;; status) COMPREPLY=( $(compgen -W "-l --long -s --short $(op5util hosts)" -- ${cur}) ) ;; *) ;; esac if [ -z $COMPREPLY ]; then COMPREPLY=($(compgen -W "${opts}" -- ${cur})) fi return 0 } complete -F _op5util op5util ' puts s end
commit_op5_config()
click to toggle source
# File lib/op5util/commit.rb, line 6 def commit_op5_config if pending_changes.empty? puts 'No changes to commit' else do_commit end end
list_hostgroups(hostgroup, options)
click to toggle source
# File lib/op5util/list_hostgroups.rb, line 7 def list_hostgroups(hostgroup, options) response = self.class.get(@base_uri + 'config/hostgroup?format=json', basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 if hostgroup.nil? hostgroups = JSON.parse!(response.body).map { |h| h['name'] } else hostgroups = JSON.parse!(response.body).map { |h| h['name'] }.select { |hg| hg == hostgroup } raise NoSuchHostgroupError if hostgroups.empty? end if options[:long] list_hostgroups_with_services(hostgroups) else hostgroups.each { |h| puts h } end end
list_hosts(host, options)
click to toggle source
# File lib/op5util/list_hosts.rb, line 6 def list_hosts(host, options) response = self.class.get(@base_uri + 'config/host?format=json', basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 JSON.parse!(response.body).map { |h| h['name'] }.select { |h| host.nil? ? true : h == host }.each do |h| puts h print_detailed_host_info(h) if options[:long] end end
method_template()
click to toggle source
# File lib/op5util/method_template.rb, line 6 def method_template response = self.class.get(@base_uri + 'some/path?format=json', basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 puts 'Do something' end
schedule_checks(host, options)
click to toggle source
# File lib/op5util/schedule_checks.rb, line 6 def schedule_checks(host, options) schedule_host_check(host) schedule_service_checks_for_host(host, options) end
schedule_downtime(host_string, options)
click to toggle source
# File lib/op5util/schedule_downtime.rb, line 7 def schedule_downtime(host_string, options) host_string.split(',').each do |host| schedule_downtime_for_host(host, options) end end
status_host(host, options)
click to toggle source
# File lib/op5util/status_host.rb, line 8 def status_host(host, options) full_status = JSON.parse!(get_host_status(host)) if options[:short] || (!options[:short] && !options[:long]) print_short_status(full_status) else print_full_status(full_status) end end
status_summary(options)
click to toggle source
# File lib/op5util/status_summary.rb, line 7 def status_summary(options) if options[:long] print_hosts_summary else print_summary end end
Private Instance Methods
ack_host_alarm(host, options)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 46 def ack_host_alarm(host, options) body = ack_host_alarm_body(host, options) response = self.class.post(@base_uri + 'command/ACKNOWLEDGE_HOST_PROBLEM?format=json', headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 puts 'Host alarm acknowledged' end
ack_host_alarm_body(host, options)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 36 def ack_host_alarm_body(host, options) { host_name: host, sticky: true, notify: true, persistent: options[:persistent], comment: options[:comment] }.to_json end
ack_host_service(host, service, options)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 66 def ack_host_service(host, service, options) body = ack_host_service_alarm_body(host, service, options) response = self.class.post(@base_uri + 'command/ACKNOWLEDGE_SVC_PROBLEM?format=json', headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 puts "Alarm for service \"#{service}\" acknowledged" if options[:verbose] end
ack_host_service_alarm_body(host, service, options)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 55 def ack_host_service_alarm_body(host, service, options) { host_name: host, service_description: service, sticky: true, notify: true, persistent: options[:persistent], comment: options[:comment] }.to_json end
add_host_request_body_as_json(host, host_ipaddr, host_alias, contactgroups, hostgroups)
click to toggle source
# File lib/op5util/add_host.rb, line 32 def add_host_request_body_as_json(host, host_ipaddr, host_alias, contactgroups, hostgroups) { file_id: 'etc/hosts.cfg', host_name: host.to_s, address: host_ipaddr.to_s, alias: host_alias.to_s, max_check_attempts: 3, notification_interval: 0, notification_options: %w[d u r], notification_period: '24x7', notifications_enabled: true, template: 'default-host-template', contact_groups: contactgroups, hostgroups: hostgroups }.to_json end
build_add_host_request_body(host, options)
click to toggle source
# File lib/op5util/add_host.rb, line 24 def build_add_host_request_body(host, options) host_ipaddr = options[:ipaddr].nil? ? Resolv.getaddress(host) : options[:ipaddr] host_alias = options[:alias].nil? ? short_name(host) : options[:alias] contactgroups = options[:contactgroups].nil? ? ['support-group'] : options[:contactgroups] hostgroups = options[:hostgroups].nil? ? [] : options[:hostgroups] add_host_request_body_as_json(host, host_ipaddr, host_alias, contactgroups, hostgroups) end
build_host_check_body(host)
click to toggle source
# File lib/op5util/schedule_checks.rb, line 13 def build_host_check_body(host) time = Time.now.to_i { host_name: host, check_time: time }.to_json end
build_schedule_downtime_request_body(host, options)
click to toggle source
# File lib/op5util/schedule_downtime.rb, line 24 def build_schedule_downtime_request_body(host, options) start_time = Time.now.to_i + options[:wait].to_i end_time = start_time + + options[:time].to_i * 3600 + 10 { host_name: host.to_s, start_time: start_time, end_time: end_time, fixed: 1, trigger_id: 0, duration: options[:time].to_i * 3600 + 10, comment: options[:comment] }.to_json end
build_service_check_body(host, service_description)
click to toggle source
# File lib/op5util/schedule_checks.rb, line 53 def build_service_check_body(host, service_description) time = Time.now.to_i { host_name: host, check_time: time, service_description: service_description }.to_json end
count_ok(a)
click to toggle source
# File lib/op5util/status_summary.rb, line 70 def count_ok(a) a[0] - a[1] - a[2] end
do_commit()
click to toggle source
# File lib/op5util/commit.rb, line 23 def do_commit url = @base_uri + 'config/change' response = self.class.post(url, body: {}, basic_auth: @auth, verify: false) raise ApiError, "Response code: #{response.code}, Message: #{response.body}" if response.code != 200 puts 'Op5-config commited' end
fold_string(s, width)
click to toggle source
# File lib/op5util/status_host.rb, line 76 def fold_string(s, width) return nil if s.nil? start_pos = 0 result = '' while start_pos < s.length cut_chars = [width, (s.length - start_pos)].min cut_pos = start_pos + cut_chars - 1 result += s[start_pos..cut_pos] start_pos += cut_chars result += "\n" if start_pos < s.length end result end
get_host_status(host)
click to toggle source
# File lib/op5util/status_host.rb, line 144 def get_host_status(host) response = self.class.get(@base_uri + "status/host/#{host}?format=json", basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 response.body end
get_host_statuses()
click to toggle source
# File lib/op5util/status_summary.rb, line 74 def get_host_statuses host_urls = ['=%5Bhosts%5D%20all', '=%5Bhosts%5D%20acknowledged%20%3D%201', '=%5Bhosts%5D%20state%20!%3D%200%20and%20acknowledged%20%3D%200%20and%20scheduled_downtime_depth%20%3D%200'] host_statuses = [] host_urls.each do |url| response = self.class.get(@base_uri + 'filter/count?query' + url, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 host_statuses << JSON.parse!(response.body)['count'].to_i end host_statuses end
get_hostgroup_members(group)
click to toggle source
# File lib/op5util/add_hostgroups.rb, line 24 def get_hostgroup_members(group) response = self.class.get(@base_uri + "config/hostgroup/#{group}?format=json", basic_auth: @auth, verify: false) raise NoSuchHostgroupError if response.code == 404 JSON.parse!(response.body)['members'] end
get_service_statuses()
click to toggle source
# File lib/op5util/status_summary.rb, line 56 def get_service_statuses service_urls = ['=%5Bservices%5D%20all', '=%5Bservices%5D%20acknowledged%20%3D%201', '=[services] state !%3D 0 and acknowledged %3D 0 and scheduled_downtime_depth %3D 0 and host.scheduled_downtime_depth %3D 0'] service_statuses = [] service_urls.each do |url| response = self.class.get(@base_uri + 'filter/count?query' + url, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 service_statuses << JSON.parse!(response.body)['count'].to_i end service_statuses end
host_exist?(host)
click to toggle source
# File lib/op5util/add_hostgroups.rb, line 31 def host_exist?(host) response = self.class.get(@base_uri + "config/host/#{host}?format=json", basic_auth: @auth, verify: false) raise NoSuchHostError if response.code == 404 raise ApiError if response.code != 200 true end
host_state_to_s(state)
click to toggle source
# File lib/op5util/status_host.rb, line 120 def host_state_to_s(state) case state when 0 'UP'.green when 1 'DOWN'.red.bold else 'UNKNOWN'.white.bold end end
host_status(host)
click to toggle source
# File lib/op5util/acknowledge_alarm.rb, line 75 def host_status(host) response = self.class.get(@base_uri + "status/host/#{host}?format=json", basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 state = JSON.parse!(response.body) { host: state['hard_state'], services: state['services_with_state'].select { |s| s[1] > 0 }.map { |s| s[0] } } end
hostgroup_info(h)
click to toggle source
# File lib/op5util/list_hostgroups.rb, line 26 def hostgroup_info(h) response = self.class.get(@base_uri + "config/hostgroup/#{URI.escape(h)}?format=json", basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 hostgroup = JSON.parse!(response.body) hostgroup['members'].nil? ? '' : members = hostgroup['members'].join(',') max = max_cell_width if hostgroup['services'].nil? services = '' else services = hostgroup['services'].map { |s| fold_string('"' + s['service_description'] + '"', max) }.join("\n") end [members, services] end
hostgroup_services(hg)
click to toggle source
# File lib/op5util/schedule_checks.rb, line 28 def hostgroup_services(hg) response = self.class.get(@base_uri + "config/hostgroup/#{URI.escape(hg)}?format=json", basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 hg_info = JSON.parse!(response.body) hg_info['services'].nil? ? [] : hg_info['services'].map { |s| s['service_description'] } end
list_hostgroups_with_services(hostgroups)
click to toggle source
# File lib/op5util/list_hostgroups.rb, line 50 def list_hostgroups_with_services(hostgroups) max = max_cell_width table = Terminal::Table.new do |t| t.add_row ['Hostgroup'.blue, 'Member hosts'.blue, 'Service checks'.blue] t.add_separator hostgroups.each do |h| (members, services) = hostgroup_info(h) t.add_row [h, fold_string(members, max), services ] end end puts table end
max_cell_width()
click to toggle source
# File lib/op5util/list_hostgroups.rb, line 41 def max_cell_width # The magic number 15 is the size of tables cells padding + the heading 'State' # and a an extra characters for safe layout on narrow terminals, down to # 80 characters width tested. require 'io/console' (_terminal_height, terminal_width) = IO.console.winsize ((terminal_width - 15) / 2).floor end
pending_changes()
click to toggle source
# File lib/op5util/commit.rb, line 16 def pending_changes url = @base_uri + 'config/change' response = self.class.get(url, basic_auth: @auth, verify: false) raise ApiError, "Response code: #{response.code}, Message: #{response.body}" if response.code != 200 JSON.parse!(response.body) end
pp_n_services(n, total = 0)
click to toggle source
# File lib/op5util/status_host.rb, line 112 def pp_n_services(n, total = 0) if n == total || ( total == 0 && n > 0 ) n.to_s.green else n.to_s.red.bold end end
pp_seconds(seconds)
click to toggle source
# File lib/op5util/status_host.rb, line 90 def pp_seconds(seconds) retval = '' s = seconds if s > 86_400 retval = (s / 8600).to_s + ' days, ' s = s % 86_400 end if s > 3600 retval += (s / 3660).to_s + ' hours, ' s = s % 3600 end if s > 60 retval += (s / 60).to_s + ' minutes, ' s = s % 60 end retval += (s % 60).to_s + ' seconds ' end
pp_unixtime_ago(t)
click to toggle source
# File lib/op5util/status_host.rb, line 108 def pp_unixtime_ago(t) pp_seconds(Time.now.to_i - t) end
print_detailed_host_info(host)
click to toggle source
# File lib/op5util/list_hosts.rb, line 18 def print_detailed_host_info(host) response = self.class.get(@base_uri + "config/host/#{host}?format=json", basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 host_info = JSON.parse!(response.body) puts 'Contact-groups: ' + host_info['contact_groups'].join(',') puts 'Host-groups: ' + host_info['hostgroups'].join(',') puts 'Address: ' + host_info['address'] puts 'Alias: ' + host_info['alias'] end
print_full_status(full_status)
click to toggle source
# File lib/op5util/status_host.rb, line 57 def print_full_status(full_status) host_status = "The host #{full_status['name']} is " host_status += host_state_to_s full_status['hard_state'] host_status += ', last check was done ' + pp_unixtime_ago(full_status['last_check']) host_status += " seconds ago.\n" puts host_status max_field_length = max_cell_width table = Terminal::Table.new do |t| t.add_row ['Service'.blue, 'State'.blue, 'Info'.blue] t.add_separator full_status['services'].each do |service| t.add_row [fold_string(service, max_field_length), service_state_to_s(service_state(service, full_status)), fold_string(service_info(service, full_status), max_field_length)] end end puts table end
print_hosts_summary()
click to toggle source
# File lib/op5util/status_summary.rb, line 17 def print_hosts_summary response = self.class.get(@base_uri + 'status/host?format=json', basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 hosts = JSON.parse!(response.body).map { |h| h['name'] } table = Terminal::Table.new do |t| t.add_row ['Host'.blue, 'Host status'.blue, 'Total Services'.blue, 'OK'.green, 'WARN'.yellow, 'CRIT'.red] t.add_separator hosts.each do |h| t.add_row row_for_host(h) end end puts table end
print_short_status(full_status)
click to toggle source
# File lib/op5util/status_host.rb, line 19 def print_short_status(full_status) tot_s = full_status['num_services'].to_s ok_s = full_status['num_services_hard_ok'].to_s mark_ok = tot_s == ok_s warn_s = full_status['num_services_hard_warn'].to_s mark_warn = warn_s != '0' crit_s = full_status['num_services_hard_crit'].to_s mark_crit = crit_s != '0' s = "The host #{full_status['name']} is in " + host_state_to_s(full_status['state'].to_i) s += ' state, and it was last checked ' + pp_unixtime_ago(full_status['last_check']) + "ago.\n" s += 'Out of ' + tot_s.blue.bold + ' services is ' s += pp_n_services(ok_s.to_i, tot_s.to_i) + ' in the ' s += mark_ok ? 'OK'.green : 'OK'.red.bold s += + ' state, ' s += mark_warn ? warn_s.yellow.bold : warn_s s += ' in the ' s += mark_warn ? 'WARN'.yellow.bold : 'WARN' s += + ' state and ' s += mark_crit ? crit_s.red.bold : crit_s s += ' in the ' s += mark_crit ? 'CRIT'.red.bold : 'CRIT' + ' state' puts s end
print_summary()
click to toggle source
# File lib/op5util/status_summary.rb, line 44 def print_summary h = get_host_statuses s = get_service_statuses table = Terminal::Table.new do |t| t.add_row ['', 'Total'.blue, 'OK'.green, 'Acknowledged problems'.yellow, 'Unhandled problems'.red] t.add_separator t.add_row ['Hosts'.blue, h[0].to_s, count_ok(h).to_s.green, h[1].to_s.yellow, h[2].to_s.red ] t.add_row ['Services'.blue, s[0].to_s, count_ok(s).to_s.green, s[1].to_s.yellow, s[2].to_s.red ] end puts table end
row_for_host(host)
click to toggle source
# File lib/op5util/status_summary.rb, line 32 def row_for_host(host) full_status = JSON.parse!(get_host_status(host)) row = [] row << host row << host_state_to_s(full_status['state'].to_i) row << full_status['num_services'].to_s.green row << full_status['num_services_hard_ok'].to_s.green row << full_status['num_services_hard_warn'].to_s.yellow row << full_status['num_services_hard_crit'].to_s.red row end
schedule_downtime_for_host(host, options)
click to toggle source
# File lib/op5util/schedule_downtime.rb, line 15 def schedule_downtime_for_host(host, options) body = build_schedule_downtime_request_body(host, options) response = self.class.post(@base_uri + 'command/SCHEDULE_HOST_DOWNTIME', headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 puts "Downtime Scheduled for host #{host}" end
schedule_host_check(host)
click to toggle source
# File lib/op5util/schedule_checks.rb, line 19 def schedule_host_check(host) body = build_host_check_body(host) response = self.class.post(@base_uri + 'command/SCHEDULE_HOST_CHECK?format=json', headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 puts 'Host check scheduled' end
schedule_service_checks_for_host(host, options)
click to toggle source
# File lib/op5util/schedule_checks.rb, line 60 def schedule_service_checks_for_host(host, options) service_description_for_host(host).each do |s| body = build_service_check_body(host, s) response = self.class.post(@base_uri + 'command/SCHEDULE_SVC_CHECK?format=json', headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 puts "Service check for service \"#{s}\" scheduled" if options[:verbose] end puts "All services for host #{host} scheduled for check" end
service_description_for_host(host)
click to toggle source
TODO: split hostgroup_info
into better re-usable code
# File lib/op5util/schedule_checks.rb, line 37 def service_description_for_host(host) response = self.class.get(@base_uri + "config/host/#{host}?format=json", basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 host_config = JSON.parse!(response.body) if host_config['services'].nil? services = [] else services = host_config['services'].map { |s| s['service_description'] } end host_config['hostgroups'].each do |hg| services += hostgroup_services(hg) end services.nil? ? [] : services end
service_info(service, full_status)
click to toggle source
# File lib/op5util/status_host.rb, line 50 def service_info(service, full_status) full_status['services_with_info'].each do |s| return s[3] if s[0] == service end '' end
service_state(service, full_status)
click to toggle source
# File lib/op5util/status_host.rb, line 43 def service_state(service, full_status) full_status['services_with_state'].each do |s| return s[1] if s[0] == service end '' end
service_state_to_s(state)
click to toggle source
# File lib/op5util/status_host.rb, line 131 def service_state_to_s(state) case state when 0 'OK'.green when 1 'WARN'.yellow.bold when 2 'CRITICAL'.red.bold else 'UNKNOWN'.white.bold end end
short_name(h)
click to toggle source
# File lib/op5util/add_host.rb, line 47 def short_name(h) split_host = h.split('.') if split_host.count > 1 split_host[0] else '' end end
update_hostgroup(hostgroup, members)
click to toggle source
# File lib/op5util/add_hostgroups.rb, line 39 def update_hostgroup(hostgroup, members) body = { file_id: 'etc/hostgroups.cfg', hostgroup_name: hostgroup.to_s, members: members }.to_json response = self.class.patch(@base_uri + "config/hostgroup/#{hostgroup}", headers: { 'Content-Type' => 'application/json' }, body: body, basic_auth: @auth, verify: false) raise ApiError unless response.code == 200 end