mybot 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/Botfile +7 -61
  2. data/CHANGELOG.md +2 -25
  3. data/README.md +72 -189
  4. data/lib/mybot.rb +20 -21
  5. data/lib/mybot/base.rb +6 -2
  6. data/lib/mybot/cli.rb +45 -5
  7. data/lib/mybot/command.rb +37 -28
  8. data/lib/mybot/fmt.rb +143 -52
  9. data/lib/mybot/helpers.rb +24 -0
  10. data/lib/mybot/installer.rb +31 -0
  11. data/lib/mybot/lib.rb +20 -59
  12. data/lib/mybot/libs.rb +31 -28
  13. data/lib/mybot/loader.rb +25 -0
  14. data/lib/mybot/node.rb +100 -47
  15. data/lib/mybot/nodes.rb +16 -0
  16. data/lib/mybot/tasks.rb +47 -11
  17. data/lib/mybot/template.rb +8 -8
  18. data/lib/mybot/templates.rb +15 -0
  19. data/lib/mybot/version.rb +1 -1
  20. data/vendor/lib/{core/.gitkeep → .gitkeep} +0 -0
  21. data/vendor/{recipes → plugins}/.gitkeep +0 -0
  22. data/vendor/{tpl/core → tasks}/.gitkeep +0 -0
  23. data/vendor/tpl/.gitkeep +0 -0
  24. metadata +11 -34
  25. data/lib/mybot/aws.rb +0 -54
  26. data/lib/mybot/commands.rb +0 -108
  27. data/lib/mybot/core-ext/array.rb +0 -9
  28. data/lib/mybot/core-ext/class.rb +0 -53
  29. data/lib/mybot/core-ext/kernel.rb +0 -21
  30. data/lib/mybot/messages.rb +0 -30
  31. data/lib/mybot/recipes.rb +0 -25
  32. data/lib/mybot/result.rb +0 -26
  33. data/lib/mybot/utils.rb +0 -7
  34. data/vendor/lib/core/fs.rb +0 -191
  35. data/vendor/lib/core/osx/git.rb +0 -31
  36. data/vendor/lib/core/osx/rails.rb +0 -31
  37. data/vendor/lib/core/osx/static.rb +0 -31
  38. data/vendor/lib/core/ubuntu/apache.rb +0 -42
  39. data/vendor/lib/core/ubuntu/apt.rb +0 -57
  40. data/vendor/lib/core/ubuntu/git.rb +0 -48
  41. data/vendor/lib/core/ubuntu/mysql.rb +0 -214
  42. data/vendor/lib/core/ubuntu/nginx.rb +0 -43
  43. data/vendor/lib/core/ubuntu/passenger.rb +0 -55
  44. data/vendor/lib/core/ubuntu/php.rb +0 -76
  45. data/vendor/lib/core/ubuntu/rails.rb +0 -105
  46. data/vendor/lib/core/ubuntu/ruby.rb +0 -166
  47. data/vendor/lib/core/ubuntu/service.rb +0 -30
  48. data/vendor/lib/core/ubuntu/static.rb +0 -50
  49. data/vendor/lib/core/ubuntu/users.rb +0 -76
  50. data/vendor/lib/core/ubuntu/vim.rb +0 -31
  51. data/vendor/tpl/core/ubuntu/apache/apache2.conf.erb +0 -80
  52. data/vendor/tpl/core/ubuntu/nginx/nginx.conf.erb +0 -72
  53. data/vendor/tpl/core/ubuntu/php/php.ini.erb +0 -1818
data/Botfile CHANGED
@@ -1,66 +1,12 @@
1
1
  require "mybot"
2
- require "fileutils"
3
2
 
