pec2 0.5.1 → 0.6.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
  SHA1:
3
- metadata.gz: cb66795b5285c636e91c6f868d3a8232ace8e6b0
4
- data.tar.gz: e6adbd3a3fb3ecf2c79f9328b748b8a12fd0a6d1
3
+ metadata.gz: 550ba6ff5b0de826f866deeafc7d97eb159980b9
4
+ data.tar.gz: 6fcf46712f036133de9c7c489c8cc30fbb80dc72
5
5
  SHA512:
6
- metadata.gz: 3eccd5049cebf61354803fdfe964051778b1ed79a13cf4589a482a28a91c1d477fed4c285497536f1b7fa1cdb88f5472dd9c633b7700f22a0ffbfb7e8f0e961a
7
- data.tar.gz: c20e2e77b347f67499b19d9fc855ed5eb2488beb54c0237ff5ca8cc6007062b5d980932ad1e4e976d81625aded3f7ee043e49607813a94b72b20f64840bdba71
6
+ metadata.gz: 6935e5dda4e21de298670ee7c20eff00d7e031db0d92aaaee9bc2d0cb189c7f8c8baefe7592bf9d99de52fe1466e930f4a78aed03949ae822905e8379b2c6816
7
+ data.tar.gz: 93dd2d07b2852a0729c51f5c7862a337615ac53b40b5a59f8d3509dc55d7efc2cc4f563894132a527c4304f3a17fb2dc167a5233e3f37d7e4f33679a7ed22337
data/lib/pec2/cli.rb CHANGED
@@ -20,7 +20,6 @@ module Pec2
20
20
  option :sudo_password, aliases: '-s', type: :string, desc: 'sudo_password'
21
21
  option :tag, aliases: '-t', type: :hash, default: {}, desc: 'tag'
22
22
  option :user, aliases: '-u', type: :string, desc: 'user'
23
- option :log, aliases: '-o', type: :string, desc: 'log'
24
23
  option :parallel, aliases: '-p', type: :numeric, desc: 'parallel'
25
24
  option :print, aliases: '-P', type: :boolean, default: false, desc: 'print stdout.'
26
25
  option :resolve, aliases: '--resolve', type: :string, default: 'private_ip_address', enum: ['private_ip_address', 'public_ip_address', 'name_tag'], desc: 'resolve'
