hocho 0.2.2 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b86467c121e99a2b09b6a09ea852aaa61edcf3cd0ced7f068184284950d5bd8b
4
- data.tar.gz: e9c851f4e6d6d7040c3455c21d91e5e674a7abe95fecd352a2b1319701e65da5
3
+ metadata.gz: 02bd4fdb528bce052b2fbbdf13094a22dd66eaf4cea358cfdf458ad744e16e7c
4
+ data.tar.gz: 133bea775d5dd49cceaca4f24abf0cb47b1bf67583d51879c37643bda8b9d8aa
5
5
  SHA512:
6
- metadata.gz: 6b94585fa2224c38601e50173206fc35499f6e810817491ce0c556e9dfe55bbbc62b309d81139a4d40855c12c19be05cc51deb7cf265bd8970e20e466cae45a2
7
- data.tar.gz: 7ce19d7a13bb657ab41b511eb290306980d1fba32b3b7c8e7011f8a12696bfcfca030ef0c3d2c17c8699a6495f38a61b7147f322b421f82bde98bb66bda762f5
6
+ metadata.gz: 8cc5f789571a9c32c8ef2633ea5ef78b128d85e8ce5c7900bb155138bd944deeb031e7fd2d3715059a1916f8c05837269a8bc9c4426f19218304308aaa41af53
7
+ data.tar.gz: b7985500b353068b4e0a7433db48b396c5f856b29d037bc3208c0420765d38dd8ec986d5a857556b56480fa210f796308d1d54b9c7e2ac8f0b5e1ea738fcc981
data/lib/hocho/command.rb CHANGED
@@ -52,28 +52,40 @@ module Hocho
52
52
  desc "apply HOST", "run itamae"
53
53
  method_option :sudo, type: :boolean, default: false
54
54
  method_option :dry_run, type: :boolean, default: false, aliases: %w(-n)
55
+ method_option :exclude, type: :string, default: '', aliases: %w(-e)
55
56
  method_option :driver, type: :string
56
57
  def apply(name)
57
- host = inventory.filter(name: name).first
58
- unless host
58
+ hosts = inventory.filter({name: name}, exclude_filters: {name: options[:exclude]})
59
+ if hosts.empty?
59
60
  raise "host name=#{name.inspect} not found"
60
61
  end
61
62
 
63
+ if hosts.size > 1
64
+ puts "Running sequencial on:"
65
+ hosts.each do |host|
66
+ puts " * #{host.name}"
67
+ end
68
+ puts
69
+ end
70
+
62
71
  if config[:ask_sudo_password] || options[:sudo]
63
72
  print "sudo password: "
64
- host.sudo_password = $stdin.noecho { $stdin.gets.chomp }
73
+ sudo_password = $stdin.noecho { $stdin.gets.chomp }
65
74
  puts
66
75
  end
67
76
 
68
- Runner.new(
69
- host,
70
- driver: options[:driver],
71
- base_dir: config[:itamae_dir] || '.',
72
- initializers: config[:initializers] || [],
73
- driver_options: config[:driver_options] || {},
74
- ).run(
75
- dry_run: options[:dry_run],
76
- )
77
+ hosts.each do |host|
78
+ host.sudo_password = sudo_password if sudo_password
79
+ Runner.new(
80
+ host,
81
+ driver: options[:driver],
82
+ base_dir: config[:itamae_dir] || '.',
83
+ initializers: config[:initializers] || [],
84
+ driver_options: config[:driver_options] || {},
85
+ ).run(
86
+ dry_run: options[:dry_run],
87
+ )
88
+ end
77
89
  end
78
90
 
79
91
  private
@@ -13,6 +13,7 @@ module Hocho
13
13
  end
14
14
 
15
15
  def run(dry_run: false)
16
+ ssh # Test connection
16
17
  deploy(**@deploy_options) do
17
18
  bundle_install
18
19
  run_itamae(dry_run: dry_run)
@@ -13,8 +13,8 @@ module Hocho
13
13
  @deploy_options = deploy_options
14
14
  end
15
15
 
16
-
17
16
  def run(dry_run: false)
17
+ ssh # Test connection
18
18
  deploy(**@deploy_options) do
19
19
  prepare_mitamae
20
20
  run_mitamae(dry_run: dry_run)
@@ -70,10 +70,12 @@ module Hocho
70
70
 
71
71
  temporary_passphrase = SecureRandom.base64(129).chomp
72
72
 
