hocho 0.1.0.beta1 → 0.2.0
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 +4 -4
- data/README.md +16 -5
- data/lib/hocho/command.rb +1 -4
- data/lib/hocho/drivers/base.rb +3 -0
- data/lib/hocho/drivers/bundler.rb +8 -44
- data/lib/hocho/drivers/mitamae.rb +87 -0
- data/lib/hocho/drivers/ssh_base.rb +122 -2
- data/lib/hocho/host.rb +48 -29
- data/lib/hocho/inventory.rb +14 -2
- data/lib/hocho/inventory_providers/file.rb +1 -1
- data/lib/hocho/property_providers.rb +1 -1
- data/lib/hocho/property_providers/add_default.rb +15 -0
- data/lib/hocho/runner.rb +4 -1
- data/lib/hocho/version.rb +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71a35bcabdd7fb28b6ddcde2093f7cdde9ddcafa
|
4
|
+
data.tar.gz: f4ac549145b6940d4bef0ade7b3338d3f89f2028
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c5e35fb5d3d3263ae7fab63fb51d846ba3ce5bb41421dd43f8731dd256081f0e712f11c192aef676140ab8801adfc558927a71574fa5b32b5f7ef29f29dd2bd7
|
7
|
+
data.tar.gz: 82ecb70f5dbb71f3be59e3d5dd9c42e9c4d733604038d8d296eb94e2795e629dc779ede9de00df8ccf28efce72827ccdb4550d82854391c1ca06b3e929f49b97
|
data/README.md
CHANGED
@@ -4,14 +4,15 @@ Hocho is a wrapper of the provisioning tool [itamae](https://github.com/itamae-k
|
|
4
4
|
|
5
5
|
## Features
|
6
6
|
|
7
|
-
-
|
8
|
-
-
|
7
|
+
- Drivers
|
8
|
+
- `itamae ssh` support
|
9
|
+
- remote `itamae local` support on rsync+bundler
|
10
|
+
- remote `mitamae` support
|
9
11
|
- Simple pluggable host inventory, discovery
|
10
12
|
|
11
|
-
## vs. other softwares
|
12
|
-
|
13
13
|
## Installation
|
14
14
|
|
15
|
+
|
15
16
|
Add this line to your application's Gemfile:
|
16
17
|
|
17
18
|
```ruby
|
@@ -33,14 +34,24 @@ Or install it yourself as:
|
|
33
34
|
inventory_providers:
|
34
35
|
file:
|
35
36
|
path: './hosts'
|
37
|
+
property_providers:
|
38
|
+
- add_default:
|
39
|
+
properties:
|
40
|
+
blah: blahblah
|
41
|
+
# preferred_driver: mitamae
|
42
|
+
# driver_options:
|
43
|
+
# mitamae:
|
44
|
+
# mitamae_prepare_script: 'wget -O /usr/local/bin/mitamae https://...'
|
36
45
|
```
|
37
46
|
|
38
|
-
```
|
47
|
+
``` yaml
|
39
48
|
# ./hosts/test.yml
|
40
49
|
test.example.org:
|
41
50
|
# ssh_options:
|
42
51
|
# user: ...
|
43
52
|
properties:
|
53
|
+
# preferred_driver: bundler
|
54
|
+
# preferred_driver: mitamae
|
44
55
|
run_list:
|
45
56
|
- roles/app/default.rb
|
46
57
|
```
|
data/lib/hocho/command.rb
CHANGED
@@ -17,9 +17,6 @@ module Hocho
|
|
17
17
|
hosts = inventory.hosts
|
18
18
|
|
19
19
|
if options[:verbose]
|
20
|
-
hosts.each do |host|
|
21
|
-
config.property_providers.each { |_| _.determine(host) }
|
22
|
-
end
|
23
20
|
case options[:format]
|
24
21
|
when 'yaml'
|
25
22
|
puts hosts.map(&:to_h).to_yaml
|
@@ -82,7 +79,7 @@ module Hocho
|
|
82
79
|
private
|
83
80
|
|
84
81
|
def inventory
|
85
|
-
@inventory ||= Hocho::Inventory.new(config.inventory_providers)
|
82
|
+
@inventory ||= Hocho::Inventory.new(config.inventory_providers, config.property_providers)
|
86
83
|
end
|
87
84
|
|
88
85
|
def config
|
data/lib/hocho/drivers/base.rb
CHANGED
@@ -3,35 +3,22 @@ require 'hocho/drivers/ssh_base'
|
|
3
3
|
module Hocho
|
4
4
|
module Drivers
|
5
5
|
class Bundler < SshBase
|
6
|
-
def initialize(host, base_dir: '.', initializers: [], itamae_options: [], bundle_without: [], bundle_path: nil,
|
6
|
+
def initialize(host, base_dir: '.', initializers: [], itamae_options: [], bundle_without: [], bundle_path: nil, deploy_options: {})
|
7
7
|
super host, base_dir: base_dir, initializers: initializers
|
8
8
|
|
9
9
|
@itamae_options = itamae_options
|
10
10
|
@bundle_without = bundle_without
|
11
11
|
@bundle_path = bundle_path
|
12
|
-
@
|
13
|
-
@keep_synced_files = keep_synced_files
|
14
|
-
end
|
15
|
-
|
16
|
-
def keep_synced_files?
|
17
|
-
@keep_synced_files
|
12
|
+
@deploy_options = deploy_options
|
18
13
|
end
|
19
14
|
|
20
15
|
def run(dry_run: false)
|
21
|
-
deploy
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
cleanup
|
16
|
+
deploy(**@deploy_options) do
|
17
|
+
bundle_install
|
18
|
+
run_itamae(dry_run: dry_run)
|
19
|
+
end
|
26
20
|
end
|
27
21
|
|
28
|
-
def deploy
|
29
|
-
ssh_cmd = ['ssh', *host.openssh_config.flat_map { |l| ['-o', "\"#{l}\""] }].join(' ')
|
30
|
-
rsync_cmd = [*%w(rsync -az --copy-links --copy-unsafe-links --delete --exclude=.git), '--rsh', ssh_cmd, '.', "#{host.hostname}:#{host_basedir}"]
|
31
|
-
|
32
|
-
puts "=> $ #{rsync_cmd.inspect}"
|
33
|
-
system(*rsync_cmd, chdir: base_dir) or raise 'failed to rsync'
|
34
|
-
end
|
35
22
|
|
36
23
|
def bundle_install
|
37
24
|
bundle_path_env = @bundle_path ? "BUNDLE_PATH=#{@bundle_path.shellescape} " : nil
|
@@ -46,12 +33,7 @@ module Hocho
|
|
46
33
|
puts "=> #{host.name} # #{bundle_install.shelljoin}"
|
47
34
|
|
48
35
|
ssh_run("bash") do |c|
|
49
|
-
c
|
50
|
-
puts "[#{host.name}] #{data}"
|
51
|
-
end
|
52
|
-
c.on_extended_data do |c, _, data|
|
53
|
-
puts "[#{host.name}/ERR] #{data}"
|
54
|
-
end
|
36
|
+
set_ssh_output_hook(c)
|
55
37
|
|
56
38
|
c.send_data("cd #{host_basedir.shellescape}\n#{sudovars}\n#{sudocmd}#{bundle_install.shelljoin}\n")
|
57
39
|
c.eof!
|
@@ -69,12 +51,7 @@ module Hocho
|
|
69
51
|
prepare_sudo do |sh, sudovars, sudocmd|
|
70
52
|
puts "=> #{host.name} # #{host.bundler_cmd} exec #{itamae_cmd.shelljoin}"
|
71
53
|
ssh_run("bash") do |c|
|
72
|
-
c
|
73
|
-
puts "[#{host.name}] #{data}"
|
74
|
-
end
|
75
|
-
c.on_extended_data do |c, _, data|
|
76
|
-
puts "[#{host.name}/ERR] #{data}"
|
77
|
-
end
|
54
|
+
set_ssh_output_hook(c)
|
78
55
|
|
79
56
|
c.send_data("cd #{host_basedir.shellescape}\n#{sudovars}\n#{sudocmd}#{host.bundler_cmd} exec #{itamae_cmd.shelljoin}\n")
|
80
57
|
c.eof!
|
@@ -82,19 +59,6 @@ module Hocho
|
|
82
59
|
end
|
83
60
|
end
|
84
61
|
end
|
85
|
-
|
86
|
-
def cleanup
|
87
|
-
return unless !keep_synced_files? || !deploy_dir
|
88
|
-
|
89
|
-
cmd = "rm -rf #{host_basedir.shellescape}"
|
90
|
-
puts "=> #{host.name} $ #{cmd}"
|
91
|
-
ssh_run(cmd, error: false)
|
92
|
-
end
|
93
|
-
|
94
|
-
def host_basedir
|
95
|
-
@deploy_dir || "#{host_tmpdir}/itamae"
|
96
|
-
end
|
97
|
-
|
98
62
|
end
|
99
63
|
end
|
100
64
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'hocho/drivers/ssh_base'
|
2
|
+
|
3
|
+
module Hocho
|
4
|
+
module Drivers
|
5
|
+
class Mitamae < SshBase
|
6
|
+
def initialize(host, base_dir: '.', mitamae_path: 'mitamae', mitamae_prepare_script: [], mitamae_outdate_check_script: nil, initializers: [], mitamae_options: [], deploy_options: {})
|
7
|
+
super host, base_dir: base_dir, initializers: initializers
|
8
|
+
|
9
|
+
@mitamae_path = mitamae_path
|
10
|
+
@mitamae_prepare_script = mitamae_prepare_script
|
11
|
+
@mitamae_outdate_check_script = mitamae_outdate_check_script
|
12
|
+
@mitamae_options = mitamae_options
|
13
|
+
@deploy_options = deploy_options
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def run(dry_run: false)
|
18
|
+
deploy(**@deploy_options) do
|
19
|
+
prepare_mitamae
|
20
|
+
run_mitamae(dry_run: dry_run)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def mitamae_available?
|
25
|
+
exitstatus, _ = if @mitamae_path.start_with?('/')
|
26
|
+
ssh_run("test -x #{@mitamae_path.shellescape}", error: false)
|
27
|
+
else
|
28
|
+
ssh_run("which #{@mitamae_path.shellescape} 2>/dev/null >/dev/null", error: false)
|
29
|
+
end
|
30
|
+
exitstatus == 0
|
31
|
+
end
|
32
|
+
|
33
|
+
def mitamae_outdated?
|
34
|
+
if @mitamae_outdate_check_script
|
35
|
+
exitstatus, _ = ssh_run("export HOCHO_MITAMAE_PATH=#{@mitamae_path.shellescape}; #{@mitamae_outdate_check_script}", error: false)
|
36
|
+
exitstatus == 0
|
37
|
+
else
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def prepare_mitamae
|
43
|
+
return if mitamae_available? && !mitamae_outdated?
|
44
|
+
script = [*@mitamae_prepare_script].join("\n\n")
|
45
|
+
if script.empty?
|
46
|
+
raise "We have to prepare MItamae, but not mitamae_prepare_script is specified"
|
47
|
+
end
|
48
|
+
prepare_sudo do |sh, sudovars, sudocmd|
|
49
|
+
log_prefix = "=> #{host.name} # "
|
50
|
+
log_prefix_white = ' ' * log_prefix.size
|
51
|
+
puts "#{log_prefix}#{script.each_line.map{ |_| "#{log_prefix_white}#{_.chomp}" }.join("\n")}"
|
52
|
+
|
53
|
+
ssh_run("bash") do |c|
|
54
|
+
set_ssh_output_hook(c)
|
55
|
+
|
56
|
+
c.send_data("cd #{host_basedir.shellescape}\n#{sudovars}\n#{sudocmd} bash <<-'HOCHOEOS'\n#{script}HOCHOEOS\n")
|
57
|
+
c.eof!
|
58
|
+
end
|
59
|
+
end
|
60
|
+
availability, outdated = mitamae_available?, mitamae_outdated?
|
61
|
+
if !availability || outdated
|
62
|
+
status = [availability ? nil : 'unavailable', outdated ? 'outdated' : nil].compact.join(' and ')
|
63
|
+
raise "prepared MItamae, but it's still #{status}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def run_mitamae(dry_run: false)
|
68
|
+
with_host_node_json_file do
|
69
|
+
itamae_cmd = [@mitamae_path, 'local', '-j', host_node_json_path, *@mitamae_options]
|
70
|
+
itamae_cmd.push('--dry-run') if dry_run
|
71
|
+
# itamae_cmd.push('--color') if $stdout.tty?
|
72
|
+
itamae_cmd.push(*run_list)
|
73
|
+
|
74
|
+
prepare_sudo do |sh, sudovars, sudocmd|
|
75
|
+
puts "=> #{host.name} # #{itamae_cmd.shelljoin}"
|
76
|
+
ssh_run("bash") do |c|
|
77
|
+
set_ssh_output_hook(c)
|
78
|
+
|
79
|
+
c.send_data("cd #{host_basedir.shellescape}\n#{sudovars}\n#{sudocmd} #{itamae_cmd.shelljoin}\n")
|
80
|
+
c.eof!
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -9,6 +9,47 @@ module Hocho
|
|
9
9
|
host.ssh_connection
|
10
10
|
end
|
11
11
|
|
12
|
+
def finalize
|
13
|
+
remove_host_tmpdir!
|
14
|
+
remove_host_shmdir!
|
15
|
+
end
|
16
|
+
|
17
|
+
def deploy(deploy_dir: nil, shm_prefix: [])
|
18
|
+
@host_basedir = deploy_dir if deploy_dir
|
19
|
+
|
20
|
+
shm_prefix = [*shm_prefix]
|
21
|
+
|
22
|
+
ssh_cmd = ['ssh', *host.openssh_config.flat_map { |l| ['-o', "\"#{l}\""] }].join(' ')
|
23
|
+
shm_exclude = shm_prefix.map{ |_| "--exclude=#{_}" }
|
24
|
+
rsync_cmd = [*%w(rsync -az --copy-links --copy-unsafe-links --delete --exclude=.git), *shm_exclude, '--rsh', ssh_cmd, '.', "#{host.hostname}:#{host_basedir}"]
|
25
|
+
|
26
|
+
puts "=> $ #{rsync_cmd.shelljoin}"
|
27
|
+
system(*rsync_cmd, chdir: base_dir) or raise 'failed to rsync'
|
28
|
+
|
29
|
+
unless shm_prefix.empty?
|
30
|
+
shm_include = shm_prefix.map{ |_| "--include=#{_.sub(%r{/\z},'')}/***" }
|
31
|
+
rsync_cmd = [*%w(rsync -az --copy-links --copy-unsafe-links --delete), *shm_include, '--exclude=*', '--rsh', ssh_cmd, '.', "#{host.hostname}:#{host_shm_basedir}"]
|
32
|
+
puts "=> $ #{rsync_cmd.shelljoin}"
|
33
|
+
system(*rsync_cmd, chdir: base_dir) or raise 'failed to rsync'
|
34
|
+
shm_prefix.each do |x|
|
35
|
+
mkdir = if %r{\A[^/].*\/.+\z} === x
|
36
|
+
%Q(mkdir -vp "$(basename #{x.shellescape})" &&)
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
ssh_run(%Q(cd #{host_basedir} && #{mkdir} ln -sfv #{host_shm_basedir}/#{x.shellescape} ./#{x.sub(%r{/\z},'').shellescape}))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
if !deploy_dir || !keep_synced_files
|
47
|
+
cmd = "rm -rf #{host_basedir.shellescape}"
|
48
|
+
puts "=> #{host.name} $ #{cmd}"
|
49
|
+
ssh_run(cmd, error: false)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
12
53
|
private
|
13
54
|
|
14
55
|
def prepare_sudo(password = host.sudo_password)
|
@@ -35,7 +76,8 @@ module Hocho
|
|
35
76
|
end
|
36
77
|
|
37
78
|
begin
|
38
|
-
|
79
|
+
tmpdir = host_shmdir ? "TMPDIR=#{host_shmdir.shellescape} " : nil
|
80
|
+
temp_executable = ssh.exec!("#{tmpdir}mktemp").chomp
|
39
81
|
raise unless temp_executable.start_with?('/')
|
40
82
|
|
41
83
|
ssh_run("chmod 0700 #{temp_executable.shellescape}; cat > #{temp_executable.shellescape}; chmod +x #{temp_executable.shellescape}") do |ch|
|
@@ -53,6 +95,69 @@ module Hocho
|
|
53
95
|
end
|
54
96
|
end
|
55
97
|
|
98
|
+
def set_ssh_output_hook(c)
|
99
|
+
outbuf, errbuf = [], []
|
100
|
+
check = ->(prefix,data,buf) do
|
101
|
+
has_newline = data.include?("\n")
|
102
|
+
lines = data.lines
|
103
|
+
last = lines.pop
|
104
|
+
if last[-1] == "\n"
|
105
|
+
buf << last
|
106
|
+
end
|
107
|
+
if has_newline
|
108
|
+
(buf+lines).join.each_line do |line|
|
109
|
+
puts "#{prefix} #{line}"
|
110
|
+
end
|
111
|
+
buf.replace([])
|
112
|
+
end
|
113
|
+
if last[-1] != "\n"
|
114
|
+
buf << last
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
c.on_data do |c, data|
|
119
|
+
check.call "[#{host.name}] ", data, outbuf
|
120
|
+
end
|
121
|
+
c.on_extended_data do |c, _, data|
|
122
|
+
check.call "[#{host.name}/ERR] ", data, errbuf
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def host_basedir
|
127
|
+
@host_basedir || "#{host_tmpdir}/itamae"
|
128
|
+
end
|
129
|
+
|
130
|
+
def host_shm_basedir
|
131
|
+
host_shmdir && "#{host_shmdir}/itamae"
|
132
|
+
end
|
133
|
+
|
134
|
+
def host_shmdir
|
135
|
+
return @host_shmdir if @host_shmdir
|
136
|
+
return nil if @host_shmdir == false
|
137
|
+
|
138
|
+
shmdir = host.shmdir
|
139
|
+
unless shmdir
|
140
|
+
if ssh.exec!('uname').chomp == 'Linux'
|
141
|
+
shmdir = '/dev/shm'
|
142
|
+
mount = ssh.exec!("grep -F #{shmdir.shellescape} /proc/mounts").each_line.map{ |_| _.chomp.split(' ') }
|
143
|
+
unless mount.find { |_| _[1] == shmdir }&.first == 'tmpfs'
|
144
|
+
@host_shmdir = false
|
145
|
+
return nil
|
146
|
+
end
|
147
|
+
else
|
148
|
+
@host_shmdir = false
|
149
|
+
return nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
mktemp_cmd = "TMPDIR=#{shmdir.shellescape} #{%w(mktemp -d -t hocho-run-XXXXXXXXX).shelljoin}"
|
154
|
+
|
155
|
+
res = ssh.exec!(mktemp_cmd)
|
156
|
+
unless res.start_with?(shmdir)
|
157
|
+
raise "Failed to shm mktemp #{mktemp_cmd.inspect} -> #{res.inspect}"
|
158
|
+
end
|
159
|
+
@host_shmdir = res.chomp
|
160
|
+
end
|
56
161
|
|
57
162
|
def host_tmpdir
|
58
163
|
@host_tmpdir ||= begin
|
@@ -60,13 +165,28 @@ module Hocho
|
|
60
165
|
mktemp_cmd.prepend("TMPDIR=#{host.tmpdir.shellescape} ") if host.tmpdir
|
61
166
|
|
62
167
|
res = ssh.exec!(mktemp_cmd)
|
63
|
-
unless res.start_with?('/
|
168
|
+
unless res.start_with?(host.tmpdir || '/')
|
64
169
|
raise "Failed to mktemp #{mktemp_cmd.inspect} -> #{res.inspect}"
|
65
170
|
end
|
66
171
|
res.chomp
|
67
172
|
end
|
68
173
|
end
|
69
174
|
|
175
|
+
def remove_host_tmpdir!
|
176
|
+
if @host_tmpdir
|
177
|
+
host_tmpdir, @host_tmpdir = @host_tmpdir, nil
|
178
|
+
ssh.exec!("rm -rf #{host_tmpdir.shellescape}")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def remove_host_shmdir!
|
183
|
+
if @host_shmdir
|
184
|
+
host_shmdir, @host_shmdir = @host_shmdir, nil
|
185
|
+
ssh.exec!("rm -rf #{host_shmdir.shellescape}")
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
70
190
|
def host_node_json_path
|
71
191
|
"#{host_tmpdir}/node.json"
|
72
192
|
end
|
data/lib/hocho/host.rb
CHANGED
@@ -5,28 +5,34 @@ require 'net/ssh/proxy/command'
|
|
5
5
|
|
6
6
|
module Hocho
|
7
7
|
class Host
|
8
|
-
def initialize(name, provider: nil, properties: {}, tags: {}, ssh_options: nil, tmpdir: nil, sudo_password: nil)
|
8
|
+
def initialize(name, provider: nil, providers: nil, properties: {}, tags: {}, ssh_options: nil, tmpdir: nil, shmdir: nil, sudo_password: nil)
|
9
|
+
if provider
|
10
|
+
warn "DEPRECATION WARNING: #{caller[1]}: Hocho::Host.new(provider:) is deprecated. Use providers: instead "
|
11
|
+
end
|
12
|
+
|
9
13
|
@name = name
|
10
|
-
@
|
14
|
+
@providers = [*provider, *providers]
|
11
15
|
self.properties = properties
|
12
16
|
@tags = tags
|
13
17
|
@override_ssh_options = ssh_options
|
14
18
|
@tmpdir = tmpdir
|
19
|
+
@shmdir = shmdir
|
15
20
|
@sudo_password = sudo_password
|
16
21
|
end
|
17
22
|
|
18
|
-
attr_reader :name, :
|
23
|
+
attr_reader :name, :providers, :properties, :tmpdir, :shmdir
|
19
24
|
attr_writer :sudo_password
|
20
25
|
attr_accessor :tags
|
21
26
|
|
22
27
|
def to_h
|
23
28
|
{
|
24
29
|
name: name,
|
25
|
-
|
30
|
+
providers: providers,
|
26
31
|
tags: tags.to_h,
|
27
32
|
properties: properties.to_h,
|
28
33
|
}.tap do |h|
|
29
34
|
h[:tmpdir] = tmpdir if tmpdir
|
35
|
+
h[:shmdir] = shmdir if shmdir
|
30
36
|
h[:ssh_options] = @override_ssh_options if @override_ssh_options
|
31
37
|
end
|
32
38
|
end
|
@@ -35,12 +41,23 @@ module Hocho
|
|
35
41
|
@properties = Hashie::Mash.new(other)
|
36
42
|
end
|
37
43
|
|
38
|
-
def
|
44
|
+
def merge!(other)
|
45
|
+
@tags.merge!(other.tags)
|
46
|
+
@tmpdir = other.tmpdir if other.tmpdir
|
47
|
+
@shmdir = other.shmdir if other.shmdir
|
48
|
+
@properties.merge(other.properties)
|
49
|
+
end
|
50
|
+
|
51
|
+
def apply_property_providers(providers)
|
39
52
|
providers.each do |provider|
|
40
53
|
provider.determine(self)
|
41
54
|
end
|
42
55
|
end
|
43
56
|
|
57
|
+
def ssh_name
|
58
|
+
properties[:ssh_name] || name
|
59
|
+
end
|
60
|
+
|
44
61
|
def run_list
|
45
62
|
properties[:run_list] || []
|
46
63
|
end
|
@@ -58,70 +75,72 @@ module Hocho
|
|
58
75
|
end
|
59
76
|
|
60
77
|
def ssh_options
|
61
|
-
(Net::SSH::Config.for(
|
78
|
+
(Net::SSH::Config.for(ssh_name) || {}).merge(Hocho::Utils::Symbolize.keys_of(properties[:ssh_options] || {})).merge(@override_ssh_options || {})
|
62
79
|
end
|
63
80
|
|
64
|
-
def openssh_config
|
81
|
+
def openssh_config(separator='=')
|
65
82
|
ssh_options.flat_map do |key, value|
|
66
83
|
case key
|
67
84
|
when :encryption
|
68
|
-
|
85
|
+
[["Ciphers", [*value].join(?,)]]
|
69
86
|
when :compression
|
70
|
-
|
87
|
+
[["Compression", value]]
|
71
88
|
when :compression_level
|
72
|
-
|
89
|
+
[["CompressionLevel", value]]
|
73
90
|
when :timeout
|
74
|
-
|
91
|
+
[["ConnectTimeout", value]]
|
75
92
|
when :forward_agent
|
76
|
-
|
93
|
+
[["ForwardAgent", value ? 'yes' : 'no']]
|
77
94
|
when :keys_only
|
78
|
-
|
95
|
+
[["IdentitiesOnly", value ? 'yes' : 'no']]
|
79
96
|
when :global_known_hosts_file
|
80
|
-
|
97
|
+
[["GlobalKnownHostsFile", value]]
|
81
98
|
when :auth_methods
|
82
99
|
[].tap do |lines|
|
83
100
|
methods = value.dup
|
84
101
|
value.each do |val|
|
85
102
|
case val
|
86
103
|
when 'hostbased'
|
87
|
-
lines << "HostBasedAuthentication yes"
|
104
|
+
lines << ["HostBasedAuthentication", "yes"]
|
88
105
|
when 'password'
|
89
|
-
lines << "PasswordAuthentication yes"
|
106
|
+
lines << ["PasswordAuthentication", "yes"]
|
90
107
|
when 'publickey'
|
91
|
-
lines << "PubkeyAuthentication yes"
|
108
|
+
lines << ["PubkeyAuthentication", "yes"]
|
92
109
|
end
|
93
110
|
end
|
94
111
|
unless methods.empty?
|
95
|
-
lines << "PreferredAuthentications
|
112
|
+
lines << ["PreferredAuthentications", methods.join(?,)]
|
96
113
|
end
|
97
114
|
end
|
98
115
|
when :host_key
|
99
|
-
|
116
|
+
[["HostKeyAlgorithms", [*value].join(?,)]]
|
100
117
|
when :host_key_alias
|
101
|
-
|
118
|
+
[["HostKeyAlias", value]]
|
102
119
|
when :host_name
|
103
|
-
|
120
|
+
[["HostName", value]]
|
104
121
|
when :keys
|
105
122
|
[*value].map do |val|
|
106
|
-
|
123
|
+
["IdentityFile", val]
|
107
124
|
end
|
108
125
|
when :hmac
|
109
|
-
|
126
|
+
[["Macs", [*value].join(?,)]]
|
110
127
|
when :port
|
111
|
-
|
128
|
+
[["Port", value]]
|
112
129
|
when :proxy
|
113
130
|
if value.kind_of?(Net::SSH::Proxy::Command)
|
114
|
-
|
131
|
+
[["ProxyCommand", value.command_line_template]]
|
115
132
|
else
|
116
|
-
|
133
|
+
[["ProxyCommand", value]]
|
117
134
|
end
|
118
135
|
when :rekey_limit
|
119
|
-
|
136
|
+
[["RekeyLimit", value]]
|
120
137
|
when :user
|
121
|
-
|
138
|
+
[["User", value]]
|
122
139
|
when :user_known_hosts_file
|
123
|
-
|
140
|
+
[["UserKnownHostsFile", value]]
|
124
141
|
end
|
142
|
+
end.compact.map do |keyval|
|
143
|
+
keyval.join(separator)
|
125
144
|
end
|
126
145
|
end
|
127
146
|
|
data/lib/hocho/inventory.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
module Hocho
|
2
2
|
class Inventory
|
3
|
-
def initialize(providers)
|
3
|
+
def initialize(providers, property_providers)
|
4
4
|
@providers = providers
|
5
|
+
@property_providers = property_providers
|
5
6
|
end
|
6
7
|
|
7
8
|
def hosts
|
8
|
-
@hosts ||= @providers.
|
9
|
+
@hosts ||= @providers.inject({}) do |r,provider|
|
10
|
+
provider.hosts.each do |host|
|
11
|
+
if r.key?(host.name)
|
12
|
+
r[host.name].merge!(host)
|
13
|
+
else
|
14
|
+
r[host.name] = host
|
15
|
+
end
|
16
|
+
end
|
17
|
+
r
|
18
|
+
end.each do |name, host|
|
19
|
+
host.apply_property_providers(@property_providers)
|
20
|
+
end.values
|
9
21
|
end
|
10
22
|
|
11
23
|
def filter(filters)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'hocho/property_providers/base'
|
2
|
+
|
3
|
+
module Hocho
|
4
|
+
module PropertyProviders
|
5
|
+
class AddDefault < Base
|
6
|
+
def initialize(properties: {})
|
7
|
+
@properties = properties
|
8
|
+
end
|
9
|
+
|
10
|
+
def determine(host)
|
11
|
+
host.properties.replace(host.properties.reverse_merge(@properties))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/hocho/runner.rb
CHANGED
@@ -18,7 +18,10 @@ module Hocho
|
|
18
18
|
def run(dry_run: false)
|
19
19
|
puts "Running using #{best_driver_name}"
|
20
20
|
driver_options = @driver_options[best_driver_name] || {}
|
21
|
-
best_driver.new(host, base_dir: base_dir, initializers: initializers, **driver_options)
|
21
|
+
driver = best_driver.new(host, base_dir: base_dir, initializers: initializers, **driver_options)
|
22
|
+
driver.run(dry_run: dry_run)
|
23
|
+
ensure
|
24
|
+
driver.finalize if driver
|
22
25
|
end
|
23
26
|
|
24
27
|
# def check_ssh_port
|
data/lib/hocho/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hocho
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sorah (Shota Fukumori)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- lib/hocho/drivers/base.rb
|
133
133
|
- lib/hocho/drivers/bundler.rb
|
134
134
|
- lib/hocho/drivers/itamae_ssh.rb
|
135
|
+
- lib/hocho/drivers/mitamae.rb
|
135
136
|
- lib/hocho/drivers/ssh_base.rb
|
136
137
|
- lib/hocho/host.rb
|
137
138
|
- lib/hocho/inventory.rb
|
@@ -139,6 +140,7 @@ files:
|
|
139
140
|
- lib/hocho/inventory_providers/base.rb
|
140
141
|
- lib/hocho/inventory_providers/file.rb
|
141
142
|
- lib/hocho/property_providers.rb
|
143
|
+
- lib/hocho/property_providers/add_default.rb
|
142
144
|
- lib/hocho/property_providers/base.rb
|
143
145
|
- lib/hocho/runner.rb
|
144
146
|
- lib/hocho/utils/finder.rb
|
@@ -161,12 +163,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
161
163
|
version: '0'
|
162
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
165
|
requirements:
|
164
|
-
- - "
|
166
|
+
- - ">="
|
165
167
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
168
|
+
version: '0'
|
167
169
|
requirements: []
|
168
170
|
rubyforge_project:
|
169
|
-
rubygems_version: 2.6.
|
171
|
+
rubygems_version: 2.6.8
|
170
172
|
signing_key:
|
171
173
|
specification_version: 4
|
172
174
|
summary: Server provisioning tool with itamae
|