@@ -43,12 +42,7 @@ module Pec2
43
42
  @logger.info(%Q{connection size #{addresses.size}.})
44
43
  @logger.info(%Q{listing connection to #{addresses.join(', ')}.})
45
44
 
46
- tf = Tempfile.open("pec2") { |fp|
47
- fp.puts(addresses.join("\n"))
48
- fp
49
- }
50
-
51
- pssh = Pssh.new(options, tf.path, addresses.size)
45
+ pssh = Pssh.new(options, addresses, addresses.size)
52
46
 
53
47
  interactive = options[:command] ? false : true
54
48
 
@@ -60,11 +54,9 @@ module Pec2
60
54
  else
61
55
  ret = pssh.exec_pssh_command(options[:command])
62
56
  unless ret
63
- tf.close
64
57
  exit 1
65
58
  end
66
59
  end
67
- tf.close
68
60
  end
69
61
 
70
62
  desc 'version', 'show version'
data/lib/pec2/pssh.rb CHANGED
@@ -1,40 +1,70 @@
1
- require 'shellwords'
1
+ require 'net/ssh'
2
+ require 'parallel'
3
+ require 'colorize'
2
4
 
3
5
  module Pec2
4
6
  class Pssh
5
7
 
6
- PSSH_PATH = File.expand_path('../../../exe/bin/pssh', __FILE__)
7
-
8
- def initialize(options, hosts_file, parallel = 1)
9
- @pssh_command = "#{PSSH_PATH} -t 0 -x '-tt' -h #{hosts_file} -O StrictHostKeyChecking=no"
10
- if options[:print]
11
- @pssh_command = "#{@pssh_command} -P"
12
- end
13
-
14
- if options[:user]
15
- @pssh_command = "#{@pssh_command} -l #{options[:user]}"
16
- end
17
-
18
- if options[:log]
19
- @pssh_command = "#{@pssh_command} -o #{options[:log]}"
20
- end
21
-
22
- @pssh_command = "#{@pssh_command} -p #{options[:parallel] || parallel}"
8
+ def initialize(options, servers, parallel = 1)
9
+ @parallel = parallel
10
+ color_index = 0
11
+ colors = String.colors.select{ |color|
12
+ !color.to_s.start_with?('light_') && !color.to_s.include?('red') && !color.to_s.include?('yellow')
13
+ }
14
+ @servers = servers.map { |server|
15
+ result = {}
16
+ result[:host] = server
17
+ result[:color] = colors[color_index]
18
+ if colors.size == color_index + 1
19
+ color_index = 0
20
+ else
21
+ color_index = color_index + 1
22
+ end
23
+ result
24
+ }
25
+ @user = options[:user]
26
+ @print = options[:print]
23
27
  @sudo_password = options[:sudo_password]
24
- end
25
-
26
- def build_pssh_command(command)
27
- if @sudo_password
28
- %Q{(echo #{@sudo_password}) | #{@pssh_command} -I #{Shellwords.escape(command)}}
29
- else
30
- %Q{#{@pssh_command} -i #{Shellwords.escape(command)}}
31
- end
28
+ @ssh_options = {
29
+ verify_host_key: false,
30
+ user_known_hosts_file: '/dev/null',
31
+ }
32
+ @logger = Logger.new(STDOUT)
32
33
  end
33
34
 
34
35
  def exec_pssh_command(command)
35
36
  return false if command.nil? || command.empty?
36
- build_command = build_pssh_command(command)
37
- system(build_command)
37
+ error_servers = []
38
+ Parallel.each(@servers, in_threads: @parallel) do |server|
39
+ begin
40
+ Net::SSH.start(server[:host], @user, @ssh_options) do |ssh|
41
+ channel = ssh.open_channel do |channel, success|
42
+ channel.on_data do |channel, data|
43
+ if data =~ /^\[sudo\] password for /
44
+ channel.send_data "#{@sudo_password}\n"
45
+ else
46
+ data.to_s.lines.each do |line|
47
+ if @print
48
+ print %Q{#{server[:host]}:#{line}}.colorize(server[:color])
49
+ end
50
+ end
51
+ end
52
+ end
53
+ channel.request_pty
54
+ channel.exec(command)
55
+ channel.wait
56
+ end
57
+ channel.wait
58
+ end
59
+ rescue => e
60
+ error_servers << server[:host]
61
+ puts "\n#{e.message}\n#{e.backtrace.join("\n")}"
62
+ end
63
+ end
64
+ if error_servers.size > 0
65
+ @logger.error "error servers => #{error_servers.join(', ')}".colorize(:red)
66
+ end
67
+ return true
38
68
  end
39
69
  end
40
70
  end
data/lib/pec2/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Pec2
2
2
  # pec2 version
3
- VERSION = "0.5.1"
3
+ VERSION = "0.6.0"
4
4
  end
data/pec2.gemspec CHANGED
@@ -18,8 +18,11 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ['lib']
19
19
 
20
20
  gem.add_dependency 'thor'
21
- gem.add_dependency 'aws-sdk'
21
+ gem.add_dependency 'aws-sdk', '~> 2.x'
22
22
  gem.add_dependency 'hashie'
23
+ gem.add_dependency 'net-ssh'
24
+ gem.add_dependency 'parallel'
25
+ gem.add_dependency 'colorize'
23
26
 
24
27
  gem.add_development_dependency 'bundler'
25
28
  gem.add_development_dependency 'pry'
data/spec/cli_spec.rb CHANGED
@@ -21,7 +21,6 @@ describe Pec2::CLI do
21
21
  expect(output).to include('--sudo-password')
22
22
  expect(output).to include('--tag')
23
23
  expect(output).to include('--user')
24
- expect(output).to include('--log')
25
24
  expect(output).to include('--parallel')
26
25
  expect(output).to include('--print')
27
26
  end
data/spec/pssh_spec.rb CHANGED
@@ -1,14 +1,9 @@
1
1
  require 'spec_helper'
2
2
  require 'pec2'
3
- require 'tempfile'
4
3
 
5
4
  describe Pec2::Pssh do
6
5
  before do
7
- @tf = Tempfile.open("pec2") { |fp|
8
- fp.puts("127.0.0.1")
9
- fp
10
- }
11
- @pssh = Pssh.new({}, @tf.path)
6
+ @pssh = Pssh.new({}, ["127.0.0.1"])
12
7
  end
13
8
 
14
9
  it "test exec_pssh_command empty" do
@@ -23,54 +18,6 @@ describe Pec2::Pssh do
23
18
  expect(ret).to eq(false)
24
19
  end
25
20
 
26
- it "test build_pssh_command empty" do
27
- pssh_command = @pssh.build_pssh_command('')
28
-
29
- expect(pssh_command).to include(%Q{-O StrictHostKeyChecking=no})
30
- expect(pssh_command).to include(%Q{-t 0 -x '-tt'})
31
- expect(pssh_command).to include(%Q{-i ''})
32
- end
33
-
34
- it "test build_pssh_command" do
35
- pssh_command = @pssh.build_pssh_command('hostname')
36
-
37
- expect(pssh_command).not_to start_with(%Q{(echo password) |})
38
- expect(pssh_command).to include(%Q{-O StrictHostKeyChecking=no})
39
- expect(pssh_command).to include(%Q{-t 0 -x '-tt'})
40
- expect(pssh_command).to include(%Q{-i hostname})
41
- end
42
-
43
- it "test build_pssh_command with user option" do
44
- pssh = Pssh.new({ user: 'app' }, @tf.path)
45
- pssh_command = pssh.build_pssh_command('hostname')
46
- expect(pssh_command).to include(%Q{ -l app})
47
- end
48
-
49
- it "test build_pssh_command with log option" do
50
- pssh = Pssh.new({ log: 'hoge.log' }, @tf.path)
51
- pssh_command = pssh.build_pssh_command('hostname')
52
- expect(pssh_command).to include(%Q{ -o hoge.log})
53
- end
54
-
55
- it "test build_pssh_command with parallel option" do
56
- pssh = Pssh.new({ parallel: 10 }, @tf.path)
57
- pssh_command = pssh.build_pssh_command('hostname')
58
- expect(pssh_command).to include(%Q{ -p 10})
59
- end
60
-
61
- it "test build_pssh_command with print option" do
62
- pssh = Pssh.new({ print: true }, @tf.path)
63
- pssh_command = pssh.build_pssh_command('hostname')
64
- expect(pssh_command).to include(%Q{ -P})
65
- end
66
-
67
- it "test build_pssh_command with sudo_password option" do
68
- pssh = Pssh.new({ sudo_password: 'password' }, @tf.path)
69
- pssh_command = pssh.build_pssh_command('hostname')
70
- expect(pssh_command).to start_with(%Q{(echo password) |})
71
- end
72
-
73
21
  after do
74
- @tf.close
75
22
  end
76
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pec2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - toyama0919
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-22 00:00:00.000000000 Z
11
+ date: 2017-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -26,6 +26,20 @@ dependencies:
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: aws-sdk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.x
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.x
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashie
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
@@ -39,7 +53,35 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: hashie
56
+ name: net-ssh
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: parallel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: colorize
43
85
  requirement: !ruby/object:Gem::Requirement
44
86
  requirements:
45
87
  - - ">="
@@ -167,26 +209,6 @@ files:
167
209
  - README.md
168
210
  - Rakefile
169
211
  - bin/pec2
170
- - exe/bin/pnuke
171
- - exe/bin/prsync
172
- - exe/bin/pscp
173
- - exe/bin/pslurp
174
- - exe/bin/pssh
175
- - exe/bin/pssh-askpass
176
- - exe/man/man1/pnuke.1
177
- - exe/man/man1/prsync.1
178
- - exe/man/man1/pscp.1
179
- - exe/man/man1/pslurp.1
180
- - exe/man/man1/pssh.1
181
- - exe/psshlib/__init__.py
182
- - exe/psshlib/askpass_client.py
183
- - exe/psshlib/askpass_server.py
184
- - exe/psshlib/cli.py
185
- - exe/psshlib/color.py
186
- - exe/psshlib/manager.py
187
- - exe/psshlib/psshutil.py
188
- - exe/psshlib/task.py
189
- - exe/psshlib/version.py
190
212
  - lib/pec2.rb
191
213
  - lib/pec2/cli.rb
192
214
  - lib/pec2/constants.rb
@@ -219,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
241
  version: '0'
220
242
  requirements: []
221
243
  rubyforge_project:
222
- rubygems_version: 2.6.8
244
+ rubygems_version: 2.6.13
223
245
  signing_key:
224
246
  specification_version: 4
225
247
  summary: run parallel ssh command. ec2 tag base operation.
data/exe/bin/pnuke DELETED
@@ -1,96 +0,0 @@
1
- #!/usr/bin/env python
2
- # -*- Mode: python -*-
3
-
4
- # Copyright (c) 2009-2012, Andrew McNabb
5
- # Copyright (c) 2003-2008, Brent N. Chun
6
-
7
- """Nukes all processes that match pattern running as user on the set of nodes
8
- in hosts.txt.
9
- """
10
-
11
- import os
12
- import sys
13
-
14
- parent, bindir = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))
15
- if os.path.exists(os.path.join(parent, 'psshlib')):
16
- sys.path.insert(0, parent)
17
-
18
- from psshlib import psshutil
19
- from psshlib.task import Task
20
- from psshlib.manager import Manager, FatalError
21
- from psshlib.cli import common_parser, common_defaults
22
-
23
- _DEFAULT_TIMEOUT = 60
24
-
25
- def option_parser():
26
- parser = common_parser()
27
- parser.usage = "%prog [OPTIONS] pattern"
28
- parser.epilog = "Example: pnuke -h hosts.txt -l irb2 java"
29
- return parser
30
-
31
- def parse_args():
32
- parser = option_parser()
33
- defaults = common_defaults(timeout=_DEFAULT_TIMEOUT)
34
- parser.set_defaults(**defaults)
35
- opts, args = parser.parse_args()
36
-
37
- if len(args) < 1:
38
- parser.error('Pattern not specified.')
39
-
40
- if len(args) > 1:
41
- parser.error('Extra arguments given after the pattern.')
42
-
43
- if not opts.host_files and not opts.host_strings:
44
- parser.error('Hosts not specified.')
45
-
46
- return opts, args
47
-
48
- def do_pnuke(hosts, pattern, opts):
49
- if opts.outdir and not os.path.exists(opts.outdir):
50
- os.makedirs(opts.outdir)
51
- if opts.errdir and not os.path.exists(opts.errdir):
52
- os.makedirs(opts.errdir)
53
- manager = Manager(opts)
54
- for host, port, user in hosts:
55
- cmd = ['ssh', host, '-o', 'NumberOfPasswordPrompts=1']
56
- if opts.options:
57
- for opt in opts.options:
58
- cmd += ['-o', opt]
59
- if user:
60
- cmd += ['-l', user]
61
- if port:
62
- cmd += ['-p', port]
63
- if opts.extra:
64
- cmd.extend(opts.extra)
65
- cmd.append('pkill -9 %s' % pattern)
66
- t = Task(host, port, user, cmd, opts)
67
- manager.add_task(t)
68
- try:
69
- statuses = manager.run()
70
- except FatalError:
71
- sys.exit(1)
72
-
73
- if min(statuses) < 0:
74
- # At least one process was killed.
75
- sys.exit(3)
76
- for status in statuses:
77
- if status == 255:
78
- sys.exit(4)
79
- for status in statuses:
80
- if status != 0:
81
- sys.exit(5)
82
-
83
- if __name__ == "__main__":
84
- opts, args = parse_args()
85
- pattern = args[0]
86
- try:
87
- hosts = psshutil.read_host_files(opts.host_files,
88
- default_user=opts.user)
89
- except IOError:
90
- _, e, _ = sys.exc_info()
91
- sys.stderr.write('Could not open hosts file: %s\n' % e.strerror)
92
- sys.exit(1)
93
- if opts.host_strings:
94
- for s in opts.host_strings:
95
- hosts.extend(psshutil.parse_host_string(s, default_user=opts.user))
96
- do_pnuke(hosts, pattern, opts)