73
+ derive = system(*%w(openssl enc -pbkdf2), in: File::NULL, out: File::NULL, err: [:child, :out]) ? %w(-pbkdf2) : []
74
+
73
75
  encrypted_password = IO.pipe do |r,w|
74
76
  w.write temporary_passphrase
75
77
  w.close
76
- IO.popen([*%w(openssl enc -aes-128-cbc -pass fd:5 -a), 5 => r], "r+") do |io|
78
+ IO.popen([*%w(openssl enc -aes-128-cbc -pass fd:5 -a -md sha256), *derive, 5 => r], "r+") do |io|
77
79
  io.puts password
78
80
  io.close_write
79
81
  io.read.chomp
@@ -86,7 +88,7 @@ module Hocho
86
88
  raise unless temp_executable.start_with?('/')
87
89
 
88
90
  ssh_run("chmod 0700 #{temp_executable.shellescape}; cat > #{temp_executable.shellescape}; chmod +x #{temp_executable.shellescape}") do |ch|
89
- ch.send_data("#!/bin/bash\nexec openssl enc -aes-128-cbc -d -a -pass env:#{passphrase_env_name} <<< #{encrypted_password.shellescape}\n")
91
+ ch.send_data("#!/bin/bash\nexec openssl enc -aes-128-cbc -d -a -md sha256 -pass env:#{passphrase_env_name} <<< #{encrypted_password.shellescape}\n")
90
92
  ch.eof!
91
93
  end
92
94
 
data/lib/hocho/host.rb CHANGED
@@ -18,11 +18,13 @@ module Hocho
18
18
  @tmpdir = tmpdir
19
19
  @shmdir = shmdir
20
20
  @sudo_password = sudo_password
21
+
22
+ @use_alternate_ssh_options = false
21
23
  end
22
24
 
23
25
  attr_reader :name, :providers, :properties, :tmpdir, :shmdir
24
26
  attr_writer :sudo_password
25
- attr_accessor :tags
27
+ attr_accessor :tags, :use_alternate_ssh_options
26
28
 
27
29
  def to_h