4
- include Messages
5
-
6
- local = node "localhost", "seba",
7
- :keys => ["/Users/seba/.ssh/id_rsa"]
8
-
9
- namespace :mybot do
10
- task :version do
11
- puts Mybot::VERSION
12
- end
13
-
14
- task :install do
15
- if File.exists? Mybot::MYBOT_PATH
16
- error "mybot is already installed"
17
- end
18
-
19
- info "installing mybot to #{Mybot::MYBOT_PATH}"
20
- FileUtils.mkdir Mybot::MYBOT_PATH
21
- FileUtils.cp_r Mybot::VENDOR_PATH, Mybot::MYBOT_PATH
22
- end
23
-
24
- task :uninstall do
25
- unless File.exists? Mybot::MYBOT_PATH
26
- error "mybot is not installed"
27
- end
28
-
29
- info "uninstalling mybot"
30
- if yes?("Do you really want to delete ~/.mybot")
31
- FileUtils.rm_rf Mybot::MYBOT_PATH
32
- else
33
- info "uninstallation aborted"
34
- end
35
- end
36
-
37
- task :update do
38
- unless File.exists? Mybot::MYBOT_PATH
39
- error "mybot is not installed"
40
- end
41
-
42
- info "updating mybot"
43
- FileUtils.rm_rf File.join(LIB_PATH, "core")
44
- FileUtils.mkdir File.join(LIB_PATH, "core")
45
- FileUtils.cp_r File.join(VENDOR_PATH, "lib", "core"),
46
- File.join(MYBOT_PATH, "lib")
47
-
48
- FileUtils.rm_rf File.join(TPL_PATH, "core")
49
- FileUtils.mkdir File.join(TPL_PATH, "core")
50
- FileUtils.cp_r File.join(VENDOR_PATH, "tpl", "core"),
51
- File.join(MYBOT_PATH, "tpl")
52
- end
53
-
54
- namespace :tasks do
55
- task :list do
56
- puts "available tasks:"
57
- tasks.each do |t|
58
- if t[:namespace]
59
- puts " #{t[:namespace]}:#{t[:name]}"
60
- else
61
- puts " #{t[:name]}"
62
- end
63
- end
3
+ namespace :tasks do
4
+ task :list do
5
+ puts "available tasks:"
6
+ tasks.each do |t|
7
+ task = t[:name]
8
+ task = "#{t[:namespace]}:#{t[:name]}" if t[:namespace]
9
+ puts " #{task}"
64
10
  end
65
11
  end
66
12
  end
@@ -1,25 +1,2 @@
1
- ### 0.0.3
2
- * added Utils with lib_to_path
3
- * added require_*_installed helper
4
- * added AWS instances support
5
- * added nginx support with static apps
6
- * added rails and static apps deployment
7
- * added git.init
8
- * added PHP support with nginx and FPM
9
- * fixed bug when running cmd in other cmd
10
- * refactored output formatting
11
- * added apt.dpkg_reconfigure
12
- * Node#run now returns Result object with STDOUT, STDERR and exit status
13
- * added fs.mktemp
14
- * added mysql user and dbs management routines
15
- * added ~/.bash_profile, ~/.bashrc and ~/.profile loading
16
- * added listeners
17
- * added write shadows
18
-
19
- ### 0.0.2
20
- * started CHANGELOG
21
- * updated README to cover all available techniques
22
- * added handling sudo via `options[:sudo]`
23
- * renamed `~/.mybot/tasks` to `~/.mybot/recipes`
24
- * lib support
25
- * added Kernel.qualified_const_get in core-ext
1
+ ### 0.1.0
2
+ * gem rewritten
data/README.md CHANGED
@@ -1,41 +1,20 @@
1
1
  # mybot
2
2
 
3
- **mybot**, my personal bot
3
+ **mybot**, personal bot
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```
8
8
  gem install mybot
9
- bot mybot:install
9
+ bot install
10
10
  ```
11
11
 
12
- This will install **myboot** to `$HOME/.mybot`.
12
+ **mybot** would be installed to `~/.mybot`
13
13
 
14
- * `.mybot`
15
- * `lib` - libraries
16
- * `recipes` - your recipes
17
- * `tpl` - templates
14
+ ## Tasks
18
15
 
