blower 0.2.3
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.
- checksums.yaml +7 -0
- data/bin/blow +24 -0
- data/lib/blower/huff.rb +56 -0
- data/lib/blower/logger.rb +44 -0
- data/lib/blower/puff.rb +57 -0
- data/lib/blower/version.rb +3 -0
- data/lib/blower.rb +4 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 52e337abe103b677ac90233cfd4f38121585fe0b
|
4
|
+
data.tar.gz: 47e87f53486d3b7ec27e2abc78d24098b5759e0d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f250fa25824a1e5c003cadb0102f90305fd6e536b7a4602021a7222ddf7d3259e2870e4dc5d4efd5d1f617367474f541be6ec1f1d784b164c6f621a00bbec87
|
7
|
+
data.tar.gz: 518c595f5587dc82b6ef0b2fb831c095e237c407c614807e56e7e126d72d58a66c7a530552fd4ca1f3bf61ad990e271c472445a3c5bcfe944ae152d37f8edbda
|
data/bin/blow
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'blower'
|
4
|
+
|
5
|
+
huff = Blower::Huff.new
|
6
|
+
|
7
|
+
args = ARGV
|
8
|
+
args = ["main"] if args.empty? && (File.exist?("main") || !Dir["main.*"].empty?)
|
9
|
+
|
10
|
+
if args.empty?
|
11
|
+
huff.log.fail "Usage: blow TASK..."
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
|
15
|
+
args = ["hosts.ini", *args] if File.exist?("hosts.ini")
|
16
|
+
|
17
|
+
begin
|
18
|
+
args.each do |arg|
|
19
|
+
huff.run arg
|
20
|
+
end
|
21
|
+
rescue RuntimeError => e
|
22
|
+
huff.log.fail e.message
|
23
|
+
exit 1
|
24
|
+
end
|
data/lib/blower/huff.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Blower
|
2
|
+
class Huff
|
3
|
+
|
4
|
+
attr_accessor :hosts, :log, :puffs, :env
|
5
|
+
|
6
|
+
def initialize ()
|
7
|
+
@hosts = ["127.0.0.1"]
|
8
|
+
@log = Logger.new
|
9
|
+
@logdent = 0
|
10
|
+
@puffs = Hash.new { |h, k| h[k] = Puff.new(self, k) }
|
11
|
+
@env = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def hosts (hosts)
|
15
|
+
log.info "new hosts: #{hosts.join(", ")}"
|
16
|
+
@hosts = hosts
|
17
|
+
end
|
18
|
+
|
19
|
+
def ruby (task)
|
20
|
+
instance_eval(File.read(task), task)
|
21
|
+
end
|
22
|
+
|
23
|
+
def shell (task)
|
24
|
+
@hosts.each do |host|
|
25
|
+
log.info "running #{task} on #{host}" do
|
26
|
+
puffs[host].shell(task)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def inventory (task)
|
32
|
+
hosts File.read(task).split
|
33
|
+
end
|
34
|
+
|
35
|
+
def run (name)
|
36
|
+
name = name.to_s
|
37
|
+
task = File.exist?(name) ? name : Dir[name + ".*"].first
|
38
|
+
if !task
|
39
|
+
fail "Can't find #{name}"
|
40
|
+
elsif File.directory?(task)
|
41
|
+
Dir.chdir(task) do
|
42
|
+
run("main")
|
43
|
+
end
|
44
|
+
elsif task =~ /\.rb$/
|
45
|
+
ruby(task)
|
46
|
+
elsif task =~ /\.sh$/
|
47
|
+
shell(task)
|
48
|
+
elsif task =~ /\.ini$/
|
49
|
+
inventory(task)
|
50
|
+
else
|
51
|
+
fail "Don't know what to do with #{task}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "colorize"
|
2
|
+
|
3
|
+
module Blower
|
4
|
+
class Logger
|
5
|
+
|
6
|
+
def initialize ()
|
7
|
+
@logdent = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def info (message, **keys, &block)
|
11
|
+
log(message, :blue, **keys, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def warn (message, **keys, &block)
|
15
|
+
log(message, :yellow, STDERR, **keys, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def fail (message, **keys, &block)
|
19
|
+
log(message, :red, STDERR, **keys, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def win (message, **keys, &block)
|
23
|
+
log(message, :green, **keys, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def log (message, color=nil, to=STDOUT, prefix: "", &block)
|
27
|
+
message.to_s.scan(/(?:[^\n\r]*[\n\r])|(?:[^\n\r]+$)/) do |line|
|
28
|
+
case line[-1]
|
29
|
+
when "\n", "\r"
|
30
|
+
else
|
31
|
+
line = line + "\n"
|
32
|
+
end
|
33
|
+
STDOUT.write " " * @logdent + prefix + (color ? line.colorize(color) : line)
|
34
|
+
end
|
35
|
+
begin
|
36
|
+
@logdent +=1
|
37
|
+
block.()
|
38
|
+
ensure
|
39
|
+
@logdent -= 1
|
40
|
+
end if block
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/blower/puff.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "net/ssh"
|
2
|
+
require "shellwords"
|
3
|
+
|
4
|
+
module Blower
|
5
|
+
class Puff
|
6
|
+
|
7
|
+
attr_accessor :huff, :host, :log, :env
|
8
|
+
|
9
|
+
def initialize (huff, host)
|
10
|
+
@huff = huff
|
11
|
+
@log = huff.log
|
12
|
+
@host = host
|
13
|
+
@env = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def env2shell ()
|
17
|
+
huff.env.merge(@env).map do |name, value|
|
18
|
+
next unless name =~ /\A[A-Za-z\d_]+\z/
|
19
|
+
"#{name}=#{value.shellescape}"
|
20
|
+
end.join("\n") + "\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def shell (task)
|
24
|
+
Net::SSH.start(host, "root") do |ssh|
|
25
|
+
command = File.read(task)
|
26
|
+
status, signal = nil, nil
|
27
|
+
ssh.open_channel do |ch|
|
28
|
+
stdout, stderr = "", ""
|
29
|
+
ch.exec(env2shell + command) do |_, success|
|
30
|
+
fail "failed to execute command" unless success
|
31
|
+
ch.on_data do |_, data|
|
32
|
+
stdout << data
|
33
|
+
if i = stdout.rindex(/[\n\r]/)
|
34
|
+
data, stdout = stdout[0..i], (stdout[(i + 1)..-1] || "")
|
35
|
+
log.log data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
ch.on_extended_data do |_, _, data|
|
39
|
+
stderr << data
|
40
|
+
if i = stderr.rindex(/[\n\r]/)
|
41
|
+
data, stderr = stderr[0..i], (stderr[(i + 1)..-1] || "")
|
42
|
+
log.fail data
|
43
|
+
end
|
44
|
+
end
|
45
|
+
ch.on_request("exit-status") { |_, data| status = data.read_long }
|
46
|
+
ch.on_request("exit-signal") { |_, data| signal = data.read_long }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
ssh.loop
|
50
|
+
if status != 0
|
51
|
+
fail "exit status #{status}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/blower.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blower
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Baum
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: net-ssh
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: colorize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.7'
|
41
|
+
description: Really simple server orchestration
|
42
|
+
email: n@p12a.org.uk
|
43
|
+
executables:
|
44
|
+
- blow
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- bin/blow
|
49
|
+
- lib/blower.rb
|
50
|
+
- lib/blower/huff.rb
|
51
|
+
- lib/blower/logger.rb
|
52
|
+
- lib/blower/puff.rb
|
53
|
+
- lib/blower/version.rb
|
54
|
+
homepage: http://www.github.org/nbaum/blower
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.4.5.1
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Really simple server orchestration
|
78
|
+
test_files: []
|