collins_shell 0.2.14

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.
Files changed (39) hide show
  1. data/.pryrc +1 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +18 -0
  4. data/Gemfile.lock +59 -0
  5. data/README.md +335 -0
  6. data/Rakefile +64 -0
  7. data/VERSION +1 -0
  8. data/bin/collins-shell +36 -0
  9. data/collins_shell.gemspec +95 -0
  10. data/lib/collins_shell.rb +3 -0
  11. data/lib/collins_shell/asset.rb +198 -0
  12. data/lib/collins_shell/cli.rb +185 -0
  13. data/lib/collins_shell/console.rb +129 -0
  14. data/lib/collins_shell/console/asset.rb +127 -0
  15. data/lib/collins_shell/console/cache.rb +17 -0
  16. data/lib/collins_shell/console/command_helpers.rb +131 -0
  17. data/lib/collins_shell/console/commands.rb +28 -0
  18. data/lib/collins_shell/console/commands/cat.rb +123 -0
  19. data/lib/collins_shell/console/commands/cd.rb +61 -0
  20. data/lib/collins_shell/console/commands/io.rb +26 -0
  21. data/lib/collins_shell/console/commands/iterators.rb +190 -0
  22. data/lib/collins_shell/console/commands/tail.rb +178 -0
  23. data/lib/collins_shell/console/commands/versions.rb +42 -0
  24. data/lib/collins_shell/console/filesystem.rb +121 -0
  25. data/lib/collins_shell/console/options_helpers.rb +8 -0
  26. data/lib/collins_shell/errors.rb +7 -0
  27. data/lib/collins_shell/ip_address.rb +144 -0
  28. data/lib/collins_shell/ipmi.rb +67 -0
  29. data/lib/collins_shell/monkeypatch.rb +60 -0
  30. data/lib/collins_shell/provision.rb +152 -0
  31. data/lib/collins_shell/state.rb +98 -0
  32. data/lib/collins_shell/tag.rb +41 -0
  33. data/lib/collins_shell/thor.rb +209 -0
  34. data/lib/collins_shell/util.rb +120 -0
  35. data/lib/collins_shell/util/asset_printer.rb +265 -0
  36. data/lib/collins_shell/util/asset_stache.rb +32 -0
  37. data/lib/collins_shell/util/log_printer.rb +187 -0
  38. data/lib/collins_shell/util/printer_util.rb +28 -0
  39. metadata +200 -0