19
- ## Updating
16
+ Define task
20
17
 
21
- ```
22
- gem update mybot
23
- bot mybot:update
24
- ```
25
-
26
- This will replace `.mybot/lib/mybot/core` and `.mybot/tpl/mybot/core` directories with new, updated ones.
27
-
28
- ## Usage
29
-
30
- ### Recipes and tasks
31
-
32
- **mybot** searches for recipes in following directories:
33
-
34
- * `~/.mybot/recipes/*.rb`
35
- * `.mybot/*.rb`
36
- * and in `./Botfile`
37
-
38
- To list all available tasks type `bot mybot:tasks:list`. Here's example recipe with task `foo:bar`:
39
18
 
40
19
  ```ruby
41
20
  require "mybot"
@@ -47,45 +26,56 @@ namespace :foo do
47
26
  end
48
27
  ```
49
28
 
50
- You can run it by typing `bot foo:bar`.
29
+ and run it by typing `bot foo:bar`.
30
+
31
+ **mybot** searches for tasks in following places:
51
32
 
52
- ### Setting nodes and running commands
33
+ * `./Botfile`
34
+ * `.mybot/*.rb`
35
+ * `~/.mybot/tasks`
36
+
37
+ To list all available tasks type `bot tasks:list`.
38
+
39
+ ## Nodes
53
40
 
54
41
  **mybot** operates on nodes which are practically computers you can SSH into. For the most part you will be executing commands using `node.run`:
55
42
 
56
43
  ```ruby
57
44
  require "mybot"
58
45
 
59
- @node = node "1.2.3.4", "user", :password => "123"
46
+ srv = node "1.2.3.4", "user", :password => "123"
60
47
 
61
48
  namespace :foo do
62
49
  task :bar do
63
- @node.run({ :cmd => "uname -a" })
50
+ srv.run "uname -a"
64
51
  end
65
52
  end
66
53
  ```
67
54
 
68
- It will execute your command on specified node (mine was Ubuntu Server). The output will be more or less:
55
+ It will execute your command on specified node (mine was Ubuntu Server).
56
+ The output will be more or less:
69
57
 
70
58
  ```
71
59
  $ bot foo:bar
72
- [ubuntu@1.2.3.4] RUN uname -a
73
- Linux ubuntu 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
60
+ TASK foo
61
+ [user@1.2.3.4] RUN sudo pwd
62
+ EXIT 0
63
+ TIME 0.353989s
74
64
  ```
75
65
 
76
- When setting node you can also use SSH keys:
66
+ You can also use SSH keys:
77
67
 
78
68
  ```ruby
79
- @node = node "1.2.3.4", "user", :keys => ["/path/to/key"]
69
+ srv = node "1.2.3.4", "user", :keys => ["/path/to/key"]
80
70
  ```
81
71
 
82
- ### Interaction
72
+ ## Interaction
83
73
 
84
74
  Executed commands can ask for your input and you can handle it with `on`:
85
75
 
86
76
  ```ruby
87
77
  task :foo do
88
- @node.run({ :cmd => "sudo pwd" }) do |cmd|
78
+ node.run "sudo pwd" do |cmd|
89
79
  cmd.on "[sudo] password" do
90
80
  cmd.write "123"
91
81
  end
@@ -96,10 +86,12 @@ end
96
86
  Here's the output:
97
87
 
98
88
  ```
99
- [ubuntu@192.168.1.7] RUN sudo pwd
100
- [sudo] password for ubuntu:
101
- [ubuntu@192.168.1.7] WRITE 123<LF>
102
- /home/ubuntu
89
+ TASK foo
90
+ [user@1.2.3.4] RUN sudo pwd
91
+ HANDLE [sudo] password
92
+ WRITE 123<LF>
93
+ EXIT 0
94
+ TIME 0.353989s
103
95
  ```
104
96
 
105
97
  ### Handling sudo
@@ -108,195 +100,86 @@ Handling sudo is such repetitive task that you can try to handle it automaticall
108
100
 
109
101
  ```ruby
