sensu-cli 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +127 -0
- data/bin/sensu +8 -0
- data/lib/sensu-cli.rb +2 -0
- data/lib/sensu-cli/cli.rb +289 -0
- data/lib/sensu-cli/sensu.rb +165 -0
- data/lib/sensu-cli/settings.rb +24 -0
- data/lib/sensu-cli/version.rb +3 -0
- data/sensu-cli.gemspec +22 -0
- data/settings.example.rb +3 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDRkNzYxOGQyMmRkM2QzMjZhMmFhNDAyYjRjYWYzNWNkYmJmYWYyYg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YjA0OGMyMTk2YjI4MTkyNjc1YmUwZTU3ZDQ1OWE5YTI2MjllZjMyMA==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZTU0MTUxMjk5ODY0YjkxZDQ5ODY5ZjYxOGMzOWY1ZWFlOTZlZWY4NjFjMmFh
|
10
|
+
ODQ1MGYyNDk2ZTZiMDJhNDIwZTY4MzZhODJmMmNiYzQwZWQxOTg5OTgzNjRh
|
11
|
+
OTAwNmNhY2M1N2YyN2FiNmY1OGEzNTk3NjcwNjhhMzNjMGIxMGM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzY1ZjEyNzRjZjEzOGRhYmIwZjcxM2Q2Mzk0OWU1NjU0MTFiYjc2YzY3YWFm
|
14
|
+
NDZiMjEyNGY1NjQ3NTMwOWFiYzI4ZTdhYjNhNzY1YTg2OGNkZmJiY2IxN2Mw
|
15
|
+
YjVjMDY3OGE4YzIyYmY3OTY2OTJjODBhNjMyZDVhNWMzYThlNGE=
|
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
sensu-cli
|
2
|
+
=========
|
3
|
+
```
|
4
|
+
#
|
5
|
+
# Welcome to the sensu-cli.
|
6
|
+
# ______
|
7
|
+
# .-' '-.
|
8
|
+
# .' __ '.
|
9
|
+
# / / \ \
|
10
|
+
# ------------------
|
11
|
+
# /\
|
12
|
+
# '--'
|
13
|
+
# SENSU
|
14
|
+
#
|
15
|
+
```
|
16
|
+
A sensu-cli for interacting with the sensu api.
|
17
|
+
|
18
|
+
What is Sensu? http://sensuapp.org/
|
19
|
+
|
20
|
+
Features
|
21
|
+
--------
|
22
|
+
* API interaction with info, health, stashes, events, clients, aggregates and checks
|
23
|
+
* Resolve Events
|
24
|
+
* Silence clients and checks
|
25
|
+
* Get Requests (get clients, stashes, events, etc.)
|
26
|
+
* Delete Requests (delete clients, stashes and events)
|
27
|
+
|
28
|
+
|
29
|
+
Usage and Configuration
|
30
|
+
-----------------------
|
31
|
+
* gem build sensu-cli.gemspec
|
32
|
+
* gem install ./{gem file created}
|
33
|
+
|
34
|
+
* There is one settings file for host, port and ssl that lives in your user directory ~/.sensu/settings.rb. You can alternatively place this in /etc/sensu/sensu-cli/settings.rb.
|
35
|
+
|
36
|
+
````
|
37
|
+
host "127.0.0.1"
|
38
|
+
port "4567"
|
39
|
+
ssl false
|
40
|
+
````
|
41
|
+
This format was chosen so you can do some ENV magic via your profile and setting up an alias. For details see the [wiki](https://github.com/agent462/sensu-cli/wiki)
|
42
|
+
|
43
|
+
* If your Sensu API has basic auth, add the parameters to the config.
|
44
|
+
|
45
|
+
````
|
46
|
+
host "127.0.0.1"
|
47
|
+
port "4567"
|
48
|
+
ssl false
|
49
|
+
user "some_user"
|
50
|
+
password "some_secret_password"
|
51
|
+
````
|
52
|
+
|
53
|
+
|
54
|
+
Examples
|
55
|
+
-----------
|
56
|
+
````
|
57
|
+
Available subcommands: (for details, sensu SUB-COMMAND --help)
|
58
|
+
|
59
|
+
** Aggregate Commands **
|
60
|
+
sensu aggregate list (OPTIONS)
|
61
|
+
sensu aggregate show CHECK
|
62
|
+
|
63
|
+
** Check Commands **
|
64
|
+
sensu check list
|
65
|
+
sensu check show CHECK
|
66
|
+
sensu check request CHECK SUB1,SUB2
|
67
|
+
|
68
|
+
** Client Commands **
|
69
|
+
sensu client list (OPTIONS)
|
70
|
+
sensu client show NODE
|
71
|
+
sensu client delete NODE
|
72
|
+
sensu client history NODE
|
73
|
+
|
74
|
+
** Event Commands **
|
75
|
+
sensu event list
|
76
|
+
sensu event show NODE (OPTIONS)
|
77
|
+
sensu event delete NODE CHECK
|
78
|
+
|
79
|
+
** Health Commands **
|
80
|
+
sensu health (OPTIONS)
|
81
|
+
|
82
|
+
** Info Commands **
|
83
|
+
sensu info
|
84
|
+
|
85
|
+
** Silence Commands **
|
86
|
+
sensu silence NODE (OPTIONS)
|
87
|
+
|
88
|
+
** Stash Commands **
|
89
|
+
sensu stash list (OPTIONS)
|
90
|
+
sensu stash show STASHPATH
|
91
|
+
sensu stash delete STASHPATH
|
92
|
+
|
93
|
+
** Resolve Commands **
|
94
|
+
sensu resolve NODE CHECK
|
95
|
+
|
96
|
+
--version, -v: Print version and exit
|
97
|
+
--help, -h: Show this message
|
98
|
+
````
|
99
|
+
|
100
|
+
Contributions
|
101
|
+
-------------
|
102
|
+
Please provide a pull request. I'm an ops guy, not a developer, so if you're submitting code cleanup, all I ask is that you explain the improvement so I can learn.
|
103
|
+
|
104
|
+
TODO
|
105
|
+
----
|
106
|
+
* support deletion of aggregate check
|
107
|
+
* cleanup the cli
|
108
|
+
* Once complete api support is implemented I'll add other features like filtering or issuing a event.
|
109
|
+
|
110
|
+
License and Author
|
111
|
+
==================
|
112
|
+
|
113
|
+
Author:: Bryan Brandau <agent462@gmail.com>
|
114
|
+
|
115
|
+
Copyright:: 2013, Bryan Brandau
|
116
|
+
|
117
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
118
|
+
you may not use this file except in compliance with the License.
|
119
|
+
You may obtain a copy of the License at
|
120
|
+
|
121
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
122
|
+
|
123
|
+
Unless required by applicable law or agreed to in writing, software
|
124
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
125
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
126
|
+
See the License for the specific language governing permissions and
|
127
|
+
limitations under the License.
|
data/bin/sensu
ADDED
data/lib/sensu-cli.rb
ADDED
@@ -0,0 +1,289 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
require 'sensu-cli/version'
|
3
|
+
|
4
|
+
module SensuCli
|
5
|
+
class Cli
|
6
|
+
SUB_COMMANDS = %w(info client check event stash aggregate silence resolve health)
|
7
|
+
CLIENT_COMMANDS = %w(list show delete history)
|
8
|
+
CHECK_COMMANDS = %w(list show request)
|
9
|
+
EVENT_COMMANDS = %w(list show delete)
|
10
|
+
STASH_COMMANDS = %w(list show delete)
|
11
|
+
AGG_COMMANDS = %w(list show)
|
12
|
+
SIL_COMMANDS = ""
|
13
|
+
RES_COMMANDS = ""
|
14
|
+
INFO_COMMANDS = ""
|
15
|
+
HEALTH_COMMANDS = ""
|
16
|
+
|
17
|
+
CLIENT_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
18
|
+
** Client Commands **
|
19
|
+
sensu client list (OPTIONS)
|
20
|
+
sensu client show NODE
|
21
|
+
sensu client delete NODE
|
22
|
+
sensu client history NODE\n\r
|
23
|
+
EOS
|
24
|
+
INFO_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
25
|
+
** Info Commands **
|
26
|
+
sensu info\n\r
|
27
|
+
EOS
|
28
|
+
HEALTH_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
29
|
+
** Health Commands **
|
30
|
+
sensu health (OPTIONS)\n\r
|
31
|
+
EOS
|
32
|
+
CHECK_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
33
|
+
** Check Commands **
|
34
|
+
sensu check list
|
35
|
+
sensu check show CHECK
|
36
|
+
sensu check request CHECK SUB1,SUB2\n\r
|
37
|
+
EOS
|
38
|
+
EVENT_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
39
|
+
** Event Commands **
|
40
|
+
sensu event list
|
41
|
+
sensu event show NODE (OPTIONS)
|
42
|
+
sensu event delete NODE CHECK\n\r
|
43
|
+
EOS
|
44
|
+
STASH_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
45
|
+
** Stash Commands **
|
46
|
+
sensu stash list (OPTIONS)
|
47
|
+
sensu stash show STASHPATH
|
48
|
+
sensu stash delete STASHPATH\n\r
|
49
|
+
EOS
|
50
|
+
#sensu stash create
|
51
|
+
#apost '/stashes'
|
52
|
+
AGG_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
53
|
+
** Aggregate Commands **
|
54
|
+
sensu aggregate list (OPTIONS)
|
55
|
+
sensu aggregate show CHECK\n\r
|
56
|
+
EOS
|
57
|
+
#sensu aggregate delete CHECK\n\r
|
58
|
+
#aget %r{/aggregates?/([\w\.-]+)/([\w\.-]+)$} do |check_name, check_issued|
|
59
|
+
SIL_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
60
|
+
** Silence Commands **
|
61
|
+
sensu silence NODE (OPTIONS)\n\r
|
62
|
+
EOS
|
63
|
+
RES_BANNER = <<-EOS.gsub(/^ {10}/, '')
|
64
|
+
** Resolve Commands **
|
65
|
+
sensu resolve NODE CHECK\n\r
|
66
|
+
EOS
|
67
|
+
|
68
|
+
def global
|
69
|
+
global_opts = Trollop::Parser.new do
|
70
|
+
version "sensu-cli version: #{SensuCli::VERSION}"
|
71
|
+
banner <<-'EOS'.gsub(/^ {10}/, '')
|
72
|
+
#
|
73
|
+
# Welcome to the sensu-cli.
|
74
|
+
# ______
|
75
|
+
# .-' '-.
|
76
|
+
# .' __ '.
|
77
|
+
# / / \ \
|
78
|
+
# ------------------
|
79
|
+
# /\
|
80
|
+
# '--'
|
81
|
+
# SENSU
|
82
|
+
#
|
83
|
+
EOS
|
84
|
+
banner "\n\rAvailable subcommands: (for details, sensu SUB-COMMAND --help)\n\r"
|
85
|
+
banner AGG_BANNER
|
86
|
+
banner CHECK_BANNER
|
87
|
+
banner CLIENT_BANNER
|
88
|
+
banner EVENT_BANNER
|
89
|
+
banner HEALTH_BANNER
|
90
|
+
banner INFO_BANNER
|
91
|
+
banner SIL_BANNER
|
92
|
+
banner STASH_BANNER
|
93
|
+
banner RES_BANNER
|
94
|
+
stop_on SUB_COMMANDS
|
95
|
+
end
|
96
|
+
|
97
|
+
opts = Trollop::with_standard_exception_handling global_opts do
|
98
|
+
global_opts.parse ARGV
|
99
|
+
raise Trollop::HelpNeeded if ARGV.empty? # show help screen
|
100
|
+
end
|
101
|
+
|
102
|
+
cmd = next_argv
|
103
|
+
self.respond_to?(cmd) ? send(cmd) : explode(global_opts)
|
104
|
+
end
|
105
|
+
|
106
|
+
def explode(opts)
|
107
|
+
explode = Trollop::with_standard_exception_handling opts do
|
108
|
+
raise Trollop::HelpNeeded # show help screen
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def deep_merge(hash_one, hash_two)
|
113
|
+
hash_one.merge(hash_two) {|key, hash_one_item, hash_two_item| deep_merge(hash_one_item, hash_two_item)}
|
114
|
+
end
|
115
|
+
|
116
|
+
def parser(cli)
|
117
|
+
opts = Trollop::Parser.new do
|
118
|
+
banner Cli.const_get("#{cli}_BANNER")
|
119
|
+
stop_on Cli.const_get("#{cli}_COMMANDS")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def explode_if_empty(opts,command)
|
124
|
+
explode(opts) if ARGV.empty? && command != 'list'
|
125
|
+
end
|
126
|
+
|
127
|
+
def next_argv
|
128
|
+
ARGV.shift
|
129
|
+
end
|
130
|
+
|
131
|
+
def client
|
132
|
+
opts = parser("CLIENT")
|
133
|
+
command = next_argv
|
134
|
+
explode_if_empty(opts,command)
|
135
|
+
case command
|
136
|
+
when 'list'
|
137
|
+
p = Trollop::options do
|
138
|
+
opt :limit, "The number if clients to return", :short => "l", :type => :string
|
139
|
+
opt :offset, "The number of clients to offset before returning", :short => "o", :type => :string
|
140
|
+
end
|
141
|
+
Trollop::die :offset, "Offset depends on the limit option --limit ( -l )".color(:red) if p[:offset] && !p[:limit]
|
142
|
+
cli = {:command => 'clients', :method => 'Get', :fields => p}
|
143
|
+
when 'delete'
|
144
|
+
p = Trollop::options
|
145
|
+
item = next_argv #the ARGV.shift needs to happen after Trollop::options to catch --help
|
146
|
+
deep_merge({:command => 'clients', :method => 'Delete', :fields => {:name => item}},{:fields => p})
|
147
|
+
when 'show'
|
148
|
+
p = Trollop::options
|
149
|
+
item = next_argv
|
150
|
+
deep_merge({:command => 'clients', :method => 'Get', :fields => {:name => item}},{:fields => p})
|
151
|
+
when 'history'
|
152
|
+
p = Trollop::options
|
153
|
+
item = next_argv
|
154
|
+
deep_merge({:command => 'clients', :method => 'Get', :fields => {:name => item, :history => true}},{:fields => p})
|
155
|
+
else
|
156
|
+
explode(opts)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def info
|
161
|
+
parser("INFO")
|
162
|
+
p = Trollop::options
|
163
|
+
cli = {:command => 'info', :method => 'Get', :fields => p}
|
164
|
+
end
|
165
|
+
|
166
|
+
def health
|
167
|
+
opts = parser("HEALTH")
|
168
|
+
p = Trollop::options do
|
169
|
+
opt :consumers, "The minimum number of consumers", :short => "c", :type => :string, :required => true
|
170
|
+
opt :messages, "The maximum number of messages", :short => "m", :type => :string, :required => true
|
171
|
+
end
|
172
|
+
cli = {:command => 'health', :method => 'Get', :fields => p}
|
173
|
+
end
|
174
|
+
|
175
|
+
def check
|
176
|
+
opts = parser("CHECK")
|
177
|
+
command = next_argv
|
178
|
+
explode_if_empty(opts,command)
|
179
|
+
p = Trollop::options
|
180
|
+
item = next_argv
|
181
|
+
case command
|
182
|
+
when 'list'
|
183
|
+
cli = {:command => 'checks', :method => 'Get', :fields => p}
|
184
|
+
when 'show'
|
185
|
+
deep_merge({:command => 'checks', :method => 'Get', :fields => {:name => item}},{:fields => p})
|
186
|
+
when 'request'
|
187
|
+
ARGV.empty? ? explode(opts) : subscribers = next_argv.split(",")
|
188
|
+
deep_merge({:command => 'checks', :method => 'Post', :fields => {:check => item, :subscribers => subscribers}},{:fields => p})
|
189
|
+
else
|
190
|
+
explode(opts)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def event
|
195
|
+
opts = parser("EVENT")
|
196
|
+
command = next_argv
|
197
|
+
explode_if_empty(opts,command)
|
198
|
+
case command
|
199
|
+
when 'list'
|
200
|
+
p = Trollop::options
|
201
|
+
cli = {:command => 'events', :method => 'Get', :fields => p}
|
202
|
+
when 'show'
|
203
|
+
p = Trollop::options do
|
204
|
+
opt :check, "Returns the check associated with the client", :short => "k", :type => :string
|
205
|
+
end
|
206
|
+
item = next_argv
|
207
|
+
deep_merge({:command => 'events', :method => 'Get', :fields => {:client => item}},{:fields => p})
|
208
|
+
when 'delete'
|
209
|
+
p = Trollop::options
|
210
|
+
item = next_argv
|
211
|
+
check = next_argv
|
212
|
+
explode(opts) if check == nil
|
213
|
+
deep_merge({:command => 'events', :method => 'Delete', :fields => {:client => item, :check => check}},{:fields => p})
|
214
|
+
else
|
215
|
+
explode(opts)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def stash
|
220
|
+
opts = parser("STASH")
|
221
|
+
command = next_argv
|
222
|
+
explode_if_empty(opts,command)
|
223
|
+
case command
|
224
|
+
when 'list'
|
225
|
+
p = Trollop::options do
|
226
|
+
opt :limit, "The number of stashes to return", :short => "l", :type => :string
|
227
|
+
opt :offset, "The number of stashes to offset before returning", :short => "o", :type => :string
|
228
|
+
end
|
229
|
+
Trollop::die :offset, "Offset depends on the limit option --limit ( -l )".color(:red) if p[:offset] && !p[:limit]
|
230
|
+
cli = {:command => 'stashes', :method => 'Get', :fields => p}
|
231
|
+
when 'show'
|
232
|
+
p = Trollop::options
|
233
|
+
item = next_argv
|
234
|
+
deep_merge({:command => 'stashes', :method => 'Get', :fields => {:path => item}},{:fields => p})
|
235
|
+
when 'delete'
|
236
|
+
p = Trollop::options
|
237
|
+
item = next_argv
|
238
|
+
deep_merge({:command => 'stashes', :method => 'Delete', :fields => {:path => item}},{:fields => p})
|
239
|
+
else
|
240
|
+
explode(opts)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def aggregate
|
245
|
+
opts = parser("AGG")
|
246
|
+
command = next_argv
|
247
|
+
explode_if_empty(opts,command)
|
248
|
+
case command
|
249
|
+
when 'list'
|
250
|
+
p = Trollop::options
|
251
|
+
cli = {:command => 'aggregates', :method => 'Get', :fields => p}
|
252
|
+
when 'show'
|
253
|
+
p = Trollop::options do
|
254
|
+
opt :limit, "The number of aggregates to return", :short => "l", :type => :string
|
255
|
+
opt :offset, "The number of aggregates to offset before returning", :short => "o", :type => :string
|
256
|
+
end
|
257
|
+
Trollop::die :offset, "Offset depends on the limit option --limit ( -l )".color(:red) if p[:offset] && !p[:limit]
|
258
|
+
item = next_argv
|
259
|
+
deep_merge({:command => 'aggregates', :method => 'Get', :fields => {:check => item}},{:fields => p})
|
260
|
+
when 'delete'
|
261
|
+
p = Trollop::options
|
262
|
+
item = next_argv
|
263
|
+
deep_merge({:command => 'aggregates', :method => 'Delete', :fields => {:check => item}},{:fields => p})
|
264
|
+
else
|
265
|
+
explode(opts)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def silence
|
270
|
+
opts = parser("SIL")
|
271
|
+
p = Trollop::options do
|
272
|
+
opt :check, "The check to silence (requires --client)", :short => 'k', :type => :string
|
273
|
+
opt :reason, "The reason this check/node is being silenced", :short => 'r', :type => :string
|
274
|
+
end
|
275
|
+
command = next_argv
|
276
|
+
explode(opts) if command == nil
|
277
|
+
deep_merge({:command => 'silence', :method => 'Post', :fields => {:client => command}},{:fields => p})
|
278
|
+
end
|
279
|
+
|
280
|
+
def resolve
|
281
|
+
opts = parser("RES")
|
282
|
+
command = next_argv
|
283
|
+
p = Trollop::options
|
284
|
+
ARGV.empty? ? explode(opts) : check = next_argv
|
285
|
+
deep_merge({:command => 'resolve', :method => 'Post', :fields => {:client => command, :check => check}},{:fields => p})
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'rubygems' if RUBY_VERSION < '1.9.0'
|
2
|
+
require 'net/https'
|
3
|
+
require 'json'
|
4
|
+
require 'sensu-cli/settings'
|
5
|
+
require 'sensu-cli/cli'
|
6
|
+
require 'rainbow'
|
7
|
+
|
8
|
+
module SensuCli
|
9
|
+
class Core
|
10
|
+
|
11
|
+
def setup
|
12
|
+
clis = Cli.new
|
13
|
+
cli = clis.global
|
14
|
+
settings
|
15
|
+
api_path(cli)
|
16
|
+
make_call
|
17
|
+
end
|
18
|
+
|
19
|
+
def settings
|
20
|
+
directory = "#{Dir.home}/.sensu"
|
21
|
+
file = "#{directory}/settings.rb"
|
22
|
+
alt = "/etc/sensu/sensu-cli/settings.rb"
|
23
|
+
settings = Settings.new
|
24
|
+
if settings.is_file?(file)
|
25
|
+
SensuCli::Config.from_file(file)
|
26
|
+
elsif settings.is_file?(alt)
|
27
|
+
SensuCli::Config.from_file(alt)
|
28
|
+
else
|
29
|
+
settings.create(directory,file)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def api_path(cli)
|
34
|
+
@command = cli[:command]
|
35
|
+
case @command
|
36
|
+
when 'clients'
|
37
|
+
path = "/clients" << (cli[:fields][:name] ? "/#{cli[:fields][:name]}" : "") << (cli[:fields][:history] ? "/history" : "")
|
38
|
+
when 'info'
|
39
|
+
path = "/info"
|
40
|
+
when 'health'
|
41
|
+
path = "/health?consumers=#{cli[:fields][:consumers]}&messages=#{cli[:fields][:messages]}"
|
42
|
+
when 'stashes'
|
43
|
+
path = "/stashes" << (cli[:fields][:path] ? "/#{cli[:fields][:path]}" : "")
|
44
|
+
when 'checks'
|
45
|
+
if cli[:fields][:name]
|
46
|
+
path = "/check/#{cli[:fields][:name]}"
|
47
|
+
elsif cli[:fields][:subscribers]
|
48
|
+
path = "/check/request"
|
49
|
+
payload = {:check => cli[:fields][:check],:subscribers => cli[:fields][:subscribers]}.to_json
|
50
|
+
else
|
51
|
+
path = "/checks"
|
52
|
+
end
|
53
|
+
when 'events'
|
54
|
+
path = "/events" << (cli[:fields][:client] ? "/#{cli[:fields][:client]}" : "") << (cli[:fields][:check] ? "/#{cli[:fields][:check]}" : "")
|
55
|
+
when 'resolve'
|
56
|
+
payload = {:client => cli[:fields][:client], :check => cli[:fields][:check]}.to_json
|
57
|
+
path = "/event/resolve"
|
58
|
+
when 'silence'
|
59
|
+
cli[:fields][:reason] ? payload = ({:reason => cli[:fields][:reason],:timestamp => Time.now.to_i}).to_json : payload = {:timestamp => Time.now.to_i}.to_json
|
60
|
+
path = "/stashes/silence" << (cli[:fields][:client] ? "/#{cli[:fields][:client]}" : "") << (cli[:fields][:check] ? "/#{cli[:fields][:check]}" : "")
|
61
|
+
when 'aggregates'
|
62
|
+
path = "/aggregates" << (cli[:fields][:check] ? "/#{cli[:fields][:check]}" : "")
|
63
|
+
end
|
64
|
+
path << pagination(cli) if ["stashes","clients","aggregates"].include?(@command)
|
65
|
+
@api = {:path => path, :method => cli[:method], :command => cli[:command], :payload => (payload || false)}
|
66
|
+
end
|
67
|
+
|
68
|
+
def pagination(cli)
|
69
|
+
if cli[:fields].has_key?(:limit) && cli[:fields].has_key?(:offset)
|
70
|
+
page = "?limit=#{cli[:fields][:limit]}&offset=#{cli[:fields][:offset]}"
|
71
|
+
elsif cli[:fields].has_key?(:limit)
|
72
|
+
page = "?limit=#{cli[:fields][:limit]}"
|
73
|
+
else
|
74
|
+
page = ""
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def http_request
|
79
|
+
http = Net::HTTP.new(Config.host, Config.port)
|
80
|
+
http.read_timeout = 15
|
81
|
+
http.open_timeout = 5
|
82
|
+
if Config.ssl
|
83
|
+
http.use_ssl = true
|
84
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
85
|
+
end
|
86
|
+
case @api[:method]
|
87
|
+
when 'Get'
|
88
|
+
req = Net::HTTP::Get.new(@api[:path])
|
89
|
+
when 'Delete'
|
90
|
+
req = Net::HTTP::Delete.new(@api[:path])
|
91
|
+
when 'Post'
|
92
|
+
req = Net::HTTP::Post.new(@api[:path],initheader = {'Content-Type' =>'application/json'})
|
93
|
+
req.body = @api[:payload]
|
94
|
+
end
|
95
|
+
req.basic_auth(Config.user, Config.password) if Config.user && Config.password
|
96
|
+
begin
|
97
|
+
http.request(req)
|
98
|
+
rescue Timeout::Error
|
99
|
+
puts "HTTP request has timed out.".color(:red)
|
100
|
+
exit
|
101
|
+
rescue StandardError => e
|
102
|
+
puts "An HTTP error occurred. Check your settings. #{e}".color(:red)
|
103
|
+
exit
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def make_call
|
108
|
+
res = http_request
|
109
|
+
msg = response_codes(res.code,res.body)
|
110
|
+
res.code != '200' ? exit : pretty(msg)
|
111
|
+
count(msg)
|
112
|
+
end
|
113
|
+
|
114
|
+
def response_codes(code,body)
|
115
|
+
case code
|
116
|
+
when '200'
|
117
|
+
JSON.parse(body)
|
118
|
+
when '201'
|
119
|
+
puts "The stash has been created." if @command == "stashes"
|
120
|
+
when '202'
|
121
|
+
puts "The item was submitted for processing."
|
122
|
+
when '204'
|
123
|
+
puts "Sensu is healthy" if @command == 'health'
|
124
|
+
puts "The item was successfully deleted." if @command == 'aggregates' || @command == 'stashes'
|
125
|
+
when '400'
|
126
|
+
puts "The payload is malformed.".color(:red)
|
127
|
+
when '401'
|
128
|
+
puts "The request requires user authentication.".color(:red)
|
129
|
+
when '404'
|
130
|
+
puts "The item did not exist.".color(:cyan)
|
131
|
+
else
|
132
|
+
(@command == 'health') ? (puts "Sensu is not healthy.".color(:red)) : (puts "There was an error while trying to complete your request. Response code: #{code}".color(:red))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def pretty(res)
|
137
|
+
if !res.empty?
|
138
|
+
if res.is_a?(Hash)
|
139
|
+
res.each do |key,value|
|
140
|
+
puts "#{key}: ".color(:cyan) + "#{value}".color(:green)
|
141
|
+
end
|
142
|
+
elsif res.is_a?(Array)
|
143
|
+
res.each do |item|
|
144
|
+
puts "-------".color(:yellow)
|
145
|
+
if item.is_a?(Hash)
|
146
|
+
item.each do |key,value|
|
147
|
+
puts "#{key}: ".color(:cyan) + "#{value}".color(:green)
|
148
|
+
end
|
149
|
+
else
|
150
|
+
puts item.to_s.color(:cyan)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
else
|
155
|
+
puts "no values for this request".color(:cyan)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def count(res)
|
160
|
+
res.is_a?(Hash) ? count = res.length : count = res.count
|
161
|
+
puts "#{count} total items".color(:yellow) if count
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'mixlib/config'
|
3
|
+
|
4
|
+
module SensuCli
|
5
|
+
class Settings
|
6
|
+
|
7
|
+
def is_file?(file)
|
8
|
+
!File.readable?(file) ? false : true
|
9
|
+
end
|
10
|
+
|
11
|
+
def create(directory,file)
|
12
|
+
FileUtils.mkdir_p(directory) if !File.directory?(directory)
|
13
|
+
FileUtils.cp(File.join(File.dirname(__FILE__),"../../settings.example.rb"), file)
|
14
|
+
puts "We created the configuration file for you at #{file}. You can also place this in /etc/sensu/sensu-cli. Edit the settings as needed.".color(:red)
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
class Config
|
21
|
+
extend(Mixlib::Config)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/sensu-cli.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'lib', 'sensu-cli', 'version')
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'sensu-cli'
|
5
|
+
s.version = SensuCli::VERSION
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.date = '2013-03-30'
|
8
|
+
s.summary = "A command line utility for Sensu."
|
9
|
+
s.description = "A command line utility for interacting with the Sensu api."
|
10
|
+
s.authors = ["Bryan Brandau"]
|
11
|
+
s.email = 'agent462@gmail.com'
|
12
|
+
s.has_rdoc = false
|
13
|
+
|
14
|
+
s.homepage ='http://github.com/agent462/sensu-cli'
|
15
|
+
s.add_dependency('rainbow', '1.1.4')
|
16
|
+
s.add_dependency('trollop', '2.0')
|
17
|
+
s.add_dependency('mixlib-config', '1.1.2')
|
18
|
+
|
19
|
+
s.files = Dir.glob('{bin,lib}/**/*') + %w[sensu-cli.gemspec README.md settings.example.rb]
|
20
|
+
s.executables = Dir.glob('bin/**/*').map { |file| File.basename(file) }
|
21
|
+
s.require_paths = ['lib']
|
22
|
+
end
|
data/settings.example.rb
ADDED
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sensu-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bryan Brandau
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-03-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rainbow
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: trollop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mixlib-config
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.1.2
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.2
|
55
|
+
description: A command line utility for interacting with the Sensu api.
|
56
|
+
email: agent462@gmail.com
|
57
|
+
executables:
|
58
|
+
- sensu
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- bin/sensu
|
63
|
+
- lib/sensu-cli/cli.rb
|
64
|
+
- lib/sensu-cli/sensu.rb
|
65
|
+
- lib/sensu-cli/settings.rb
|
66
|
+
- lib/sensu-cli/version.rb
|
67
|
+
- lib/sensu-cli.rb
|
68
|
+
- sensu-cli.gemspec
|
69
|
+
- README.md
|
70
|
+
- settings.example.rb
|
71
|
+
homepage: http://github.com/agent462/sensu-cli
|
72
|
+
licenses: []
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.0.3
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: A command line utility for Sensu.
|
94
|
+
test_files: []
|