eventhub-command 0.0.22 → 0.1.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/.gitignore +17 -17
- data/Gemfile +2 -2
- data/README.md +52 -29
- data/Rakefile +44 -44
- data/bin/eh +39 -39
- data/eh.gemspec +31 -28
- data/eh.rdoc +4 -4
- data/features/eh.feature +8 -8
- data/features/step_definitions/eh_steps.rb +6 -6
- data/features/support/env.rb +15 -15
- data/lib/deployer.rb +6 -0
- data/lib/deployer/executor.rb +102 -0
- data/lib/deployer/net_ssh_extension.rb +37 -0
- data/lib/deployer/stage.rb +28 -0
- data/lib/eh-commands.rb +8 -6
- data/lib/eh.rb +11 -7
- data/lib/eh/commands/copy_config.rb +51 -51
- data/lib/eh/commands/deploy.rb +38 -38
- data/lib/eh/commands/deploy_mule.rb +67 -0
- data/lib/eh/commands/deploy_ruby.rb +87 -0
- data/lib/eh/commands/generate_processor.rb +90 -90
- data/lib/eh/commands/package.rb +104 -104
- data/lib/eh/commands/package_rails.rb +68 -70
- data/lib/eh/settings.rb +72 -69
- data/lib/eh/version.rb +3 -3
- data/test/default_test.rb +14 -14
- data/test/test_helper.rb +9 -9
- data/todo.txt +8 -8
- metadata +37 -3
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
class Deployer::Executor
|
5
|
+
attr_reader :stage
|
6
|
+
|
7
|
+
def initialize(stage, options = {})
|
8
|
+
@stage = stage
|
9
|
+
@options = options
|
10
|
+
yield(self) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def execute(command, options = {})
|
15
|
+
log_command("Execute: '#{command}'", options[:comment])
|
16
|
+
stage.hosts.each_with_index do |host, index|
|
17
|
+
log_host(host, index)
|
18
|
+
result = execute_on(host, command)
|
19
|
+
log_result(result)
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue => e
|
23
|
+
handle_exception(e, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def upload(source, target, options = {})
|
27
|
+
log_command("Execute: scp #{source} to #{target}", options[:comment])
|
28
|
+
stage.hosts.each_with_index do |host, index|
|
29
|
+
log_host(host, index)
|
30
|
+
result = upload_on(host, source, target)
|
31
|
+
log_result(result)
|
32
|
+
end
|
33
|
+
|
34
|
+
rescue => e
|
35
|
+
handle_exception(e, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
def handle_exception(e, options)
|
41
|
+
if options[:abort_on_error] == false
|
42
|
+
puts "warning".black.on_yellow
|
43
|
+
puts " #{e.message}".yellow
|
44
|
+
else
|
45
|
+
puts "failure".black.on_red
|
46
|
+
puts " #{e.message}".red
|
47
|
+
end
|
48
|
+
raise unless options[:abort_on_error] == false
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def verbose?
|
53
|
+
@options[:verbose]
|
54
|
+
end
|
55
|
+
|
56
|
+
def log_result(result)
|
57
|
+
puts "success".black.on_green
|
58
|
+
if verbose? && result[:stdout] && result[:stdout].length > 0
|
59
|
+
puts " -> #{result[:stdout].chomp}".light_blue
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def log_host(host, index)
|
64
|
+
print " #{host[:host]} (#{index + 1}/#{stage.hosts.size}): "
|
65
|
+
end
|
66
|
+
|
67
|
+
def log_command(cmd, comment = nil)
|
68
|
+
puts cmd.blue
|
69
|
+
puts " (#{comment})" if verbose? && comment
|
70
|
+
end
|
71
|
+
|
72
|
+
def upload_on(host, source, target)
|
73
|
+
execute_local "scp -P #{host[:port]} #{source} #{host[:user]}@#{host[:host]}:#{target}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def execute_on(host, command)
|
77
|
+
Net::SSH.start(host[:host], host[:user], port: host[:port]) do |ssh|
|
78
|
+
ssh.exec_sc!(command)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def execute_local(command)
|
83
|
+
output = nil
|
84
|
+
exit_code = nil
|
85
|
+
|
86
|
+
Bundler.with_clean_env do
|
87
|
+
output = `#{command}`
|
88
|
+
exit_code = $?
|
89
|
+
end
|
90
|
+
|
91
|
+
raise "Command \"#{command}\" returned exit code #{exit_code}" unless exit_code.success?
|
92
|
+
|
93
|
+
result = {
|
94
|
+
stdout: output,
|
95
|
+
stderr: '',
|
96
|
+
exit_code: 0,
|
97
|
+
}
|
98
|
+
|
99
|
+
result
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Net::SSH::Connection::Session
|
2
|
+
|
3
|
+
def exec_sc!(command)
|
4
|
+
stdout_data,stderr_data = "",""
|
5
|
+
exit_code,exit_signal = nil,nil
|
6
|
+
self.open_channel do |channel|
|
7
|
+
channel.exec(command) do |_, success|
|
8
|
+
raise "Command \"#{command}\" was unable to execute" unless success
|
9
|
+
|
10
|
+
channel.on_data do |_, data|
|
11
|
+
stdout_data += data
|
12
|
+
end
|
13
|
+
|
14
|
+
channel.on_extended_data do |_, _, data|
|
15
|
+
stderr_data += data
|
16
|
+
end
|
17
|
+
|
18
|
+
channel.on_request("exit-status") do |_, data|
|
19
|
+
exit_code = data.read_long
|
20
|
+
end
|
21
|
+
|
22
|
+
channel.on_request("exit-signal") do |_, data|
|
23
|
+
exit_signal = data.read_long
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
self.loop
|
28
|
+
raise stderr_data unless exit_code == 0
|
29
|
+
|
30
|
+
{
|
31
|
+
stdout: stdout_data,
|
32
|
+
stderr: stderr_data,
|
33
|
+
exit_code: exit_code,
|
34
|
+
exit_signal: exit_signal
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Deployer::Stage
|
2
|
+
attr_reader :name, :node_env, :hosts
|
3
|
+
|
4
|
+
def initialize(name, node_env)
|
5
|
+
@name = name
|
6
|
+
@node_env = node_env
|
7
|
+
@hosts = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def host(host, port, user)
|
11
|
+
@hosts << {
|
12
|
+
host: host,
|
13
|
+
port: port,
|
14
|
+
user: user
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.load(file)
|
19
|
+
data = YAML.load_file(file)
|
20
|
+
data.map do |name, config|
|
21
|
+
stage = Deployer::Stage.new(name, config['node_env'])
|
22
|
+
config['hosts'].each do |host|
|
23
|
+
stage.host(host['host'], host['port'], host['user'])
|
24
|
+
end
|
25
|
+
stage
|
26
|
+
end.first
|
27
|
+
end
|
28
|
+
end
|
data/lib/eh-commands.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
# All commands are required here
|
2
|
-
require 'eh/commands/deploy'
|
3
|
-
require 'eh/commands/copy_config'
|
4
|
-
require 'eh/commands/generate_processor'
|
5
|
-
require 'eh/commands/package_rails'
|
6
|
-
require 'eh/commands/package'
|
1
|
+
# All commands are required here
|
2
|
+
require 'eh/commands/deploy'
|
3
|
+
require 'eh/commands/copy_config'
|
4
|
+
require 'eh/commands/generate_processor'
|
5
|
+
require 'eh/commands/package_rails'
|
6
|
+
require 'eh/commands/package'
|
7
|
+
require 'eh/commands/deploy_ruby'
|
8
|
+
require 'eh/commands/deploy_mule'
|
data/lib/eh.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
module Eh
|
2
|
-
end
|
3
|
-
|
4
|
-
require '
|
5
|
-
|
6
|
-
|
7
|
-
require 'eh/
|
1
|
+
module Eh
|
2
|
+
end
|
3
|
+
|
4
|
+
require 'zip'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
require 'eh/version'
|
8
|
+
require 'eh/settings'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
require_relative 'deployer'
|
@@ -1,51 +1,51 @@
|
|
1
|
-
desc 'Copies the config directory of a given processor to remote'
|
2
|
-
command :copy_config do |c|
|
3
|
-
c.flag([:s, :source], :desc => "Source config directory", :default_value => Eh::Settings.current.source_config_dir, :long_desc => "A local directory containing subfolders for each of the processors")
|
4
|
-
c.flag([:p, :processors], :desc => "Specify what processors' configs to copy", :type => Array, :long_desc => "You can specify multiple processors by providing a comma-separated list.")
|
5
|
-
|
6
|
-
c.action do |global_options, options, args|
|
7
|
-
source_config_dir = options['s']
|
8
|
-
repository_deployment_dir = File.join(Eh::Settings.current.repository_root_dir, "branches", "master", "src", "deployment")
|
9
|
-
|
10
|
-
processor_names = Dir["#{source_config_dir}/*"].map do |dir|
|
11
|
-
File.basename(dir)
|
12
|
-
end
|
13
|
-
|
14
|
-
included_processor_names = processor_names
|
15
|
-
|
16
|
-
# only include processors specified by -p option, if option is given
|
17
|
-
if options['p']
|
18
|
-
included_processor_names = included_processor_names.select do |processor_name|
|
19
|
-
options['p'].include?(processor_name)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# make sure we have at least one processor
|
24
|
-
if included_processor_names.empty?
|
25
|
-
raise "There are no processor configs to copy. Either there is nothing in #{source_config_dir} or the processor(s) specified with -p don't exist."
|
26
|
-
end
|
27
|
-
|
28
|
-
included_processor_names.each do |processor_name|
|
29
|
-
processor_config_source_dir = File.join(source_config_dir, processor_name)
|
30
|
-
|
31
|
-
cmd = "cd #{repository_deployment_dir} && COPY_FROM_DIR=#{processor_config_source_dir} bundle exec cap event_hub:scp_copy_config"
|
32
|
-
|
33
|
-
puts "Will copy config files from #{processor_config_source_dir} to remote."
|
34
|
-
puts "WARNING: This will overwrite any existing files with the same name!"
|
35
|
-
puts "Do you really want to do this?"
|
36
|
-
input = STDIN.gets.chomp
|
37
|
-
|
38
|
-
unless ['y', 'Y'].include?(input)
|
39
|
-
raise "Not confirmed. Stop."
|
40
|
-
end
|
41
|
-
|
42
|
-
puts "Command: #{cmd}" if global_options['v']
|
43
|
-
|
44
|
-
Bundler.with_clean_env do
|
45
|
-
system cmd
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
puts "Done."
|
50
|
-
end
|
51
|
-
end
|
1
|
+
desc 'Copies the config directory of a given processor to remote'
|
2
|
+
command :copy_config do |c|
|
3
|
+
c.flag([:s, :source], :desc => "Source config directory", :default_value => Eh::Settings.current.source_config_dir, :long_desc => "A local directory containing subfolders for each of the processors")
|
4
|
+
c.flag([:p, :processors], :desc => "Specify what processors' configs to copy", :type => Array, :long_desc => "You can specify multiple processors by providing a comma-separated list.")
|
5
|
+
|
6
|
+
c.action do |global_options, options, args|
|
7
|
+
source_config_dir = options['s']
|
8
|
+
repository_deployment_dir = File.join(Eh::Settings.current.repository_root_dir, "branches", "master", "src", "deployment")
|
9
|
+
|
10
|
+
processor_names = Dir["#{source_config_dir}/*"].map do |dir|
|
11
|
+
File.basename(dir)
|
12
|
+
end
|
13
|
+
|
14
|
+
included_processor_names = processor_names
|
15
|
+
|
16
|
+
# only include processors specified by -p option, if option is given
|
17
|
+
if options['p']
|
18
|
+
included_processor_names = included_processor_names.select do |processor_name|
|
19
|
+
options['p'].include?(processor_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# make sure we have at least one processor
|
24
|
+
if included_processor_names.empty?
|
25
|
+
raise "There are no processor configs to copy. Either there is nothing in #{source_config_dir} or the processor(s) specified with -p don't exist."
|
26
|
+
end
|
27
|
+
|
28
|
+
included_processor_names.each do |processor_name|
|
29
|
+
processor_config_source_dir = File.join(source_config_dir, processor_name)
|
30
|
+
|
31
|
+
cmd = "cd #{repository_deployment_dir} && COPY_FROM_DIR=#{processor_config_source_dir} bundle exec cap event_hub:scp_copy_config"
|
32
|
+
|
33
|
+
puts "Will copy config files from #{processor_config_source_dir} to remote."
|
34
|
+
puts "WARNING: This will overwrite any existing files with the same name!"
|
35
|
+
puts "Do you really want to do this?"
|
36
|
+
input = STDIN.gets.chomp
|
37
|
+
|
38
|
+
unless ['y', 'Y'].include?(input)
|
39
|
+
raise "Not confirmed. Stop."
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "Command: #{cmd}" if global_options['v']
|
43
|
+
|
44
|
+
Bundler.with_clean_env do
|
45
|
+
system cmd
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
puts "Done."
|
50
|
+
end
|
51
|
+
end
|
data/lib/eh/commands/deploy.rb
CHANGED
@@ -1,38 +1,38 @@
|
|
1
|
-
desc 'Deploys the app'
|
2
|
-
arg_name 'stage', optional: true
|
3
|
-
command :deploy do |c|
|
4
|
-
|
5
|
-
c.flag([:deploy_via], :desc => "One of 'copy' or 'scm'", :default_value => 'scm')
|
6
|
-
c.flag([:copy_from_dir], :desc => "Source directory for copy operation", :default_value => Eh::Settings.current.releases_dir)
|
7
|
-
c.flag([:tag], :desc => "The tag to deploy")
|
8
|
-
c.flag([:branch], :desc => "The branch to deploy", :default_value => "master")
|
9
|
-
|
10
|
-
c.action do |global_options, options, args|
|
11
|
-
stage = args[0] || "development"
|
12
|
-
|
13
|
-
deployment_dir = Eh::Settings.current.deployment_dir
|
14
|
-
|
15
|
-
env_variables = []
|
16
|
-
env_variables << "DEPLOY_VIA=#{options[:deploy_via]}"
|
17
|
-
|
18
|
-
if options[:tag]
|
19
|
-
env_variables << "TAG=#{options[:tag]}"
|
20
|
-
else
|
21
|
-
env_variables << "BRANCH=#{options[:branch]}"
|
22
|
-
end
|
23
|
-
|
24
|
-
if options[:deploy_via] == "copy"
|
25
|
-
env_variables << "COPY_FROM_DIR=#{options[:copy_from_dir]}"
|
26
|
-
end
|
27
|
-
|
28
|
-
cmd = "cd #{deployment_dir} && #{env_variables.join(' ')} bundle exec cap #{stage} event_hub"
|
29
|
-
|
30
|
-
puts "Command: #{cmd}" if global_options['v']
|
31
|
-
|
32
|
-
Bundler.with_clean_env do
|
33
|
-
system cmd
|
34
|
-
end
|
35
|
-
|
36
|
-
puts "Done."
|
37
|
-
end
|
38
|
-
end
|
1
|
+
desc 'Deploys the app'
|
2
|
+
arg_name 'stage', optional: true
|
3
|
+
command :deploy do |c|
|
4
|
+
|
5
|
+
c.flag([:deploy_via], :desc => "One of 'copy' or 'scm'", :default_value => 'scm')
|
6
|
+
c.flag([:copy_from_dir], :desc => "Source directory for copy operation", :default_value => Eh::Settings.current.releases_dir)
|
7
|
+
c.flag([:tag], :desc => "The tag to deploy")
|
8
|
+
c.flag([:branch], :desc => "The branch to deploy", :default_value => "master")
|
9
|
+
|
10
|
+
c.action do |global_options, options, args|
|
11
|
+
stage = args[0] || "development"
|
12
|
+
|
13
|
+
deployment_dir = Eh::Settings.current.deployment_dir
|
14
|
+
|
15
|
+
env_variables = []
|
16
|
+
env_variables << "DEPLOY_VIA=#{options[:deploy_via]}"
|
17
|
+
|
18
|
+
if options[:tag]
|
19
|
+
env_variables << "TAG=#{options[:tag]}"
|
20
|
+
else
|
21
|
+
env_variables << "BRANCH=#{options[:branch]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
if options[:deploy_via] == "copy"
|
25
|
+
env_variables << "COPY_FROM_DIR=#{options[:copy_from_dir]}"
|
26
|
+
end
|
27
|
+
|
28
|
+
cmd = "cd #{deployment_dir} && #{env_variables.join(' ')} bundle exec cap #{stage} event_hub"
|
29
|
+
|
30
|
+
puts "Command: #{cmd}" if global_options['v']
|
31
|
+
|
32
|
+
Bundler.with_clean_env do
|
33
|
+
system cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
puts "Done."
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
desc 'deploy a single channel adapter'
|
3
|
+
arg_name 'channel_adapter stage'
|
4
|
+
|
5
|
+
command :deploy_mule do |c|
|
6
|
+
c.flag([:s, :stage], desc: "stage", type: String, long_desc: "Stage where channel adapter is deployed to", default_value: 'localhost')
|
7
|
+
c.flag([:deploy_via], desc: "how to get hold of the channel adapter: scm or scp", type: String, long_desc: "copy the channel adapter zip file via scp from this machine or check it out from scm", default_value: 'scp')
|
8
|
+
|
9
|
+
c.switch([:v, :verbose], :desc => "Show additional output.")
|
10
|
+
|
11
|
+
c.action do |global_options, options, args|
|
12
|
+
if args.size < 1
|
13
|
+
puts "Needs at least one argument: channel_adapter"
|
14
|
+
exit -1
|
15
|
+
end
|
16
|
+
|
17
|
+
adapter_name = args[0]
|
18
|
+
|
19
|
+
|
20
|
+
stage_path = File.join(Eh::Settings.current.stages_dir, "#{options[:stage]}.yml")
|
21
|
+
stage = Deployer::Stage.load(stage_path)
|
22
|
+
|
23
|
+
puts "deploying #{adapter_name} to #{stage.name} for environment #{stage.node_env}"
|
24
|
+
puts "deploying via: #{options[:deploy_via]}"
|
25
|
+
|
26
|
+
|
27
|
+
base_dir = "/apps/compoundbank/s_cme/apps/event_hub"
|
28
|
+
|
29
|
+
|
30
|
+
if options[:deploy_via] == 'scp'
|
31
|
+
cached_copy_dir = File.join(base_dir, 'eh-cached-copy-scp')
|
32
|
+
else
|
33
|
+
cached_copy_dir = File.join(base_dir, 'eh-cached-copy-scm')
|
34
|
+
end
|
35
|
+
|
36
|
+
adapter_cached_copy = File.join(cached_copy_dir, 'mule', "#{adapter_name}.zip")
|
37
|
+
config_source_dir = File.join(base_dir, 'config', 'mule', adapter_name)
|
38
|
+
|
39
|
+
# TODO: move to common place for all commands
|
40
|
+
scm_username = 'deploy'
|
41
|
+
scm_password = 'deploy2014!'
|
42
|
+
scm_base_url = "https://whistler.plan.io/svn/eventhub"
|
43
|
+
repository = "#{scm_base_url}/branches/master/releases"
|
44
|
+
|
45
|
+
Deployer::Executor.new(stage, verbose: options[:verbose]) do |executor|
|
46
|
+
# create required directories
|
47
|
+
executor.execute("mkdir -p #{base_dir} ; mkdir -p #{File.join(cached_copy_dir, 'mule')}")
|
48
|
+
|
49
|
+
if options[:deploy_via] == 'scp'
|
50
|
+
# upload pre-packaged processor via scp
|
51
|
+
source = "#{Eh::Settings.current.releases_dir}/mule/#{adapter_name}.zip"
|
52
|
+
raise ArgumentError, "#{adapter_name} does not seem to exist, no file to read at #{source}" if !File.readable?(source)
|
53
|
+
executor.upload(source, adapter_cached_copy)
|
54
|
+
else
|
55
|
+
co_line = "svn co --trust-server-cert --non-interactive --username #{scm_username} --password #{scm_password} #{repository} #{cached_copy_dir}"
|
56
|
+
executor.execute(co_line)
|
57
|
+
end
|
58
|
+
|
59
|
+
# copy config
|
60
|
+
source = File.join(config_source_dir, adapter_name)
|
61
|
+
executor.execute("if [[ -d #{config_source_dir} ]] ; then cd #{config_source_dir} ; zip -r #{adapter_cached_copy} . ; fi")
|
62
|
+
|
63
|
+
# deploy
|
64
|
+
executor.execute("cp #{adapter_cached_copy} $MULE_HOME/apps")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|