110
102
  task :foo do
111
- puts "=> running uname -a"
112
- @node.run({ :cmd => "pwd", :sudo => true })
103
+ node.run "pwd", :sudo => true
113
104
  end
114
105
  ```
115
106
 
116
107
  It would try to use password provided with node declaration and will fail when the password doesn't work asking you to handle sudo manually. Note that you don't have to prepend command with **sudo** when using `:sudo => true`.
117
108
 
118
- ### Customizing output
119
-
120
- As you saw in previous sections, **mybot** produces fair amount of output when talking with nodes. Everything is controlled by options in `node.fmt`:
121
-
122
- * `use_color` - turn of when your terminal don't support colors
123
- * `show_cmd` - show messages like `[user@host] RUN cmd`
124
- * `show_stdout` and `show_stdout` - show **STDOUT** and **STDERR** produced by executed commands
125
- * `show_stdin` - show input being passed to nodes (messages like `[user@host] WRITE sth<LF>`)
126
-
127
- Each option is set to `true` by default. For example you can customize **mybot** to show only commands without output:
128
-
129
- ```ruby
130
- @node.fmt.show_stdout = false
131
- @node.fmt.show_stderr = false
132
- @node.fmt.show_stdin = false
133
-
134
- task :foo do
135
- @node.run({ :cmd => "uname -a" })
136
- end
137
- ```
138
-
139
- or even completely disable it and only display own informations, so adding `@node.fmt.show_cmd = false` to previous example will produce only:
140
-
141
- ```
142
- => running uname -a
143
- ```
144
-
145
- You can use helpers build-in: `info`, `warning` and `error` which aborts execution of the script.
146
-
147
- ### Libraries
148
-
149
- You can `use` many provided libraries to extend nodes functionality. The most common is Filesystem library:
150
-
151
- ```ruby
152
- task :foo do
153
- if @node.fs.exists?({ :file => "/path/to/file" })
154
- content = @node.fs.read({ :file => "/path/to/file" })
155
- else
156
- @node.fs.create({ :file => "/path/to/file", :content => "abc\n" })
157
- end
158
- end
159
- ```
160
-
161
- ### Templates
162
-
163
- There is build-in templating system based on **ERB**.
109
+ ## Templates
164
110
 
165
111
  ```ruby
166
- @tpl = tpl <<<-TPL
167
- This is template
168
- param1: <%= param1 %>
169
- param2: <%= param2 %>
170
- TPL
112
+ mytpl = tpl "param: <%= param %>"
171
113
 
172
114
  task :foo do
173
- @node.fs.create({
174
- :file => "/path/to/file",
175
- :content => @tpl.render({
176
- :param1 => "value1",
177
- :param2 => "value2"
178
- })
179
- })
115
+ puts mytpl.render({ param: "value" })
180
116
  end
181
117
  ```
182
118
 
183
119
  In fact you don't want to clutter your recipes with template strings so better use template files:
184
120
 
185
121
  ```ruby
186
- @tpl = tpl_file "path/to/tpl"
122
+ mytpl = tpl :file => "path/to/tpl"
187
123
  ```
188
124
 
189
125
  **mybot** will look for templates in `~/.mybot/tpl`
190
126
 
191
- Downloading and uploading files is simple as:
127
+ ## Download and upload files
192
128
 
193
129
  ```ruby
194
130
  task :foo do