data/.pryrc ADDED
@@ -0,0 +1 @@
1
+ Pry.config.default_asset_format = '{{tag}} {{hostname}} {{status}}'
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.3
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source :rubygems
2
+
3
+ Encoding.default_external = Encoding::UTF_8
4
+
5
+ gem 'collins_client', '~> 0.2.7'
6
+ gem 'highline', '~> 1.6.15'
7
+ gem 'mustache', '~> 0.99.4'
8
+ gem 'pry', '~> 0.9.9.6'
9
+ gem 'rubygems-update','~> 1.8.24'
10
+ gem 'terminal-table', '~> 1.4.5'
11
+ gem 'thor', '~> 0.16.0'
12
+
13
+ group :development do
14
+ gem 'jeweler', '~> 1.8.3'
15
+ gem 'redcarpet'
16
+ gem 'rspec', '~> 2.10.0'
17
+ gem 'yard', '~> 0.8'
18
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,59 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ coderay (1.0.8)
5
+ collins_client (0.2.7)
6
+ httparty (~> 0.8.3)
7
+ diff-lcs (1.1.3)
8
+ git (1.2.5)
9
+ highline (1.6.15)
10
+ httparty (0.8.3)
11
+ multi_json (~> 1.0)
12
+ multi_xml
13
+ jeweler (1.8.4)
14
+ bundler (~> 1.0)
15
+ git (>= 1.2.5)
16
+ rake
17
+ rdoc
18
+ json (1.7.5)
19
+ method_source (0.7.1)
20
+ multi_json (1.3.6)
21
+ multi_xml (0.5.1)
22
+ mustache (0.99.4)
23
+ pry (0.9.9.6)
24
+ coderay (~> 1.0.5)
25
+ method_source (~> 0.7.1)
26
+ slop (>= 2.4.4, < 3)
27
+ rake (0.9.2.2)
28
+ rdoc (3.12)
29
+ json (~> 1.4)
30
+ redcarpet (2.2.2)
31
+ rspec (2.10.0)
32
+ rspec-core (~> 2.10.0)
33
+ rspec-expectations (~> 2.10.0)
34
+ rspec-mocks (~> 2.10.0)
35
+ rspec-core (2.10.1)
36
+ rspec-expectations (2.10.0)
37
+ diff-lcs (~> 1.1.3)
38
+ rspec-mocks (2.10.1)
39
+ rubygems-update (1.8.24)
40
+ slop (2.4.4)
41
+ terminal-table (1.4.5)
42
+ thor (0.16.0)
43
+ yard (0.8.3)
44
+
45
+ PLATFORMS
46
+ ruby
47
+
48
+ DEPENDENCIES
49
+ collins_client (~> 0.2.7)
50
+ highline (~> 1.6.15)
51
+ jeweler (~> 1.8.3)
52
+ mustache (~> 0.99.4)
53
+ pry (~> 0.9.9.6)
54
+ redcarpet
55
+ rspec (~> 2.10.0)
56
+ rubygems-update (~> 1.8.24)
57
+ terminal-table (~> 1.4.5)
58
+ thor (~> 0.16.0)
59
+ yard (~> 0.8)
data/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # CollinsShell Description
2
+
3
+ The collins shell is a lightweight application built on top of the
4
+ `collins_client` gem. The `collins_client` gem provides API access to collins,
5
+ the `collins_shell` application provides CLI API access to collins.
6
+
7
+ ## Installation
8
+
9
+ > gem install collins_shell --source=http://repo.tumblr.net:9929
10
+
11
+ ## Setup
12
+
13
+ Collins shell will look for a yaml file at ~/.collins.yaml, passed in via
14
+ `--config=my_collins.yaml`, or passed in via an environment variable like
15
+ `COLLINS=~/my_collins.yaml`. The file should look like:
16
+
17
+ ---
18
+ collins:
19
+ host: "http://somehost:8080"
20
+ username: "user"
21
+ password: "secret"
22
+
23
+ You can also specify the host, username, or options via the `--host`,
24
+ `--username` and `--password` options. If you just specify `--password`
25
+ (without a value), or your configs are missing a password, you will be
26
+ prompted for one.
27
+
28
+ ## Overview
29
+
30
+ There are a few common themes found throughout the collins shell that will
31
+ help you be productive.
32
+
33
+ ### Command Structure
34
+
35
+ collins-shell uses thor under the hood to handle command line dispatching and
36
+ parsing. Arguments to collins-shell consist of commands, subcommands,
37
+ arguments, and options.
38
+
39
+ Supported commands and subcommands are:
40
+
41
+ asset
42
+ create
43
+ delete
44
+ delete_attribute
45
+ find
46
+ get
47
+ set_attribute
48
+ set_status
49
+ console
50
+ ip_address
51
+ allocate
52
+ assets
53
+ delete
54
+ delete_all
55
+ find
56
+ pools
57
+ update
58
+ ipmi
59
+ create
60
+ update
61
+ latest
62
+ log
63
+ logs
64
+ power
65
+ power_status
66
+ provision
67
+ host
68
+ list
69
+ tag
70
+ list
71
+ values
72
+ version
73
+
74
+ All commands are of the form:
75
+
76
+ collins-shell <command> <args> <options>
77
+
78
+ Every command can be described via `help`, e.g. `collins-shell help log` or
79
+ `collins-shell asset help create`. Note that to get help for a subcommand, the
80
+ help directive must come after the command, but before the subcommand.
81
+
82
+ This returns help for the `asset find` subcommand:
83
+
84
+ collins-shell asset help find
85
+
86
+ This returns help for the `asset` command (the `find` subcommand is ignored):
87
+
88
+ collins-shell help asset find
89
+
90
+ A command is something like `log` or `asset find`. Arguments are required
91
+ options, passed to the command without a switch (e.g. `asset get TAG`, `TAG`
92
+ is an argument there). Options are optional, and generally passed like
93
+ `--option` or `--option=value`.
94
+
95
+ ### Universal Options
96
+
97
+ The following options can be specified for every command:
98
+
99
+ --config=CONFIG # YAML configuration file
100
+ --debug # Debug output
101
+ --host=HOST # Collins host (e.g. http://host:port)
102
+ --quiet # Mostly used in conjunction with commands that have an --exec option
103
+ --timeout=SECONDS # Seconds to allow for operation, defaults to 30
104
+ --username=USERNAME # Collins username
105
+ --password=PASSWORD # Collins password
106
+
107
+
108
+ ### Common Options
109
+
110
+ Many options will allow you to specify either a selector (matching many
111
+ assets) or a tag (matching a single asset). A tag is the asset tag, a selector
112
+ is a space separated list of `key:value` pairs that are asset keys and values.
113
+ Some examples are:
114
+
115
+ # Allocated web servers (note that multiple selectors are separated by a space)
116
+ --selector=hostname:'^web.*' status:Allocated
117
+ # Allocated master database servers in the main pool
118
+ --selector=primary_role:database pool:main secondary_role:master status:Allocated
119
+ # Asset with tag 001923
120
+ --tag=001923
121
+
122
+ Note that any time a command will result in changing more than one asset,
123
+ collins-shell will prompt for confirmation.
124
+
125
+ # Multi-Collins Support
126
+
127
+ Collins has a feature called 'multi-collins' that allows multiple collins servers to
128
+ know about each other. This functionality provides a unified view of all assets,
129
+ regardless of which collins server stores a given asset. If you have enabled
130
+ multi-collins, your collins-shell configuration only needs to have credentials and host
131
+ information for one of your collins servers.
132
+
133
+ By default, collins-shell only interacts a single collins server (the one specified in the configuration file). To run commands against all of your collins servers, pass the `--remote` option.
134
+
135
+ One exception to this is `asset get`. `asset get` takes `--remote=TAG` where
136
+ tag is the asset tag of the datacenter that has the asset, e.g.
137
+ `--remote=ewr01` or `--remote=d2`.
138
+
139
+ The following commands support multi-collins:
140
+
141
+ asset find
142
+ asset get (with --remote=DC)
143
+ asset set_attribute
144
+ asset delete_attribute
145
+ asset set_status
146
+ log
147
+
148
+ Because `asset find` supports multi-collins, for any commands that don't (e.g.
149
+ `power_status`, it's trivial to script piping the results of the find to some
150
+ other command.
151
+
152
+ # Usage
153
+
154
+ ## Getting Help
155
+
156
+ Before using any command, check out the help. You can see help for a command
157
+ by running:
158
+
159
+ collins-shell help <command>
160
+
161
+ or
162
+
163
+ collins-shell <sub> help <command>
164
+
165
+ Where `<sub>` is something like `asset`, `ipmi` or `ip_address` and
166
+ `<command>` is something like `create`, `delete` or `get`. For example
167
+
168
+ > collins-shell asset help get
169
+ Usage:
170
+ collins-shell asset get TAG
171
+
172
+ Options:
173
+ --config=CONFIG # YAML configuration file
174
+ --debug # Debug output
175
+ --host=HOST # Collins host (e.g. http://host:port)
176
+ --password=PASSWORD # Collins password
177
+ --quiet # Be quiet when appropriate
178
+ --timeout=N # Collins client timeout
179
+ # Default: 30
180
+ --username=USERNAME # Collins username
181
+ --confirm # Require exec confirmation. Defaults to true
182
+ # Default: true
183
+ --exec=EXEC # Execute a command using the data from this asset. Use {{hostname}}, {{ipmi.password}}, etc for substitution
184
+ --logs # Also display asset logs
185
+ --remote=REMOTE # Remote location to search. This is a tag in collins corresponding to the datacenter asset
186
+
187
+ get an asset and display its attributes
188
+
189
+ ## Examples
190
+
191
+ > collins-shell
192
+ Tasks:
193
+ collins-shell asset <command> # Asset related commands
194
+ collins-shell console # drop into the interactive collins shell
195
+ collins-shell help [TASK] # Describe available tasks or one specific task
196
+ collins-shell ip_address <command> # IP address related commands
197
+ collins-shell ipmi <command> # IPMI related commands
198
+ collins-shell log MESSAGE # log a message on an asset
199
+ collins-shell power ACTION --reason=REASON --tag=TAG # perform power action (off, on, rebootSoft, rebootHard, etc) on an asset
200
+ collins-shell power_status --tag=TAG # check power status on an asset
201
+ collins-shell provision <command> # Provisioning related commands
202
+ collins-shell tag <command> # Tag related commands
203
+ > collins-shell asset
204
+ Tasks:
205
+ collins-shell asset create --tag=TAG # create an asset in collins
206
+ collins-shell asset delete --tag=TAG # delete an asset in collins (must be cancelled)
207
+ collins-shell asset delete_attribute KEY # delete an attribute in collins
208
+ collins-shell asset find --selector=key value # find assets using the specified selector
209
+ collins-shell asset get TAG # get an asset and display its attributes
210
+ collins-shell asset help [COMMAND] # Describe subcommands or one specific subcommand
211
+ collins-shell asset set_attribute KEY VALUE # set an attribute in collins
212
+ collins-shell asset set_status STATUS # set status on an asset
213
+ > collins-shell asset find --selector=status:Allocated 'hostname:^web.*'
214
+ id,tag,status,type,created,updated
215
+ 18,sl-90918,Allocated,Server Node,2012-02-08T00:34:43+00:00,2012-06-09T00:31:39+00:00
216
+ 20,sl-111623,Allocated,Server Node,2012-02-08T00:34:44+00:00,2012-06-09T01:25:35+00:00
217
+ 21,sl-70108,Allocated,Server Node,2012-02-08T00:34:44+00:00,2012-06-09T00:42:16+00:00
218
+ 23,sl-89121,Allocated,Server Node,2012-02-08T00:34:47+00:00,2012-06-09T00:33:31+00:00
219
+
220
+ # Tips and Tricks
221
+
222
+ There are a couple of neat features in the collins shell to be aware of.
223
+
224
+ ## Detailed asset views
225
+
226
+ I have tried to make the shell as consistent with the web UI as possible. Try
227
+ running a command like:
228
+
229
+ collins-shell asset get VALID_TAG_HERE
230
+
231
+ The display should be familiar to people if you've logged into the web UI.
232
+
233
+ ## Asset Logs
234
+
235
+ Adding `--logs` to your `asset get` or `asset find` commands will show logs
236
+ for each asset.
237
+
238
+ ## Making find more useful
239
+
240
+ There are three switches that are useful to know about with the `asset find`
241
+ command.
242
+
243
+ ### awk format
244
+
245
+ If you need to do some kind of post processing on data not found in the
246
+ default find results, you can specify them via the `--tags` option. This will
247
+ give you a comma separated list of tags, one for each asset. For example:
248
+
249
+ collins-shell asset find --selector=hostname:'^web' status:Allocated --tags=hostname addresses
250
+
251
+ Will provide you a list that might look like:
252
+
253
+ hostname,addresses
254
+ web-7c177b48.d2.tumblr.net,10.80.96.243|10.80.96.1|255.255.248.0,192.172.29.80|192.172.29.65|255.255.255.224
255
+ web-a1a316af.d2.tumblr.net,10.80.97.95|10.80.96.1|255.255.248.0,192.172.38.108|192.172.38.97|255.255.255.224
256
+
257
+ The header line tells you the asset tags you are displaying. Each
258
+ line has a comma separated list of values. If a value is an array of some
259
+ sort, values within it are separated by pipes. Easy parsing!
260
+
261
+ If you would prefer not to display the header line, just add `--header=false` to your find command.
262
+
263
+ Note there is one caveat, the current version of collins-shell cannot prompt for authentication
264
+ data if you are passing output to a pipe. In order to pass output to a pipe, you must have your
265
+ collins server and credentials defined in ~/.collins.yaml or pass them to collins-shell on the
266
+ command line.
267
+
268
+ ### Detailed output
269
+
270
+ Try adding `--details` to your `asset find` command to get a detailed asset
271
+ view of each of the assets in the result set.
272
+
273
+ ### Size
274
+
275
+ Setting `--size=N` (e.g. `--size=1000`) will give you that number of results
276
+ or less. The default is 50 results.
277
+
278
+ ## Friendly Sizes
279
+
280
+ If you're querying on the `memory_size_total` or `disk_storage_total`, you can
281
+ use human readable values like `72GB` or `2.18298348411918TB`. Yeah, the disk
282
+ one kind of sucks. But, if you do a `get` or `find --details` you can see what
283
+ the correct query value is.
284
+
285
+ ## Execute commands using asset data
286
+
287
+ Some commands support an `--exec` option that allows you to execute a command
288
+ using the information associated with the asset. An example might be:
289
+
290
+ collins-shell asset get TAG \
291
+ --exec='IPMI_PASSWORD={{ipmi.password}} ipmitool -I lanplus -E -U {{ipmi.username}} -H {{ipmi.address}} sol activate'
292
+
293
+ This will create a console session using IPMI with the asset specified by `TAG`. Any attributes of an asset
294
+ can be specified as `{{attribute}}`, e.g. `{{hostname}}` or `{{addresses.first.address}}`.
295
+
296
+ # The Interactive Shell
297
+
298
+ It is also possible to use collins shell in an interactive mode. You can drop
299
+ into the collins shell console by doing:
300
+
301
+ collins-shell console
302
+
303
+ Be sure to provide your config YAML in the usual way. Once you are in the shell
304
+ you can get a list of global commands by typing `help`. Global commands can be
305
+ used regardless of context. Below is a sample interactive session.
306
+
307
+ collins / > ls /
308
+ ....
309
+ collins / > cd /PRIMARY_ROLE
310
+ collins /PRIMARY_ROLE > ls
311
+ collins /PRIMARY_ROLE > cd DEVEL
312
+ collins /PRIMARY_ROLE/DEVEL > ls --format='{{hostname}} {{status}} {{tag}}' --grep=blake
313
+ collins /PRIMARY_ROLE/DEVEL > cd sl-91016
314
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > ls
315
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > cat -b
316
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > cat /var/log/messages
317
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > cat /var/log/NOTE
318
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > asset.created.to_s
319
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > power?
320
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > reboot!
321
+ collins /PRIMARY_ROLE/DEVEL/sl-91016* > cd ../sl-102313
322
+ collins /PRIMARY_ROLE/DEVEL/sl-102313* > stat
323
+
324
+ This is all ruby, so you can play with a lot of this data using ruby as you
325
+ would expect. Some examples:
326
+
327
+ collins / > ls /HOSTNAME/.*blake.* | {|array| array.map{|a| [a.tag,a.hostname,a.status]}}
328
+ collins / > hosts = _
329
+ collins / > hosts.select do |host|
330
+ collins / * host[2] == 'Allocated'
331
+ collins / * end.map do |host|
332
+ collins / * [host[0], host[1], collins_client.with_asset(host[0]).power_status]
333
+ collins / * end
334
+
335
+ The above checks the power status of the selected hosts.
data/Rakefile ADDED
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'jeweler'
14
+
15
+ jeweler = Jeweler::Tasks.new do |gem|
16
+ gem.name = 'collins_shell'
17
+ gem.homepage = 'https://github.com/tumblr/collins/tree/master/support/collins-shell'
18
+ gem.license = 'APL 2.0'
19
+ gem.summary = %Q{Shell for Collins API}
20
+ gem.description = "Provides basic CLI for interacting with Collins API"
21
+ gem.email = 'bmatheny@tumblr.com'
22
+ gem.authors = ['Blake Matheny']
23
+ gem.files.exclude "spec/**/*"
24
+ gem.files.exclude '.gitignore'
25
+ gem.files.exclude '.rspec'
26
+ gem.add_runtime_dependency 'collins_client', '~> 0.2.7'
27
+ gem.add_runtime_dependency 'highline', '~> 1.6.15'
28
+ gem.add_runtime_dependency 'mustache', '~> 0.99.4'
29
+ gem.add_runtime_dependency 'pry', '~> 0.9.9.6'
30
+ gem.add_runtime_dependency 'rubygems-update', '~> 1.8.24'
31
+ gem.add_runtime_dependency 'terminal-table', '~> 1.4.5'
32
+ gem.add_runtime_dependency 'thor', '~> 0.16.0'
33
+ end
34
+
35
+ task :help do
36
+ puts("rake -T # See available rake tasks")
37
+ puts("rake publish # generate gemspec, build it, push it to repo")
38
+ puts("rake version:bump:patch # Bump patch number")
39
+ puts("rake all # bump patch and publish")
40
+ puts("rake # Run tests")
41
+ end
42
+
43
+ task :publish => [:gemspec, :build] do
44
+ package_abs = jeweler.jeweler.gemspec_helper.gem_path
45
+ package_name = File.basename(package_abs)
46
+
47
+ ["repo.tumblr.net","repo.ewr01.tumblr.net"].each do |host|
48
+ puts("Copying #{package_abs} to #{host} and installing, you may be prompted for your password")
49
+ system "scp #{package_abs} #{host}:"
50
+ system "ssh -t #{host} 'sudo tumblr_gem install #{package_name}'"
51
+ end
52
+ end
53
+
54
+ task :all => ["version:bump:patch", :publish] do
55
+ puts("Done!")
56
+ end
57
+
58
+ task :default => :yard
59
+
60
+ require 'yard'
61
+ YARD::Rake::YardocTask.new do |t|
62
+ t.files = ['lib/**/*.rb']
63
+ t.options = ['--markup', 'markdown']
64
+ end