28
30
  {
@@ -42,10 +44,10 @@ module Hocho
42
44
  end
43
45
 
44
46
  def merge!(other)
45
- @tags.merge!(other.tags)
47
+ @tags.merge!(other.tags) if other.tags
46
48
  @tmpdir = other.tmpdir if other.tmpdir
47
49
  @shmdir = other.shmdir if other.shmdir
48
- @properties.merge(other.properties)
50
+ @properties.merge!(other.properties)
49
51
  end
50
52
 
51
53
  def apply_property_providers(providers)
@@ -79,9 +81,25 @@ module Hocho
79
81
  end
80
82
 
81
83
  def ssh_options
84
+ use_alternate_ssh_options? ? alternate_ssh_options : normal_ssh_options
85
+ end
86
+
87
+ def normal_ssh_options
82
88
  (Net::SSH::Config.for(ssh_name) || {}).merge(Hocho::Utils::Symbolize.keys_of(properties[:ssh_options] || {})).merge(@override_ssh_options || {})
83
89
  end
84
90
 
91
+ def alternate_ssh_options
92
+ normal_ssh_options.merge(Hocho::Utils::Symbolize.keys_of(properties.fetch(:alternate_ssh_options, {})))
93
+ end
94
+
95
+ def alternate_ssh_options_available?
96
+ !!properties[:alternate_ssh_options]
97
+ end
98
+
99
+ def use_alternate_ssh_options?
100
+ @use_alternate_ssh_options
101
+ end
102
+
85
103
  def openssh_config(separator='=')
86
104
  ssh_options.flat_map do |key, value|
87
105
  case key
@@ -131,8 +149,11 @@ module Hocho
131
149
  when :port
132
150
  [["Port", value]]
133
151
  when :proxy
134
- if value.kind_of?(Net::SSH::Proxy::Command)
152
+ case value
153
+ when Net::SSH::Proxy::Command
135
154
  [["ProxyCommand", value.command_line_template]]
155
+ when false
156
+ [["ProxyCommand", 'none']]
136
157
  else
137
158
  [["ProxyCommand", value]]
138
159
  end
@@ -173,7 +194,17 @@ module Hocho
173
194
  end
174
195
 
175
196
  def make_ssh_connection
176
- Net::SSH.start(name, nil, ssh_options)
197
+ alt = false
198
+ begin
199
+ Net::SSH.start(name, nil, ssh_options)
200
+ rescue Net::SSH::Exception => e
201
+ raise if alt
202
+ raise unless alternate_ssh_options_available?
203
+ puts "[#{name}] Trying alternate_ssh_options due to #{e.inspect}"
204
+ self.use_alternate_ssh_options = true
205
+ alt = true
206
+ retry
207
+ end
177
208
  end
178
209
  end
179
210
  end
@@ -20,19 +20,32 @@ module Hocho
20
20
  end.values
21
21
  end
22
22
 
23
- def filter(filters)
24
- filters = filters.map do |name, value|
25
- [name.to_s, value.to_s.split(?,).map! { |_| /#{Regexp.escape(_).gsub(/\\*/,'.*')}/ }]
26
- end.to_h
23
+ def filter(include_filters, exclude_filters: [])
24
+ include_filters, exclude_filters = [include_filters, exclude_filters].map do |f|
25
+ f.map do |name, value|
26
+ values = value.to_s.split(?,).map! do |_|
27
+ if _[0] == '/' && _[-1] == '/'
28
+ Regexp.new(_[1...-1])
29
+ else
30
+ /#{Regexp.escape(_).gsub(/\*/,'.*')}/
31
+ end
32
+ end
33
+ [name.to_s, values]
34
+ end.to_h
35
+ end
36
+
37
+ filters = include_filters.map do |name, conditions|
38
+ [name, [conditions, exclude_filters.fetch(name, [])]]
39
+ end
27
40
 
28
41
  hosts.select do |host|
29
- filters.all? do |name, conditions|
42
+ filters.all? do |name, (conditions, exclude_conditions)|
30
43
  case name
31
44
  when 'name'
32
- conditions.any? { |c| host.name.match(c) }
45
+ conditions.any? { |c| host.name.match(c) } && !exclude_conditions.any? { |c| host.name.match(c) }
33
46
  else
34
47
  v = (host.attributes[name] || host.attributes[name.to_sym] || host.tags[name] || host.tags[name.to_sym])
35
- v && conditions.any? { |c| v.to_s.match(c) }
48
+ v && conditions.any? { |c| v.to_s.match(c) } && !exclude_conditions.any?{ |c| v.to_s.match(c) }
36
49
  end
37
50
  end
38
51
  end
@@ -28,9 +28,9 @@ module Hocho
28
28
  Host.new(
29
29
  name.to_s,
30
30
  providers: self.class,
31
- properties: value[:properties],
32
- tags: value[:tags],
33
- ssh_options: value[:ssh_options]
31
+ properties: value[:properties] || {},
32
+ tags: value[:tags] || {},
33
+ ssh_options: value[:ssh_options],
34
34
  )
35
35
  end
36
36
  end
data/lib/hocho/runner.rb CHANGED
@@ -16,7 +16,7 @@ module Hocho
16
16
  attr_reader :host, :driver, :base_dir, :initializers
17
17
 
18
18
  def run(dry_run: false)
19
- puts "Running using #{best_driver_name}"
19
+ puts "=> Running on #{host.name} using #{best_driver_name}"
20
20
  driver_options = @driver_options[best_driver_name] || {}
21
21
  driver = best_driver.new(host, base_dir: base_dir, initializers: initializers, **driver_options)
22
22
  driver.run(dry_run: dry_run)
@@ -1,6 +1,7 @@
1
1
  module Hocho
2
2
  module Utils
3
3
  module Finder
4
+ class NotFound < StandardError; end
4
5
  def self.find(const, prefix, name)
5
6
  retried = false
6
7
  constant_name = name.to_s.gsub(/\A.|_./) { |s| s[-1].upcase }
@@ -17,8 +18,7 @@ module Hocho
17
18
  retried = true
18
19
  retry
19
20
  end
20
-
21
- nil
21
+ raise NotFound, "Couldn't find #{prefix}/#{name}"
22
22
  end
23
23
  end
24
24
  end
data/lib/hocho/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Hocho
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
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.2.2
4
+ version: 0.3.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: 2018-06-10 00:00:00.000000000 Z
11
+ date: 2019-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -167,8 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
167
  - !ruby/object:Gem::Version
168
168
  version: '0'
169
169
  requirements: []
170
- rubyforge_project:
171
- rubygems_version: 2.7.6
170
+ rubygems_version: 3.0.1
172
171
  signing_key:
173
172
  specification_version: 4
174
173
  summary: Server provisioning tool with itamae