195
- @node.fs.upload({
196
- :from => "/file/to/upload",
197
- :to => "/home/ubuntu/file"
198
- })
199
-
200
- @node.fs.download({
201
- :from => "/home/ubuntu/file,
202
- :to => "/tmp/downloaded_file"
203
- })
204
- end
205
- ```
206
-
207
- There's always *progress bar* so you know if you have time for coffee :)
208
-
209
- There's nice **Ubuntu** library already:
210
-
211
- ```ruby
212
- @node = node "1.2.3.4", "user", :password => "123"
213
- @node.use "core/ubuntu/apt"
214
-
215
- task :setup do
216
- unless @node.apt.installed?({ :pkg => "name" })
217
- @node.apt.install({ :pkg => "name" })
218
- else
219
- @node.apt.update
220
- end
221
- end
222
- ```
131
+ node.upload "/Users/seba/Downloads/test.zip",
132
+ :to => "/home/user/test.zip"
223
133
 
224
- Of course you can roll own libraries. Save them to `~/.mybot/lib` folder. Do not touch `~/.mybot/lib/core` because it will be replaced by updates. Your custom lib should look like this:
225
-
226
- ```ruby
227
- class Foo < Mybot::Lib
228
- def initialize(node)
229
- @node = node
230
- end
231
-
232
- def bar
233
- puts "foo:bar"
234
- end
235
-
236
- def baz?
237
- true
238
- end
134
+ node.download "/home/user/test.zip",
135
+ :to => "/Users/seba/Downloads/t.zip"
239
136
  end
240
137
  ```
241
138
 
242
- and should be used like this:
243
-
244
- ```ruby
245
- @node.use "foo"
246
-
247
- task :foo
248
- if @node.foo.baz?
249
- @node.foo.bar
250
- end
251
- end
252
- ```
139
+ There's always *progress bar* so you know if you have time for coffee :)
253
140
 
254
- ### Usefull CLI helpers
141
+ ## CLI helpers
255
142
 
256
143
  * `wait` will display *Press any key to continue...* message and will wait for any user interaction
257
144
  * `ask` will display question passed as argument and return the answer
258
145
  * `yes?` will display question too but it should return true or false based on user's answer. Only `yes | Yes | y` and similar answers are acceptable. When boolean value cannot be guessed the question is asked again.
259
146
 
260
- Here's example showing helpers in action:
147
+ ## Libs
261
148
 
262
- ```ruby
263
- task :foo do
264
- wait
149
+ You can group node operations into lib
265
150
 
266
- @node.run({ :cmd => "sudo pwd" }) do |cmd|
267
- cmd.on "[sudo] password" do
268
- # ask's 1st argument is the question and it defaults to empty string
269
- # we're displaying STDOUT so question is already asked :)
270
- cmd.write ask
271
- end
272
- end
151
+ ```ruby
152
+ require "mybot"
273
153
 
274
- if yes?("type sth (yes/no): ")
275
- puts "you said yes"
276
- else
277
- puts "you said no"
278
- end
154
+ library "ubuntu:apt" do
155
+ library_options({
156
+ :env => {
157
+ "DEBIAN_FRONTEND" => "noninteractive"
158
+ }
159
+ })
160
+
161
+ func :update do |node, options|
162
+ node.run "apt-get update", options do |cmd|
163
+ cmd.on "dpkg was interrupted" do
164
+ error "Cannot update"
165
+ end
166
+
167
+ cmd.on "Could not get lock" do
168
+ error "Cannot update"
169
+ end
170
+ end
171
+ end
279
172
  end
280
173
  ```
281
174
 
282
- Running `foo` task will produce:
175
+ and use them in this way
283
176
 
284
- ```
285
- Press any key to continue...
286
- [user@1.2.3.4] RUN sudo pwd
287
- [sudo] password for ubuntu: 34
288
-
289
- [user@1.2.3.4] WRITE 34<LF>
290
-
291
- Sorry, try again.
292
- [sudo] password for ubuntu: 123
177
+ ```ruby
178
+ require "mybot"
293
179
 
294
- [user@1.2.3.4] WRITE 123<LF>
180
+ apt = lib "ubuntu:apt"
295
181
 
296
- /home/ubuntu
297
- type sth (yes/no): x
298
- type sth (yes/no): y
299
- you said yes
182
+ apt.update node, {}
300
183
  ```
301
184
 
302
185
  ## Uninstallation