mybot 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Botfile +7 -61
- data/CHANGELOG.md +2 -25
- data/README.md +72 -189
- data/lib/mybot.rb +20 -21
- data/lib/mybot/base.rb +6 -2
- data/lib/mybot/cli.rb +45 -5
- data/lib/mybot/command.rb +37 -28
- data/lib/mybot/fmt.rb +143 -52
- data/lib/mybot/helpers.rb +24 -0
- data/lib/mybot/installer.rb +31 -0
- data/lib/mybot/lib.rb +20 -59
- data/lib/mybot/libs.rb +31 -28
- data/lib/mybot/loader.rb +25 -0
- data/lib/mybot/node.rb +100 -47
- data/lib/mybot/nodes.rb +16 -0
- data/lib/mybot/tasks.rb +47 -11
- data/lib/mybot/template.rb +8 -8
- data/lib/mybot/templates.rb +15 -0
- data/lib/mybot/version.rb +1 -1
- data/vendor/lib/{core/.gitkeep → .gitkeep} +0 -0
- data/vendor/{recipes → plugins}/.gitkeep +0 -0
- data/vendor/{tpl/core → tasks}/.gitkeep +0 -0
- data/vendor/tpl/.gitkeep +0 -0
- metadata +11 -34
- data/lib/mybot/aws.rb +0 -54
- data/lib/mybot/commands.rb +0 -108
- data/lib/mybot/core-ext/array.rb +0 -9
- data/lib/mybot/core-ext/class.rb +0 -53
- data/lib/mybot/core-ext/kernel.rb +0 -21
- data/lib/mybot/messages.rb +0 -30
- data/lib/mybot/recipes.rb +0 -25
- data/lib/mybot/result.rb +0 -26
- data/lib/mybot/utils.rb +0 -7
- data/vendor/lib/core/fs.rb +0 -191
- data/vendor/lib/core/osx/git.rb +0 -31
- data/vendor/lib/core/osx/rails.rb +0 -31
- data/vendor/lib/core/osx/static.rb +0 -31
- data/vendor/lib/core/ubuntu/apache.rb +0 -42
- data/vendor/lib/core/ubuntu/apt.rb +0 -57
- data/vendor/lib/core/ubuntu/git.rb +0 -48
- data/vendor/lib/core/ubuntu/mysql.rb +0 -214
- data/vendor/lib/core/ubuntu/nginx.rb +0 -43
- data/vendor/lib/core/ubuntu/passenger.rb +0 -55
- data/vendor/lib/core/ubuntu/php.rb +0 -76
- data/vendor/lib/core/ubuntu/rails.rb +0 -105
- data/vendor/lib/core/ubuntu/ruby.rb +0 -166
- data/vendor/lib/core/ubuntu/service.rb +0 -30
- data/vendor/lib/core/ubuntu/static.rb +0 -50
- data/vendor/lib/core/ubuntu/users.rb +0 -76
- data/vendor/lib/core/ubuntu/vim.rb +0 -31
- data/vendor/tpl/core/ubuntu/apache/apache2.conf.erb +0 -80
- data/vendor/tpl/core/ubuntu/nginx/nginx.conf.erb +0 -72
- 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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
namespace :
|
10
|
-
task
|
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
|
data/CHANGELOG.md
CHANGED
@@ -1,25 +1,2 @@
|
|
1
|
-
### 0.0
|
2
|
-
*
|
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**,
|
3
|
+
**mybot**, personal bot
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
7
|
```
|
8
8
|
gem install mybot
|
9
|
-
bot
|
9
|
+
bot install
|
10
10
|
```
|
11
11
|
|
12
|
-
|
12
|
+
**mybot** would be installed to `~/.mybot`
|
13
13
|
|
14
|
-
|
15
|
-
* `lib` - libraries
|
16
|
-
* `recipes` - your recipes
|
17
|
-
* `tpl` - templates
|
14
|
+
## Tasks
|
18
15
|
|
19
|
-
|
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
|
-
|
29
|
+
and run it by typing `bot foo:bar`.
|
30
|
+
|
31
|
+
**mybot** searches for tasks in following places:
|
51
32
|
|
52
|
-
|
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
|
-
|
46
|
+
srv = node "1.2.3.4", "user", :password => "123"
|
60
47
|
|
61
48
|
namespace :foo do
|
62
49
|
task :bar do
|
63
|
-
|
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).
|
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
|
-
|
73
|
-
|
60
|
+
TASK foo
|
61
|
+
[user@1.2.3.4] RUN sudo pwd
|
62
|
+
EXIT 0
|
63
|
+
TIME 0.353989s
|
74
64
|
```
|
75
65
|
|
76
|
-
|
66
|
+
You can also use SSH keys:
|
77
67
|
|
78
68
|
```ruby
|
79
|
-
|
69
|
+
srv = node "1.2.3.4", "user", :keys => ["/path/to/key"]
|
80
70
|
```
|
81
71
|
|
82
|
-
|
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
|
-
|
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
|
-
|
100
|
-
[
|
101
|
-
[
|
102
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
122
|
+
mytpl = tpl :file => "path/to/tpl"
|
187
123
|
```
|
188
124
|
|
189
125
|
**mybot** will look for templates in `~/.mybot/tpl`
|
190
126
|
|
191
|
-
|
127
|
+
## Download and upload files
|
192
128
|
|
193
129
|
```ruby
|
194
130
|
task :foo do
|
195
|
-
|
196
|
-
:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
147
|
+
## Libs
|
261
148
|
|
262
|
-
|
263
|
-
task :foo do
|
264
|
-
wait
|
149
|
+
You can group node operations into lib
|
265
150
|
|
266
|
-
|
267
|
-
|
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
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
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
|
-
|
175
|
+
and use them in this way
|
283
176
|
|
284
|
-
```
|
285
|
-
|
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
|
-
|
180
|
+
apt = lib "ubuntu:apt"
|
295
181
|
|
296
|
-
|
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
|