mybot 0.0.1
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/.gitignore +17 -0
- data/Botfile +59 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +1 -0
- data/bin/bot +6 -0
- data/lib/mybot.rb +20 -0
- data/lib/mybot/base.rb +8 -0
- data/lib/mybot/cli.rb +14 -0
- data/lib/mybot/command.rb +43 -0
- data/lib/mybot/commands.rb +84 -0
- data/lib/mybot/fmt.rb +87 -0
- data/lib/mybot/messages.rb +20 -0
- data/lib/mybot/node.rb +124 -0
- data/lib/mybot/recipes.rb +23 -0
- data/lib/mybot/tasks.rb +35 -0
- data/lib/mybot/template.rb +14 -0
- data/lib/mybot/version.rb +3 -0
- data/mybot.gemspec +26 -0
- data/vendor/lib/mybot/.gitkeep +0 -0
- data/vendor/tasks/.gitkeep +0 -0
- data/vendor/tpl/mybot/.gitkeep +0 -0
- metadata +150 -0
data/.gitignore
ADDED
data/Botfile
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "mybot"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
include Messages
|
5
|
+
|
6
|
+
namespace :mybot do
|
7
|
+
task :install do
|
8
|
+
if File.exists? Mybot::MYBOT_PATH
|
9
|
+
fatal "mybot is already installed"
|
10
|
+
end
|
11
|
+
|
12
|
+
info "installing mybot to #{Mybot::MYBOT_PATH}"
|
13
|
+
FileUtils.mkdir Mybot::MYBOT_PATH
|
14
|
+
FileUtils.cp_r Mybot::VENDOR_PATH, Mybot::MYBOT_PATH
|
15
|
+
end
|
16
|
+
|
17
|
+
task :uninstall do
|
18
|
+
unless File.exists? Mybot::MYBOT_PATH
|
19
|
+
fatal "mybot is not installed"
|
20
|
+
end
|
21
|
+
|
22
|
+
info "uninstalling mybot"
|
23
|
+
if yes?("Do you really want to delete ~/.mybot")
|
24
|
+
FileUtils.rm_rf Mybot::MYBOT_PATH
|
25
|
+
else
|
26
|
+
info "uninstallation aborted"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
task :update do
|
31
|
+
unless File.exists? Mybot::MYBOT_PATH
|
32
|
+
fatal "mybot is not installed"
|
33
|
+
end
|
34
|
+
|
35
|
+
info "updating mybot"
|
36
|
+
FileUtils.rm_rf File.join(LIB_PATH, "mybot")
|
37
|
+
FileUtils.mkdir File.join(LIB_PATH, "mybot")
|
38
|
+
FileUtils.cp_r File.join(VENDOR_PATH, "lib", "mybot"),
|
39
|
+
File.join(MYBOT_PATH, "lib")
|
40
|
+
|
41
|
+
FileUtils.rm_rf File.join(TPL_PATH, "mybot")
|
42
|
+
FileUtils.mkdir File.join(TPL_PATH, "mybot")
|
43
|
+
FileUtils.cp_r File.join(VENDOR_PATH, "tpl", "mybot"),
|
44
|
+
File.join(MYBOT_PATH, "tpl")
|
45
|
+
end
|
46
|
+
|
47
|
+
namespace :tasks do
|
48
|
+
task :list do
|
49
|
+
puts "available tasks:"
|
50
|
+
tasks.each do |t|
|
51
|
+
if t[:namespace]
|
52
|
+
puts " #{t[:namespace]}:#{t[:name]}"
|
53
|
+
else
|
54
|
+
puts " #{t[:name]}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sebastian Sito
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Mybot
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
gem install mybot
|
6
|
+
bot install
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
**Mybot** searches for tasks in following directories:
|
10
|
+
|
11
|
+
* `~/.mybot/tasks/`
|
12
|
+
* `.mybot/`
|
13
|
+
* and in `./Botfile`
|
14
|
+
|
15
|
+
## Tasks
|
16
|
+
This is example task
|
17
|
+
|
18
|
+
require "mybot"
|
19
|
+
|
20
|
+
namespace :foo do
|
21
|
+
task :bar do
|
22
|
+
puts "foo:bar"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
and you can run it by typing `bot foo:bar`
|
27
|
+
|
28
|
+
## Uninstallation
|
29
|
+
|
30
|
+
bot uninstall
|
31
|
+
gem uninstall -Iax mybot
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/bot
ADDED
data/lib/mybot.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mybot
|
2
|
+
autoload :Base, "mybot/base"
|
3
|
+
autoload :Cli, "mybot/cli"
|
4
|
+
autoload :Command, "mybot/command"
|
5
|
+
autoload :Commands, "mybot/commands"
|
6
|
+
autoload :Fmt, "mybot/fmt"
|
7
|
+
autoload :Messages, "mybot/messages"
|
8
|
+
autoload :Node, "mybot/node"
|
9
|
+
autoload :Recipes, "mybot/recipes"
|
10
|
+
autoload :Tasks, "mybot/tasks"
|
11
|
+
autoload :Template, "mybot/template"
|
12
|
+
autoload :VERSION, "mybot/version"
|
13
|
+
|
14
|
+
GEM_PATH = File.dirname(File.dirname(__FILE__))
|
15
|
+
VENDOR_PATH = File.join(GEM_PATH, "vendor", ".")
|
16
|
+
HOME_PATH = File.expand_path "~"
|
17
|
+
MYBOT_PATH = File.join HOME_PATH, ".mybot"
|
18
|
+
LIB_PATH = File.join MYBOT_PATH, "lib"
|
19
|
+
TPL_PATH = File.join MYBOT_PATH, "tpl"
|
20
|
+
end
|
data/lib/mybot/base.rb
ADDED
data/lib/mybot/cli.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Mybot
|
2
|
+
class Command
|
3
|
+
attr_accessor :out, :stdout, :stderr, :channel, :exit_status
|
4
|
+
|
5
|
+
def initialize(node)
|
6
|
+
@node = node
|
7
|
+
@out = @stdout = @stderr = ""
|
8
|
+
@handlers = {}
|
9
|
+
@exit_status = 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def on(s, &block)
|
13
|
+
@handlers[s] = block
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_stdout(data)
|
17
|
+
@out = data
|
18
|
+
@stdout += data.strip
|
19
|
+
@node.fmt.stdout data
|
20
|
+
@handlers.each do |s, proc|
|
21
|
+
proc.call if @out.include? s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_stderr(data)
|
26
|
+
@out = data
|
27
|
+
@stderr += data.strip
|
28
|
+
@node.fmt.stderr data
|
29
|
+
@handlers.each do |s, proc|
|
30
|
+
proc.call if @out.include? s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def handle_exit
|
35
|
+
@stdout
|
36
|
+
end
|
37
|
+
|
38
|
+
def write(data)
|
39
|
+
@node.fmt.write data
|
40
|
+
@channel.send_data "#{data}\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Mybot
|
2
|
+
module Commands
|
3
|
+
include Messages
|
4
|
+
|
5
|
+
def node(host, user, options = {})
|
6
|
+
Node.new(host, user, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def namespace(name)
|
10
|
+
outer_ns, @namespace = @namespace, name.to_s
|
11
|
+
if outer_ns && outer_ns != ""
|
12
|
+
@namespace = "#{outer_ns}:#{@namespace}"
|
13
|
+
end
|
14
|
+
|
15
|
+
yield
|
16
|
+
ensure
|
17
|
+
@namespace = outer_ns
|
18
|
+
end
|
19
|
+
|
20
|
+
def task(name, &block)
|
21
|
+
name, deps = *case name
|
22
|
+
when Hash
|
23
|
+
name.shift
|
24
|
+
else
|
25
|
+
[name, []]
|
26
|
+
end
|
27
|
+
|
28
|
+
namespaced_deps = Array(deps).map do |d|
|
29
|
+
case d
|
30
|
+
when Symbol
|
31
|
+
"#{@namespace}:#{d}"
|
32
|
+
when String
|
33
|
+
if d.include? ":"
|
34
|
+
d
|
35
|
+
else
|
36
|
+
"#{@namespace}:#{d}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end.uniq
|
40
|
+
|
41
|
+
task = tasks.find do |t|
|
42
|
+
t[:name] == name.to_s && t[:namespace] == @namespace
|
43
|
+
end
|
44
|
+
|
45
|
+
tasks.push({
|
46
|
+
:name => name.to_s,
|
47
|
+
:namespace => @namespace,
|
48
|
+
:deps => namespaced_deps,
|
49
|
+
:block => block
|
50
|
+
}) unless task
|
51
|
+
end
|
52
|
+
|
53
|
+
def tpl(content)
|
54
|
+
Template.new(content)
|
55
|
+
end
|
56
|
+
|
57
|
+
def tpl_file(file)
|
58
|
+
tpl = File.join(TPL_PATH, file)
|
59
|
+
fatal "template file '#{tpl}' does not exists" unless File.exists?(tpl)
|
60
|
+
Template.new(File.read(tpl))
|
61
|
+
end
|
62
|
+
|
63
|
+
def wait
|
64
|
+
$stdout.print "Press any key to continue..."
|
65
|
+
$stdin.gets
|
66
|
+
end
|
67
|
+
|
68
|
+
def ask(q)
|
69
|
+
$stdout.print "#{q}?: "
|
70
|
+
$stdin.gets.chomp
|
71
|
+
end
|
72
|
+
|
73
|
+
def yes?(q)
|
74
|
+
result = ""
|
75
|
+
loop do
|
76
|
+
$stdout.print "#{q} (y/n)?: "
|
77
|
+
result = $stdin.gets.chomp
|
78
|
+
break if result =~ /y|yes|Y|YES|Yes|n|no|N|NO|No/
|
79
|
+
end
|
80
|
+
|
81
|
+
result =~ /y|yes|Y|YES|Yes/
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/mybot/fmt.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require "colored"
|
2
|
+
|
3
|
+
module Mybot
|
4
|
+
class Fmt
|
5
|
+
attr_accessor :use_color, :show_cmd,
|
6
|
+
:show_stdout, :show_stderr, :show_stdin
|
7
|
+
|
8
|
+
def initialize(host, user)
|
9
|
+
@host, @user = host, user
|
10
|
+
@use_color = true
|
11
|
+
@show_cmd = true
|
12
|
+
@show_stdout = true
|
13
|
+
@show_stderr = true
|
14
|
+
@show_stdin = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def run(cmd)
|
18
|
+
run_format = "RUN"
|
19
|
+
run_format = run_format.blue.bold if @use_color
|
20
|
+
$stdout.print "#{prompt} #{run_format} #{cmd}\n" if @show_cmd
|
21
|
+
end
|
22
|
+
|
23
|
+
def stdout(data)
|
24
|
+
data = data.green if @use_color
|
25
|
+
$stdout.print(data) if @show_stdout
|
26
|
+
end
|
27
|
+
|
28
|
+
def stderr(data)
|
29
|
+
data = data.red if @use_color
|
30
|
+
$stdout.print(data) if @show_stderr
|
31
|
+
end
|
32
|
+
|
33
|
+
def write(data)
|
34
|
+
write_format = "WRITE"
|
35
|
+
write_format = write_format.blue.bold if @use_color
|
36
|
+
enter_format = "<ENTER>"
|
37
|
+
enter_format = enter_format.red.bold if @use_color
|
38
|
+
if @show_stdin
|
39
|
+
$stdout.print "#{prompt} #{write_format} #{data}#{enter_format}\n"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def upload(from, to)
|
44
|
+
upload_format = "UPLOAD"
|
45
|
+
upload_format = upload_format.blue.bold if @use_color
|
46
|
+
|
47
|
+
if @show_cmd
|
48
|
+
$stdout.print "#{prompt} #{upload_format} #{from} -> #{to}\n"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def download(from, to)
|
53
|
+
download_format = "DOWNLOAD"
|
54
|
+
download_format = download_format.blue.bold if @use_color
|
55
|
+
|
56
|
+
|
57
|
+
if @show_cmd
|
58
|
+
$stdout.print "#{prompt} #{download_format} #{from} -> #{to}\n"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def progress(n)
|
63
|
+
if @show_cmd
|
64
|
+
$stdout.print "\r#{n}%"
|
65
|
+
puts if n == 100
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def error(msg)
|
70
|
+
error_format = "ERROR"
|
71
|
+
error_format = error_format.bold.red if @use_color
|
72
|
+
$stdout.print "#{prompt} #{error_format} #{msg}\n"
|
73
|
+
end
|
74
|
+
|
75
|
+
def fatal(msg)
|
76
|
+
error(msg)
|
77
|
+
abort
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def prompt
|
83
|
+
p ="[#{@user}@#{@host}]"
|
84
|
+
p = p.bold if @use_color
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mybot
|
2
|
+
module Messages
|
3
|
+
def info(msg)
|
4
|
+
puts "info: #{msg}"
|
5
|
+
end
|
6
|
+
|
7
|
+
def warning(msg)
|
8
|
+
puts "warning: #{msg}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def error(msg)
|
12
|
+
puts "error: #{msg}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def fatal(msg)
|
16
|
+
puts "fatal: #{msg}"
|
17
|
+
abort
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/mybot/node.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require "net/ssh"
|
2
|
+
require "net/sftp"
|
3
|
+
|
4
|
+
module Mybot
|
5
|
+
class Node
|
6
|
+
attr_accessor :host, :user, :ssh, :sftp, :fmt
|
7
|
+
|
8
|
+
def initialize(host, user, options = {})
|
9
|
+
@host, @user, @options = host, user, options
|
10
|
+
@fmt = Fmt.new(@host, @user)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ssh
|
14
|
+
@ssh ||= Net::SSH.start(@host, @user, @options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def sftp
|
18
|
+
@sftp ||= Net::SFTP.start(@host, @user, @options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def run(options, &block)
|
22
|
+
@fmt.fatal "cmd not specified" unless options[:cmd]
|
23
|
+
|
24
|
+
command = Command.new(self)
|
25
|
+
yield command if block_given?
|
26
|
+
|
27
|
+
ssh.open_channel do |ch|
|
28
|
+
ch.request_pty do |ch, ok|
|
29
|
+
@fmt.fatal "cannot request pty" unless ok
|
30
|
+
end
|
31
|
+
|
32
|
+
command.channel = ch
|
33
|
+
@fmt.run(options[:cmd])
|
34
|
+
|
35
|
+
ch.exec options[:cmd] do |ch, ok|
|
36
|
+
@fmt.fatal "run: cannot exec #{options[:cmd]}" unless ok
|
37
|
+
|
38
|
+
ch.on_data do |ch, data|
|
39
|
+
command.handle_stdout(data)
|
40
|
+
end
|
41
|
+
|
42
|
+
ch.on_extended_data do |ch, data|
|
43
|
+
command.handle_stderr(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
ch.on_request("exit-status") do |ch, data|
|
47
|
+
command.exit_status = data.read_long
|
48
|
+
end
|
49
|
+
|
50
|
+
ch.on_close do |ch|
|
51
|
+
return command.handle_exit
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ssh.loop
|
57
|
+
return command.stdout_all
|
58
|
+
end
|
59
|
+
|
60
|
+
def exists?(options)
|
61
|
+
@fmt.fatal "exists?: file not specified" unless options[:file]
|
62
|
+
|
63
|
+
options[:cmd] = "test -e #{options[:file]} && echo EXISTS"
|
64
|
+
run(options).include?("EXISTS") ? true : false
|
65
|
+
end
|
66
|
+
|
67
|
+
def create(options)
|
68
|
+
@fmt.fatal "create: file not specified" unless options[:file]
|
69
|
+
|
70
|
+
options[:cmd] = "mktemp /tmp/mybot.XXXXX"
|
71
|
+
tmp = run(options)
|
72
|
+
|
73
|
+
options[:content] ||= ""
|
74
|
+
sftp.file.open(tmp, "w") { |f| f.write options[:content] }
|
75
|
+
options[:cmd] = "mv #{tmp} #{options[:file]}"
|
76
|
+
run(options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def read(options)
|
80
|
+
@fmt.fatal "read: file not specified" unless options[:file]
|
81
|
+
|
82
|
+
options[:cmd] = "cat #{options[:file]}"
|
83
|
+
run(options) do |cmd|
|
84
|
+
cmd.on "No such file or directory" do
|
85
|
+
@fmt.error "read: file '#{options[:file]}' does not exists"
|
86
|
+
return ""
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def upload(options)
|
92
|
+
@fmt.fatal "upload: from not specified" unless options[:from]
|
93
|
+
@fmt.fatal "upload: to not specified" unless options[:to]
|
94
|
+
@fmt.upload(options[:from], options[:to])
|
95
|
+
|
96
|
+
sftp.upload!(options[:from], options[:to]) do |event, uploader, *args|
|
97
|
+
case event
|
98
|
+
when :put
|
99
|
+
n = (args[1].to_f * 100 / args[0].size.to_f).to_i
|
100
|
+
@fmt.progress(n)
|
101
|
+
when :finish
|
102
|
+
@fmt.progress(100)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def download(options)
|
108
|
+
@fmt.fatal "download: from not specified" unless options[:from]
|
109
|
+
@fmt.fatal "download: to not specified" unless options[:to]
|
110
|
+
@fmt.download(options[:from], options[:to])
|
111
|
+
|
112
|
+
sftp.download!(options[:from], options[:to]) do |event, uploader, *args|
|
113
|
+
case event
|
114
|
+
when :get
|
115
|
+
size = args[0].size ? args[0].size : sftp.stat!(options[:from]).size
|
116
|
+
n = (args[1].to_f * 100 / size.to_f).to_i
|
117
|
+
@fmt.progress(n)
|
118
|
+
when :finish
|
119
|
+
@fmt.progress(100)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Mybot
|
2
|
+
module Recipes
|
3
|
+
def recipes
|
4
|
+
@recipes ||= (
|
5
|
+
Dir[File.join(GEM_PATH, "Botfile")] +
|
6
|
+
Dir[File.join(MYBOT_PATH, "tasks", "**", "*.rb")].flatten +
|
7
|
+
Dir[File.join(".mybot", "**", "*.rb")].flatten +
|
8
|
+
Dir["Botfile"]
|
9
|
+
).reject { |f| !File.exists?(f) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def load_recipes
|
13
|
+
recipes.each { |r| self.load_recipe(r) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_recipe(r)
|
17
|
+
instance_eval(File.read(r), __FILE__, __LINE__)
|
18
|
+
rescue Exception => e
|
19
|
+
puts "error: cannot load recipe #{r}"
|
20
|
+
raise(e)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/mybot/tasks.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Mybot
|
2
|
+
module Tasks
|
3
|
+
include Messages
|
4
|
+
|
5
|
+
def tasks
|
6
|
+
@tasks ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_task(name)
|
10
|
+
ns = name.split ":"
|
11
|
+
task = ns.pop
|
12
|
+
ns = ns.join ":"
|
13
|
+
|
14
|
+
tasks.find do |t|
|
15
|
+
t[:name] == task && (t[:namespace] == ns || t[:namespace].nil?)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def run_task(name)
|
20
|
+
task = find_task(name)
|
21
|
+
|
22
|
+
unless task
|
23
|
+
error "cannot find task '#{name}'"
|
24
|
+
find_task("mybot:tasks:list")[:block].call
|
25
|
+
abort
|
26
|
+
end
|
27
|
+
|
28
|
+
task[:deps].each do |d|
|
29
|
+
run_task(d)
|
30
|
+
end
|
31
|
+
|
32
|
+
task[:block].call
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/mybot.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mybot/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mybot"
|
8
|
+
spec.version = Mybot::VERSION
|
9
|
+
spec.authors = ["Sebastian Sito"]
|
10
|
+
spec.email = ["sebastian@hypenode.com"]
|
11
|
+
spec.description = %q{Provision, manage and monitor stuff}
|
12
|
+
spec.summary = %q{Mybot, your personal bot}
|
13
|
+
spec.homepage = "https://github.com/sebastiansito/mybot"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "thor"
|
22
|
+
spec.add_dependency "fog"
|
23
|
+
spec.add_dependency "colored"
|
24
|
+
spec.add_dependency "net-ssh"
|
25
|
+
spec.add_dependency "net-sftp"
|
26
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mybot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sebastian Sito
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: thor
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: fog
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: colored
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: net-ssh
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: net-sftp
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: Provision, manage and monitor stuff
|
95
|
+
email:
|
96
|
+
- sebastian@hypenode.com
|
97
|
+
executables:
|
98
|
+
- bot
|
99
|
+
extensions: []
|
100
|
+
extra_rdoc_files: []
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- Botfile
|
104
|
+
- Gemfile
|
105
|
+
- LICENSE.txt
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- bin/bot
|
109
|
+
- lib/mybot.rb
|
110
|
+
- lib/mybot/base.rb
|
111
|
+
- lib/mybot/cli.rb
|
112
|
+
- lib/mybot/command.rb
|
113
|
+
- lib/mybot/commands.rb
|
114
|
+
- lib/mybot/fmt.rb
|
115
|
+
- lib/mybot/messages.rb
|
116
|
+
- lib/mybot/node.rb
|
117
|
+
- lib/mybot/recipes.rb
|
118
|
+
- lib/mybot/tasks.rb
|
119
|
+
- lib/mybot/template.rb
|
120
|
+
- lib/mybot/version.rb
|
121
|
+
- mybot.gemspec
|
122
|
+
- vendor/lib/mybot/.gitkeep
|
123
|
+
- vendor/tasks/.gitkeep
|
124
|
+
- vendor/tpl/mybot/.gitkeep
|
125
|
+
homepage: https://github.com/sebastiansito/mybot
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ! '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
requirements: []
|
145
|
+
rubyforge_project:
|
146
|
+
rubygems_version: 1.8.23
|
147
|
+
signing_key:
|
148
|
+
specification_version: 3
|
149
|
+
summary: Mybot, your personal bot
|
150
|
+
test_files: []
|