scout 5.2.2 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,4 +1,9 @@
1
- == 5.2.2
1
+ == 5.3.0
2
+
3
+ * Ping over http instead of https. All plan retrievals and check-ins are still SSL
4
+ * Added ability to post troubleshooting report back to scoutapp.com
5
+
6
+ == 5.2.2
2
7
 
3
8
  * More graceful handling of *rare* client_history.yaml corruption
4
9
 
data/lib/scout.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby -wKU
2
2
 
3
3
  module Scout
4
- VERSION = "5.2.2".freeze
4
+ VERSION = "5.3.0".freeze
5
5
  end
6
6
 
7
7
  require "scout/command"
data/lib/scout/command.rb CHANGED
@@ -37,8 +37,8 @@ module Scout
37
37
  opts.separator " ... OR ..."
38
38
  opts.separator " #{program_name} [OPTIONS] install"
39
39
  opts.separator " Troubleshoot:"
40
- opts.separator " #{program_name} troubleshoot"
41
- opts.separator " ... print Scout environment info. Recommend directing output to a file."
40
+ opts.separator " #{program_name} [OPTIONS] troubleshoot"
41
+ opts.separator " ... print troubleshooting info, or post it back to scoutapp.com."
42
42
  opts.separator " Local plugin testing:"
43
43
  opts.separator " #{program_name} [OPTIONS] test " +
44
44
  "PATH_TO_PLUGIN [PLUGIN_OPTIONS]"
@@ -88,6 +88,16 @@ module Scout
88
88
  options[:force] = bool
89
89
  end
90
90
 
91
+ opts.separator " "
92
+ opts.separator "Troubleshooting Options:"
93
+ opts.separator "--------------------------------------------------------------------------"
94
+ opts.on( "--post", "For use with 'troubleshoot' - post the troubleshooting results back to scoutapp.com") do
95
+ options[:troubleshoot_post] = true
96
+ end
97
+ opts.on( "--no-history", "For use with 'troubleshoot' - don't include the history file contents.") do
98
+ options[:troubleshoot_no_history] = true
99
+ end
100
+
91
101
  opts.separator " "
92
102
  opts.separator "Examples: "
93
103
  opts.separator "--------------------------------------------------------------------------"
@@ -1,12 +1,25 @@
1
1
  #!/usr/bin/env ruby -wKU
2
2
 
3
- require "pp"
3
+ require "uri"
4
+ require "socket"
5
+ require "net/https"
6
+ require "timeout"
7
+
4
8
 
5
9
  module Scout
6
10
  class Command
11
+ class APITimeoutError < RuntimeError; end
12
+
13
+ HTTP_HEADERS = { "Client-Version" => Scout::VERSION,
14
+ "Client-Hostname" => Socket.gethostname}
15
+
7
16
  class Troubleshoot < Command
17
+
8
18
  def initialize(options, args)
19
+ @post = options[:troubleshoot_post]
20
+ @include_history = !options[:troubleshoot_no_history]
9
21
  @contents=[]
22
+ options[:verbose]=true # force verbose logging for this command
10
23
  super
11
24
  end
12
25
 
@@ -32,19 +45,31 @@ module Scout
32
45
  heading "Installed Gems"
33
46
  text `gem list --local`
34
47
 
35
- heading "History file Contents"
36
- contents=File.read(history) rescue "History not found at #{log_path}"
37
- text contents
48
+
49
+ if @include_history
50
+ heading "History file Contents"
51
+ contents=File.read(history) rescue "History not found at #{log_path}"
52
+ text contents
53
+ else
54
+ heading "Skipping History file Contents"
55
+ end
38
56
 
39
57
  heading "Agent directory Contents"
40
58
  text `ls -la #{config_dir}`
41
59
 
42
60
  heading ""
43
61
 
44
- puts "Done"
45
-
46
- puts @contents.join("\n")
47
-
62
+ if @post
63
+ puts "Posting troubleshooting info to #{@server} ... "
64
+ url = URI.join( @server,"/admin/troubleshooting_reports")
65
+ post_form(url, "Couldn't contact server at #{@server}",{:body=>contents_as_text}) do |res|
66
+ puts "Scout server says: \"#{res.body}\""
67
+ end
68
+ else
69
+ puts contents_as_text
70
+ end
71
+
72
+ puts " ... Done"
48
73
  end
49
74
  end
50
75
 
@@ -61,5 +86,57 @@ module Scout
61
86
  @contents << s
62
87
  end
63
88
 
89
+ def contents_as_text
90
+ @contents.join("\n")
91
+ end
92
+
93
+ def post_form(url, error, form_data, headers = Hash.new, &response_handler)
94
+ return unless url
95
+ request(url, response_handler, error) do |connection|
96
+ post = Net::HTTP::Post.new( url.path +
97
+ (url.query ? ('?' + url.query) : ''),
98
+ HTTP_HEADERS.merge(headers) )
99
+ post.set_form_data(form_data)
100
+ connection.request(post)
101
+ end
102
+ end
103
+
104
+ def request(url, response_handler, error, &connector)
105
+ response = nil
106
+ Timeout.timeout(5 * 60, APITimeoutError) do
107
+ http = Net::HTTP.new(url.host, url.port)
108
+ if url.is_a? URI::HTTPS
109
+ http.use_ssl = true
110
+ http.ca_file = File.join( File.dirname(__FILE__),
111
+ *%w[.. .. data cacert.pem] )
112
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER |
113
+ OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
114
+ end
115
+ response = no_warnings { http.start(&connector) }
116
+ end
117
+ case response
118
+ when Net::HTTPSuccess, Net::HTTPNotModified
119
+ response_handler[response] unless response_handler.nil?
120
+ else
121
+ error = "Server says: #{response['x-scout-msg']}" if response['x-scout-msg']
122
+ log.fatal error
123
+ raise SystemExit.new(error)
124
+ end
125
+ rescue Timeout::Error
126
+ log.fatal "Request timed out."
127
+ exit
128
+ rescue Exception
129
+ raise if $!.is_a? SystemExit
130
+ log.fatal "An HTTP error occurred: #{$!.message}"
131
+ exit
132
+ end
133
+
134
+ def no_warnings
135
+ old_verbose = $VERBOSE
136
+ $VERBOSE = false
137
+ yield
138
+ ensure
139
+ $VERBOSE = old_verbose
140
+ end
64
141
  end
65
142
  end
data/lib/scout/server.rb CHANGED
@@ -62,6 +62,26 @@ module Scout
62
62
  end
63
63
  end
64
64
 
65
+ def refresh?
66
+ return true if !ping_key
67
+
68
+ url=URI.join( @server.sub("https://","http://"), "/clients/#{ping_key}/ping.scout")
69
+
70
+ headers = {"x-scout-tty" => ($stdin.tty? ? 'true' : 'false')}
71
+ if @history["plan_last_modified"] and @history["old_plugins"]
72
+ headers["If-Modified-Since"] = @history["plan_last_modified"]
73
+ end
74
+ get(url, "Could not ping #{url} for refresh info", headers) do |res|
75
+ if res.is_a?(Net::HTTPNotModified)
76
+ return false
77
+ else
78
+ info "Plan has been modified!"
79
+ return true
80
+ end
81
+ end
82
+ end
83
+
84
+
65
85
  #
66
86
  # Retrieves the Plugin Plan from the server. This is the list of plugins
67
87
  # to execute, along with all options.
@@ -70,23 +90,13 @@ module Scout
70
90
  # 1) it sets the @plugin_plan with either A) whatever is in history, B) the results of the /plan retrieval
71
91
  # 2) it sets @checkin_to = true IF so directed by the scout server
72
92
  def fetch_plan
73
- url = urlify(:plan)
74
- info "Pinging server at #{url}..."
75
- headers = {"x-scout-tty" => ($stdin.tty? ? 'true' : 'false')}
93
+ if refresh?
76
94
 
77
- if @history["plan_last_modified"] and @history["old_plugins"]
78
- headers["If-Modified-Since"] = @history["plan_last_modified"]
79
- end
80
- get(url, "Could not retrieve plan from server.", headers) do |res|
81
- if res.is_a? Net::HTTPNotModified
82
- info "Plan not modified. Will reuse saved plan."
83
- @plugin_plan = Array(@history["old_plugins"])
84
- # Add local plugins to the plan. Note that local plugins are NOT saved to history file
85
- @plugin_plan += get_local_plugins
86
- @directives = @history["directives"] || Hash.new
95
+ url = urlify(:plan)
96
+ info "Fetching plan from server at #{url}..."
97
+ headers = {"x-scout-tty" => ($stdin.tty? ? 'true' : 'false')}
87
98
 
88
- else
89
- info "plan has been modified. Will run the new plan now."
99
+ get(url, "Could not retrieve plan from server.", headers) do |res|
90
100
  begin
91
101
  body = res.body
92
102
  if res["Content-Encoding"] == "gzip" and body and not body.empty?
@@ -144,6 +154,11 @@ module Scout
144
154
  exit
145
155
  end
146
156
  end
157
+ else
158
+ info "Plan not modified."
159
+ @plugin_plan = Array(@history["old_plugins"])
160
+ @plugin_plan += get_local_plugins
161
+ @directives = @history["directives"] || Hash.new
147
162
  end
148
163
  end
149
164
 
@@ -174,6 +189,10 @@ module Scout
174
189
  (@history['directives'] || {})['sleep_interval'].to_f
175
190
  end
176
191
 
192
+ def ping_key
193
+ (@history['directives'] || {})['ping_key']
194
+ end
195
+
177
196
  # uses values from history and current time to determine if we should checkin at this time
178
197
  def time_to_checkin?
179
198
  @history['last_checkin'] == nil ||
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease: false
6
6
  segments:
7
7
  - 5
8
- - 2
9
- - 2
10
- version: 5.2.2
8
+ - 3
9
+ - 0
10
+ version: 5.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Scout Monitoring
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-01 00:00:00 -08:00
18
+ date: 2011-03-07 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency