eventhub-command 0.1.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f66abed175efcdc6ba3009737a7a8c8fa1672c4
4
- data.tar.gz: 7c74829f7b39de27229d96770d4de564a653b908
3
+ metadata.gz: 5e59a6239b908a41811a317418219b8a4760792e
4
+ data.tar.gz: 1ed264c65607cfeed2698851870da30f7a1c99bf
5
5
  SHA512:
6
- metadata.gz: 0c7bc9272b01e836f9d418e392c9cfd5ca255f56ce8b9cfffa89d7c450d03fdca9a6827d4b16b8dd078681c8b8c082b76cb4c2f4cda01a9452f508f4cd57b0d3
7
- data.tar.gz: 152dc8f8fc1fe2cabc65441f050ba71143460e18a57e1be8e3f4fd4eddd62be6edf39cf4b320bb25f0839224659d66a90b9da5f7cf35a38912db9af8b3a5a495
6
+ metadata.gz: 1733d17688b953e82fe07afa35d1c9a0fd304b78b451463a3217f34ce9c2fd62d7244c88fb2e7cccbd9fe700164cae18d4037298ff880529f479ddbbfbadb998
7
+ data.tar.gz: 322c3ddd44488f03cdd01095b6b95bc2a632930879e92c0007765b2c1e2586673dc103c05398214d0434cccbe3676fffaffb0c7e1a6245acbb4b6dee80cdf71e
data/README.md CHANGED
@@ -19,34 +19,73 @@ $ rbenv rehash
19
19
  First time running the command
20
20
  ~~~ sh
21
21
  $ eh
22
- Config file missing: ~/.eh, will create it now...
23
- Please specify the Eventhub SVN root directory (i.e. the directory which contains the 'src', 'release', ... directories
24
- /Users/username/dev/event_hub
25
- Config file written to /Users/username/.eh. Please try again.
22
+ Created empty config file. Please run 'eh repository add'
26
23
  $
27
24
  ~~~
28
25
 
29
- For some deploy commands you'll need a file describing the target servers (stages).
30
- Put them into
31
-
32
- ~~~
33
- ~/.eh-stages
26
+ Run again:
27
+ ~~~ sh
28
+ $ eh repository add http://something.com/project/svn /Users/foo/eventhub/branches/master username password
29
+ $
34
30
  ~~~
35
31
 
32
+ NOTE: username and password you specify here are from the deploy user.
33
+
34
+ ### Stages
35
+
36
+ Some commands (e.g. deploy commands) will use stages to determine where to deploy. Those stage files are now
37
+ stored in the eventhub SVN repository under config/ directory
38
+
36
39
  The file name is the name of the stage, the content describes environments, hosts, ports and users to use.
37
40
  Content looks like this:
38
41
 
39
42
  ~~~
40
43
  localhost:
41
- node_env: development
42
44
  hosts:
43
45
  - host: localhost
44
46
  port: 2222
45
- user: s_cme
47
+ user: some_user
46
48
  ~~~
47
49
 
48
50
 
51
+ ## Usage
49
52
 
53
+ Help and description for the commands can be obtained through:
54
+
55
+ ~~~
56
+ eh --help
57
+ ~~~
58
+ and more specific for a single command
59
+ ~~~
60
+ eh <COMMAND> --help
61
+ ~~~
62
+
63
+ ### Common options
64
+
65
+ Some common options are:
66
+
67
+ * --stage (one of the names that are listed from list_stages command)
68
+ * --deploy_via (use svn or scp for deployment. If scp, then the local release directory is used, otherwise svn)
69
+ * --branch/--tag (specify a branch or tag to use for "deploy_via scp")
70
+ * --verbose (enable verbose output)
71
+
72
+ ### Commands
73
+
74
+ * deploy_ruby: deploy a ruby processor to a stage. You can specify:
75
+ * a processor name
76
+ * multiple processor names spearated via commas
77
+ * a pattern like something.*
78
+ * a combination of above
79
+ * deploy_mule: deploy a mule adapter to a stage
80
+ * a adapter name
81
+ * multiple adapter names spearated via commas
82
+ * a pattern like something.*
83
+ * a combination of above
84
+ * deploy_config: checkout the latest version of config on target stage and copy to the config folder on stage.
85
+ Those config files will be used uppon next deployment.
86
+ * list_stages: list stages that are available for deploy_* commands
87
+ * package_ruby: package ruby processors to zip files and copy to release directory on local machines. Those packages
88
+ will be used upon next "deploy_via scp" or if you commit them to SVN then upon next "deploy_via svn"
89
+ * generate_processor: generate a processor from a basic template
50
90
 
51
91
 
52
- ## Usage
data/bin/eh CHANGED
@@ -14,14 +14,10 @@ if File.readable?(config_file)
14
14
  settings = Eh::Settings.load(config_file)
15
15
  Eh::Settings.current = settings
16
16
  else
17
- puts "Config file missing: ~/.eh, will create it now..."
18
- puts "Please specify the Eventhub SVN root directory (i.e. the directory which contains the 'src', 'release', ... directories"
19
- input = STDIN.gets.chomp
20
- data = {'repository_root_dir' => input}
21
17
  File.open(config_file, 'w') do |file|
22
- file.write(JSON.dump(data))
18
+ file.write(JSON.dump({}))
23
19
  end
24
- puts "Config file written to #{config_file}. Please try again."
20
+ puts "Created empty config file. Please run 'eh repository add'"
25
21
  exit
26
22
  end
27
23
 
data/lib/deployer.rb CHANGED
@@ -4,3 +4,8 @@ end
4
4
  require_relative 'deployer/executor'
5
5
  require_relative 'deployer/net_ssh_extension'
6
6
  require_relative 'deployer/stage'
7
+
8
+ require_relative 'deployer/base_deployer'
9
+ require_relative 'deployer/mule_deployer'
10
+ require_relative 'deployer/ruby_deployer'
11
+ require_relative 'deployer/config_deployer'
@@ -0,0 +1,136 @@
1
+ class Deployer::BaseDeployer
2
+ attr_reader :options, :stage_path, :stage
3
+
4
+ def initialize(options)
5
+ @options = options
6
+
7
+ @stage_path = File.join(Eh::Settings.current.stages_dir, "#{options[:stage]}.yml")
8
+ @stage = Deployer::Stage.load(stage_path)
9
+ end
10
+
11
+ private
12
+
13
+ def config_source_dir(*extra_paths)
14
+ File.join(base_dir, 'config', *extra_paths)
15
+ end
16
+
17
+ def log_deployment(executor, message)
18
+ executor.execute("echo $(date): #{message} - #{ENV['USER']} >> #{deploy_log_file}")
19
+ end
20
+
21
+ def base_dir
22
+ "/apps/compoundbank/s_cme/apps/event_hub"
23
+ end
24
+
25
+ def deploy_log_file
26
+ File.join(base_dir, 'shared', 'logs', 'deploy.log')
27
+ end
28
+
29
+ def deploy_via
30
+ options[:deploy_via]
31
+ end
32
+
33
+ def verbose?
34
+ options[:verbose]
35
+ end
36
+
37
+ def via_scp?
38
+ deploy_via == 'scp'
39
+ end
40
+
41
+ def cached_copy_dir(*extra_paths)
42
+ dir = if via_scp?
43
+ File.join(base_dir, 'shared', 'cached-copy-scp')
44
+ else
45
+ if options[:tag]
46
+ File.join(base_dir, 'shared', 'cached-copy-svn', 'tags', options[:tag], 'releases')
47
+ elsif options[:branch]
48
+ File.join(base_dir, 'shared', 'cached-copy-svn', 'branches', options[:branch], 'releases')
49
+ else
50
+ File.join(base_dir, 'shared', 'cached-copy-svn', 'branches', 'master', 'releases')
51
+ end
52
+ end
53
+ File.join(dir, *extra_paths)
54
+ end
55
+
56
+ def scm_username
57
+ 'deploy'
58
+ end
59
+
60
+ def scm_password
61
+ 'deploy2014!'
62
+ end
63
+
64
+ def scm_base_url
65
+ "https://whistler.plan.io/svn/eventhub"
66
+ end
67
+
68
+ def repository
69
+ "#{scm_base_url}/branches/master/releases"
70
+ end
71
+
72
+
73
+ def create_base_dirs(executor)
74
+ dirs = [
75
+ File.join(base_dir, 'config'),
76
+ File.join(base_dir, 'ruby'),
77
+ File.join(base_dir, 'mule'),
78
+ File.join(base_dir, 'rails'),
79
+ File.join(base_dir, 'shared'),
80
+ File.join(base_dir, 'shared', 'pids'),
81
+ File.join(base_dir, 'shared', 'logs'),
82
+ File.join(base_dir, 'shared', 'cached-copy-scp')
83
+ ]
84
+ cmds = dirs.map do |dir|
85
+ "mkdir -p #{dir}"
86
+ end
87
+ executor.execute(cmds.join(" && "))
88
+ end
89
+ def update_scm(executor)
90
+ dir = File.join(base_dir, 'shared/cached-copy-svn')
91
+ cmd = <<-EOS
92
+ if [[ -d #{dir} ]]
93
+ then
94
+ cd #{dir}
95
+ svn up --trust-server-cert --non-interactive --username #{scm_username} --password #{scm_password}
96
+ else
97
+ svn co --trust-server-cert --non-interactive --username #{scm_username} --password #{scm_password} #{scm_base_url} #{dir}
98
+ fi
99
+ EOS
100
+ executor.execute(cmd)
101
+ end
102
+
103
+ private
104
+
105
+
106
+ # Executes an ls on all hosts and returns the combined
107
+ # list of files or dirs.
108
+ def remote_ls(executor, options, pattern)
109
+ results = executor.execute("ls #{pattern}", options)
110
+ results.map do |result|
111
+ if result[:stdout]
112
+ result[:stdout].split("\n")
113
+ end
114
+ end.flatten.compact.uniq
115
+ end
116
+
117
+ def verify_deployment_list!(requested, available)
118
+ # remove requested that are not available
119
+ puts 'Deployment List'.light_blue.on_blue
120
+ abort = false
121
+ requested.each do |name|
122
+ if available.include?(name)
123
+ puts "#{name}: AVAILABLE".green
124
+ else
125
+ abort = true
126
+ puts "#{name}: UNAVAILABLE".red
127
+ end
128
+ end
129
+ if abort
130
+ puts 'Not all requested components are available in #{cached_copy_dir}. Will abort.'.red
131
+ raise
132
+ end
133
+
134
+ end
135
+
136
+ end
@@ -0,0 +1,29 @@
1
+ class Deployer::ConfigDeployer < Deployer::BaseDeployer
2
+ def initialize(options = {})
3
+ options[:deploy_via] = 'svn'
4
+ super(options)
5
+ end
6
+
7
+ def deploy!
8
+ puts "deploying to #{stage.name} via #{deploy_via}".light_blue.on_blue
9
+ Deployer::Executor.new(stage, verbose: verbose?) do |executor|
10
+ create_base_dirs(executor)
11
+ update_scm(executor)
12
+
13
+ source = cached_copy_dir('..', 'config', "%{stagename}", "%{hostname}", '')
14
+ target = config_source_dir
15
+
16
+ cmd = "rsync -r --exclude=.svn #{source} #{target}"
17
+ executor.execute(cmd)
18
+ # stage.hosts.each do |host|
19
+ # hostname = host[:host]
20
+ # source = cached_copy_dir('..', 'config', stage.name, hostname, '')
21
+ # target = config_source_dir
22
+
23
+ # # we use rsync to copy without .svn folders
24
+ # cmd = "mkdir -p #{target} && rsync -r --exclude=.svn #{source} #{target}"
25
+ # executor.execute_on(host, cmd)
26
+ # end
27
+ end
28
+ end
29
+ end
@@ -10,32 +10,47 @@ class Deployer::Executor
10
10
  yield(self) if block_given?
11
11
  end
12
12
 
13
-
13
+ # execute a command on all hosts of a stage
14
+ # commands are expanded with :hostname, :port and :stagename
14
15
  def execute(command, options = {})
15
- log_command("Execute: '#{command}'", options[:comment])
16
- stage.hosts.each_with_index do |host, index|
16
+ log_command("Execute: '#{command.strip}'", options[:comment])
17
+ stage.hosts.each_with_index.map do |host, index|
18
+ expand_options = {hostname: host[:host], stagename: stage.name, port: host[:port]}
19
+
20
+ expanded_command = command % expand_options
21
+ if expanded_command != command
22
+ log_command("Expanded command to #{expanded_command}")
23
+ end
17
24
  log_host(host, index)
18
- result = execute_on(host, command)
25
+ result = execute_on(host, expanded_command)
19
26
  log_result(result)
27
+ result
20
28
  end
21
29
 
22
30
  rescue => e
23
31
  handle_exception(e, options)
24
32
  end
25
33
 
34
+
35
+ def execute_on(host, command)
36
+ Net::SSH.start(host[:host], host[:user], port: host[:port]) do |ssh|
37
+ ssh.exec_sc!(command)
38
+ end
39
+ end
40
+
26
41
  def upload(source, target, options = {})
27
42
  log_command("Execute: scp #{source} to #{target}", options[:comment])
28
43
  stage.hosts.each_with_index do |host, index|
29
44
  log_host(host, index)
30
45
  result = upload_on(host, source, target)
31
46
  log_result(result)
47
+ result
32
48
  end
33
49
 
34
50
  rescue => e
35
51
  handle_exception(e, options)
36
52
  end
37
53
 
38
-
39
54
  private
40
55
  def handle_exception(e, options)
41
56
  if options[:abort_on_error] == false
@@ -73,11 +88,7 @@ class Deployer::Executor
73
88
  execute_local "scp -P #{host[:port]} #{source} #{host[:user]}@#{host[:host]}:#{target}"
74
89
  end
75
90
 
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
91
+
81
92
 
82
93
  def execute_local(command)
83
94
  output = nil
@@ -0,0 +1,85 @@
1
+ class Deployer::MuleDeployer < Deployer::BaseDeployer
2
+ attr_reader :adapter_names
3
+
4
+ def initialize(adapter_names, options)
5
+ super(options)
6
+ @adapter_names = adapter_names
7
+ end
8
+
9
+ def adapter_cached_copy(adapter_name)
10
+ cached_copy_dir('mule', "#{adapter_name}.zip")
11
+ end
12
+
13
+ def config_source_dir(adapter_name)
14
+ super('mule', adapter_name)
15
+ end
16
+
17
+ def deploy!
18
+ puts "deploying to #{stage.name} via #{deploy_via}".light_blue.on_blue
19
+
20
+ Deployer::Executor.new(stage, verbose: verbose?) do |executor|
21
+ create_base_dirs(executor)
22
+
23
+ # update
24
+ update_cached_copy(executor)
25
+
26
+ adapter_names_to_deploy = resolve_adapter_names(executor, options)
27
+
28
+ adapter_names_to_deploy.each do |adapter_name|
29
+ puts
30
+ puts "Deploying #{adapter_name}".light_blue.on_blue
31
+ log_deployment(executor, "Deploying #{adapter_name} via #{deploy_via} from #{cached_copy_dir}")
32
+ # make a copy of the zip files to merge them with config
33
+ cached_copy_source = adapter_cached_copy(adapter_name)
34
+ configuration_target = File.join(base_dir, 'mule', "#{adapter_name}.zip")
35
+ executor.execute("cp #{cached_copy_source} #{configuration_target}")
36
+
37
+ # copy config
38
+ config_source = config_source_dir(adapter_name)
39
+ executor.execute("if [[ -d #{config_source} ]] ; then cd #{config_source} ; zip -r #{configuration_target} . ; fi")
40
+
41
+ # deploy
42
+ executor.execute("cp #{adapter_cached_copy(adapter_name)} $MULE_HOME/apps")
43
+ end
44
+ end
45
+ end
46
+
47
+
48
+ private
49
+
50
+ def resolve_adapter_names(executor, options)
51
+ available = remote_ls(executor, options, cached_copy_dir('mule', '*.zip')).map do |name|
52
+ File.basename(name, '.zip')
53
+ end
54
+
55
+ fetched = Array(adapter_names).map do |name|
56
+ if name.include?('*') # resolve pattern on remote machine
57
+ remote_ls(executor, options, cached_copy_dir('mule', "#{name}.zip"))
58
+ else
59
+ name
60
+ end
61
+ end
62
+ if fetched.empty? # then fetch all
63
+ fetched = available
64
+ end
65
+
66
+ fetched = fetched.flatten.map do |name|
67
+ File.basename(name, '.zip')
68
+ end
69
+
70
+ verify_deployment_list!(fetched, available)
71
+
72
+ fetched
73
+ end
74
+
75
+ def update_cached_copy(executor)
76
+ if via_scp?
77
+ source = Eh::Settings.current.releases_dir('mule', '*.zip')
78
+ target_dir = cached_copy_dir('mule')
79
+ executor.execute("rm -rf #{target_dir}/*.zip && mkdir -p #{target_dir}")
80
+ executor.upload(source, target_dir)
81
+ else
82
+ update_scm(executor)
83
+ end
84
+ end
85
+ end
@@ -2,7 +2,7 @@ class Net::SSH::Connection::Session
2
2
 
3
3
  def exec_sc!(command)
4
4
  stdout_data,stderr_data = "",""
5
- exit_code,exit_signal = nil,nil
5
+ exit_code, exit_signal = nil,nil
6
6
  self.open_channel do |channel|
7
7
  channel.exec(command) do |_, success|
8
8
  raise "Command \"#{command}\" was unable to execute" unless success
@@ -0,0 +1,111 @@
1
+ class Deployer::RubyDeployer < Deployer::BaseDeployer
2
+ attr_accessor :processor_names
3
+
4
+ def initialize(processor_names, options)
5
+ super(options)
6
+ @processor_names = processor_names
7
+ end
8
+
9
+ def deploy!
10
+ puts "deploying to #{stage.name} via #{deploy_via}".light_blue.on_blue
11
+
12
+ Deployer::Executor.new(stage, verbose: verbose?) do |executor|
13
+ create_base_dirs(executor)
14
+
15
+
16
+ update_cached_copy(executor)
17
+
18
+
19
+ # fetch processor_names unless they have been passed as an argument to the initializer
20
+ processor_names_to_deploy = resolve_processor_names(executor, options)
21
+ processor_names_to_deploy.each do |processor_name|
22
+ puts
23
+ puts "Deploying #{processor_name}".light_blue.on_blue
24
+ log_deployment(executor, "Deploying #{processor_name} via #{deploy_via} from #{cached_copy_dir}")
25
+ # stop old one
26
+ executor.execute("kill -s TERM $(cat #{File.join(pids_dir, processor_name)}.pid)", abort_on_error: false, comment: "This is not sooo important")
27
+
28
+ # unzip package
29
+ target = deploy_dir('ruby')
30
+ source = cached_copy_dir('ruby',"#{processor_name}.zip")
31
+ executor.execute("rm -rf #{processor_dir(processor_name)} && unzip -o -d #{target} #{source}")
32
+
33
+ # copy config
34
+ executor.execute("if [[ -d #{config_source_dir(processor_name)} ]] ; then cp -r #{config_source_dir(processor_name)}/* #{processor_dir(processor_name)}; fi")
35
+
36
+ # symlink log dir
37
+ executor.execute("ln -s #{logs_dir} #{processor_dir(processor_name, 'logs')}")
38
+
39
+ # symlink pids dir
40
+ executor.execute("ln -s #{pids_dir} #{processor_dir(processor_name, 'pids')}")
41
+
42
+ # install gems
43
+ executor.execute("cd #{processor_dir(processor_name)} && bundle install --without test")
44
+
45
+ # start new one
46
+ executor.execute("cd #{processor_dir(processor_name)} && bundle exec ruby #{processor_name}.rb -d -e $EH_ENV")
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def update_cached_copy(executor)
54
+ if via_scp?
55
+ source = Eh::Settings.current.releases_dir('ruby', '*.zip')
56
+ target_dir = File.join(cached_copy_dir, 'ruby')
57
+ executor.execute("rm -rf #{target_dir}/*.zip && mkdir -p #{target_dir}")
58
+ executor.upload(source, target_dir)
59
+ else
60
+ update_scm(executor)
61
+ end
62
+ end
63
+
64
+ def logs_dir
65
+ File.join(base_dir, 'shared', 'logs')
66
+ end
67
+
68
+ def pids_dir
69
+ File.join(base_dir, 'shared', 'pids')
70
+ end
71
+
72
+ def deploy_dir(*extra_paths)
73
+ File.join(base_dir, *extra_paths)
74
+ end
75
+
76
+ def processor_dir(*extra_paths)
77
+ File.join(deploy_dir, 'ruby', *extra_paths)
78
+ end
79
+
80
+ def config_source_dir(processor_name)
81
+ super('ruby', processor_name)
82
+ end
83
+
84
+ # Detect what processors to deploy
85
+ #
86
+ def resolve_processor_names(executor, options)
87
+ available = remote_ls(executor, options, File.join(cached_copy_dir, 'ruby', '*.zip')).map do |name|
88
+ File.basename(name, '.zip')
89
+ end
90
+
91
+ fetched = Array(processor_names).map do |name|
92
+ if name.include?('*') # resolve pattern on remote machine
93
+ remote_ls(executor, options, File.join(cached_copy_dir, 'ruby', "#{name}.zip"))
94
+ else
95
+ name
96
+ end
97
+ end
98
+ if fetched.empty? # then fetch all
99
+ fetched = available
100
+ end
101
+
102
+ fetched = fetched.flatten.map do |name|
103
+ File.basename(name, '.zip')
104
+ end
105
+
106
+ verify_deployment_list!(fetched, available)
107
+
108
+ fetched
109
+ end
110
+
111
+ end
@@ -1,9 +1,8 @@
1
1
  class Deployer::Stage
2
- attr_reader :name, :node_env, :hosts
2
+ attr_reader :name, :hosts
3
3
 
4
- def initialize(name, node_env)
4
+ def initialize(name)
5
5
  @name = name
6
- @node_env = node_env
7
6
  @hosts = []
8
7
  end
9
8
 
@@ -18,7 +17,7 @@ class Deployer::Stage
18
17
  def self.load(file)
19
18
  data = YAML.load_file(file)
20
19
  data.map do |name, config|
21
- stage = Deployer::Stage.new(name, config['node_env'])
20
+ stage = Deployer::Stage.new(name)
22
21
  config['hosts'].each do |host|
23
22
  stage.host(host['host'], host['port'], host['user'])
24
23
  end
data/lib/eh-commands.rb CHANGED
@@ -1,8 +1,17 @@
1
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'
2
+ if Eh::Settings.current.repository
3
+ require 'eh/commands/deploy'
4
+ require 'eh/commands/generate_processor'
5
+ require 'eh/commands/package_ruby'
6
+ require 'eh/commands/list_stages'
7
+ require 'eh/commands/deploy_config'
8
+ require 'eh/commands/deploy_ruby'
9
+ require 'eh/commands/deploy_mule'
10
+ else
11
+ # remove unused settings for this version
12
+ Eh::Settings.current.data.delete('repository_root_dir')
13
+ Eh::Settings.current.write
14
+ puts "No current repository defined. Please run 'eh repository add' and/or 'eh repository select'"
15
+ end
16
+
17
+ require 'eh/commands/repository'
@@ -1,7 +1,7 @@
1
1
  desc 'Deploys the app'
2
2
  arg_name 'stage', optional: true
3
- command :deploy do |c|
4
3
 
4
+ command :deploy do |c|
5
5
  c.flag([:deploy_via], :desc => "One of 'copy' or 'scm'", :default_value => 'scm')
6
6
  c.flag([:copy_from_dir], :desc => "Source directory for copy operation", :default_value => Eh::Settings.current.releases_dir)
7
7
  c.flag([:tag], :desc => "The tag to deploy")
@@ -0,0 +1,18 @@
1
+ desc 'distribute the configs to the nodes'
2
+
3
+ command :deploy_config do |c|
4
+ c.flag([:stage], desc: 'stage', type: String, long_desc: 'Stage where processor is deployed to', default_value: 'development')
5
+ c.flag([:branch], desc: 'branch', type: String, long_desc: 'What branch to deploy. Only when deploy_via=scm', default_value: 'master')
6
+ c.flag([:tag], desc: 'tag', type: String, long_desc: 'What tag to deploy. Only when deploy_via=scm', default_value: nil)
7
+
8
+ c.switch([:v, :verbose], :desc => 'Show additional output.')
9
+
10
+ c.action do |global_options, options, args|
11
+ begin
12
+ Deployer::ConfigDeployer.new(options).deploy!
13
+ rescue => e
14
+ puts e.message
15
+ puts e.backtrace.join("\n")
16
+ end
17
+ end
18
+ end
@@ -1,68 +1,23 @@
1
-
2
1
  desc 'deploy a single channel adapter'
3
- arg_name 'channel_adapter stage'
2
+ arg_name '[channel_adapter[,other_channel_adapter,pattern*]]'
4
3
 
5
4
  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')
5
+ c.flag([:stage], desc: 'stage', type: String, long_desc: 'Stage where channel adapter is deployed to', default_value: 'development')
6
+ 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
7
 
9
- c.switch([:v, :verbose], :desc => "Show additional output.")
8
+ c.switch([:v, :verbose], :desc => 'Show additional output.')
10
9
 
11
10
  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}")
48
- executor.execute("rm -rf #{cached_copy_dir}")
49
-
50
- if options[:deploy_via] == 'scp'
51
- # upload pre-packaged processor via scp
52
- source = "#{Eh::Settings.current.releases_dir}/mule/#{adapter_name}.zip"
53
- raise ArgumentError, "#{adapter_name} does not seem to exist, no file to read at #{source}" if !File.readable?(source)
54
- executor.upload(source, adapter_cached_copy)
11
+ begin
12
+ if args[0]
13
+ adapter_names = args[0].split(',').map(&:strip)
55
14
  else
56
- co_line = "svn co --trust-server-cert --non-interactive --username #{scm_username} --password #{scm_password} #{repository} #{cached_copy_dir}"
57
- executor.execute(co_line)
15
+ adapter_names = nil
58
16
  end
59
-
60
- # copy config
61
- source = File.join(config_source_dir, adapter_name)
62
- executor.execute("if [[ -d #{config_source_dir} ]] ; then cd #{config_source_dir} ; zip -r #{adapter_cached_copy} . ; fi")
63
-
64
- # deploy
65
- executor.execute("cp #{adapter_cached_copy} $MULE_HOME/apps")
17
+ Deployer::MuleDeployer.new(adapter_names, options).deploy!
18
+ rescue => e
19
+ puts e.message
20
+ puts e.backtrace.join("\n")
66
21
  end
67
22
  end
68
23
  end
@@ -1,87 +1,25 @@
1
1
  desc 'deploy a single ruby processor'
2
- arg_name 'processor_name stage'
2
+ arg_name '[processor_name,[other_processor_name,pattern*]]'
3
3
 
4
4
  command :deploy_ruby do |c|
5
- c.flag([:s, :stage], desc: "stage", type: String, long_desc: "Stage where processor is deployed to", default_value: 'localhost')
6
- c.flag([:deploy_via], desc: "how to get hold of the processor: scm or scp", type: String, long_desc: "copy the processor zip file via scp from this machine or check it out from scm", default_value: 'scp')
5
+ c.flag([:stage], desc: 'stage', type: String, long_desc: 'Stage where processor is deployed to', default_value: 'development')
6
+ c.flag([:deploy_via], desc: 'how to get hold of the processor: scm or scp', type: String, long_desc: 'copy the processor zip file via scp from this machine or check it out from scm', default_value: 'scp')
7
+ c.flag([:branch], desc: 'branch', type: String, long_desc: 'What branch to deploy. Only when deploy_via=scm', default_value: 'master')
8
+ c.flag([:tag], desc: 'tag', type: String, long_desc: 'What tag to deploy. Only when deploy_via=scm', default_value: nil)
7
9
 
8
- c.switch([:v, :verbose], :desc => "Show additional output.")
10
+ c.switch([:v, :verbose], :desc => 'Show additional output.')
9
11
 
10
12
  c.action do |global_options, options, args|
11
-
12
- if args.size < 1
13
- puts "Needs at least one argument: processor_name"
14
- exit -1
15
- end
16
-
17
- processor_name = args[0]
18
- stage_path = File.join(Eh::Settings.current.stages_dir, "#{options[:stage]}.yml")
19
- stage = Deployer::Stage.load(stage_path)
20
-
21
-
22
- puts "deploying #{processor_name} to #{stage.name} for environment #{stage.node_env}"
23
- puts "deploying via: #{options[:deploy_via]}"
24
-
25
-
26
- base_dir = "/apps/compoundbank/s_cme/apps/event_hub"
27
- logs_dir = File.join(base_dir, 'shared', 'logs')
28
- pids_dir = File.join(base_dir, 'shared', 'pids')
29
-
30
-
31
- if options[:deploy_via] == 'scp'
32
- cached_copy_dir = File.join(base_dir, 'eh-cached-copy-scp')
33
- else
34
- cached_copy_dir = File.join(base_dir, 'eh-cached-copy-scm')
35
- end
36
-
37
- current_dir = File.join(base_dir, 'eh-current')
38
-
39
- processor_dir = File.join(current_dir, 'ruby', processor_name)
40
- config_source_dir = File.join(base_dir, 'config', 'ruby', processor_name)
41
-
42
- # TODO: move to common place
43
- scm_username = 'deploy'
44
- scm_password = 'deploy2014!'
45
- scm_base_url = "https://whistler.plan.io/svn/eventhub"
46
- repository = "#{scm_base_url}/branches/master/releases"
47
-
48
- Deployer::Executor.new(stage, verbose: options[:verbose]) do |executor|
49
- # create required directories
50
- executor.execute("mkdir -p #{base_dir} ; mkdir -p #{logs_dir} ; mkdir -p #{File.join(current_dir, 'ruby')} ; mkdir -p #{File.join(cached_copy_dir, 'ruby')}")
51
-
52
- if options[:deploy_via] == 'scp'
53
- # upload pre-packaged processor via scp
54
- source = "#{Eh::Settings.current.releases_dir}/ruby/#{processor_name}.zip"
55
- target = File.join(cached_copy_dir, 'ruby', "#{processor_name}.zip")
56
- executor.upload(source, target)
13
+ begin
14
+ if args[0]
15
+ processor_names = args[0].split(',').map(&:strip)
57
16
  else
58
- co_line = "svn co --trust-server-cert --non-interactive --username #{scm_username} --password #{scm_password} #{repository} #{cached_copy_dir}"
59
- executor.execute(co_line)
17
+ processor_names = nil
60
18
  end
61
-
62
- # unzip package
63
- source = File.join(current_dir, 'ruby')
64
- target = "#{File.join(cached_copy_dir, 'ruby', processor_name)}.zip"
65
- executor.execute("unzip -o -d #{source} #{target}")
66
-
67
- # copy config
68
- executor.execute("if [[ -d #{config_source_dir} ]] ; then cp -r #{config_source_dir}/* #{processor_dir}; fi")
69
-
70
- # symlink log dir
71
- executor.execute("ln -s #{logs_dir} #{File.join(processor_dir, 'logs')}")
72
-
73
- # symlink pids dir
74
- executor.execute("ln -s #{pids_dir} #{File.join(processor_dir, 'pids')}")
75
-
76
- # install gems
77
- executor.execute("cd #{processor_dir} && bundle install --without test")
78
-
79
- # stop old one
80
- executor.execute("kill -s TERM $(cat #{File.join(pids_dir, processor_name)}.pid)", abort_on_error: false, comment: "This is not sooo important")
81
-
82
- # start new one
83
- executor.execute("cd #{processor_dir} && bundle exec ruby #{processor_name}.rb -d --environment=#{stage.node_env}")
19
+ Deployer::RubyDeployer.new(processor_names, options).deploy!
20
+ rescue => e
21
+ puts e.message
22
+ puts e.backtrace.join("\n")
84
23
  end
85
-
86
24
  end
87
25
  end
@@ -0,0 +1,17 @@
1
+ desc 'list the available stages'
2
+
3
+ command :list_stages do |c|
4
+ #c.flag([:branch], desc: 'branch', type: String, long_desc: 'What branch to deploy. Only when deploy_via=scm', default_value: 'master')
5
+ #c.flag([:tag], desc: 'tag', type: String, long_desc: 'What tag to deploy. Only when deploy_via=scm', default_value: nil)
6
+
7
+ c.switch([:v, :verbose], :desc => 'Show additional output.')
8
+
9
+ c.action do |global_options, options, args|
10
+ dir = Eh::Settings.current.stages_dir
11
+ puts "Checking in #{dir}".green if options[:verbose]
12
+ puts "Available stages are:".blue
13
+ Dir.glob(File.join(dir, '*.yml')) do |name|
14
+ puts "#{File.basename(name, '.*')}".light_blue
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  desc 'Packages processors to zip files'
2
- command :package do |c|
2
+ command :package_ruby do |c|
3
3
  c.flag([:x, :exclude], :desc => "Exclude processors by name.", :type => Array, :long_desc => "You can specify multiple processors by providing a comma-separated list.")
4
4
  c.flag([:p, :processors], :desc => "Specify what processors to package", :type => Array, :long_desc => "You can specify multiple processors by providing a comma-separated list.")
5
5
  c.flag([:d, :destination], :desc => "Destination directory to place created zip files.", :default_value => Eh::Settings.current.ruby_release_dir)
@@ -0,0 +1,71 @@
1
+ desc "manage repositories"
2
+
3
+ command :repository do |command|
4
+ command.desc "Lists all avaiable repositories"
5
+ command.command :list do |command|
6
+ command.action do |global_options,options,args|
7
+ Eh::Settings.current.repositories.each_with_index do |repository, index|
8
+ if repository.current?
9
+ puts "#{index + 1}: #{repository.url} (current)"
10
+ else
11
+ puts "#{index + 1}: #{repository.url}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ command.desc "selects a repository: eh repository select INDEX"
18
+ command.command :select do |command|
19
+ command.action do |global_options,options,args|
20
+ if Eh::Settings.current.repositories.length == 0
21
+ raise "No repository configured so far"
22
+ end
23
+ if args.length != 1
24
+ raise "Need exactly 1 arguments: index"
25
+ end
26
+ selected = args[0].to_i
27
+ puts "Will select #{args[0]}"
28
+ Eh::Settings.current.data['repositories'].each_with_index do |repository, index|
29
+ repository['current'] = (index + 1) == selected
30
+ end
31
+ Eh::Settings.current.write
32
+ end
33
+ end
34
+
35
+ command.desc 'add a repository to the config: eh repository add URL DIR USERNAME PASSWORD'
36
+ command.command :add do |command|
37
+ command.action do |global_options, options, args|
38
+ if args.length != 4
39
+ raise "Need exactly 4 arguments: URL, DIR, USERNAME, PASSWORD"
40
+ end
41
+ Eh::Settings.current.data['repositories'] ||= []
42
+ Eh::Settings.current.data['repositories'] << {
43
+ 'url' => args[0],
44
+ 'dir' => args[1],
45
+ 'deploy_username' => args[2],
46
+ 'deploy_password' => args[3],
47
+ 'current' => (Eh::Settings.current.data['repositories'].length == 0)
48
+ }
49
+ Eh::Settings.current.write
50
+ end
51
+ end
52
+
53
+
54
+ command.desc 'remove a repository from the config: eh repository remove INDEX'
55
+ command.command :remove do |command|
56
+ command.action do |global_options, options, args|
57
+
58
+ if args.length != 1
59
+ raise "Need exactly 1 arguments: index"
60
+ end
61
+ selected = args[0].to_i
62
+
63
+ if Eh::Settings.current.repositories[selected - 1].nil?
64
+ raise "No repository with index #{selected}"
65
+ end
66
+
67
+ Eh::Settings.current.data['repositories'].delete_at(selected - 1)
68
+ Eh::Settings.current.write
69
+ end
70
+ end
71
+ end
data/lib/eh/settings.rb CHANGED
@@ -1,9 +1,46 @@
1
1
  class Eh::Settings
2
- attr_reader :data
2
+
3
+ attr_reader :data, :file
4
+
5
+ class Repository
6
+ def initialize(json)
7
+ @json = json
8
+ end
9
+
10
+ def url
11
+ @json['url']
12
+ end
13
+
14
+ def deploy_username
15
+ @json['deploy_username']
16
+ end
17
+
18
+ def deploy_password
19
+ @json['deploy_password']
20
+ end
21
+
22
+ def dir
23
+ @json['dir']
24
+ end
25
+
26
+ def current?
27
+ @json['current']
28
+ end
29
+ end
30
+
31
+ def initialize(file)
32
+ @file = file
33
+ @data = JSON.parse(File.read(file))
34
+ end
35
+
3
36
  def self.load(file)
4
- data = File.read(file)
5
- json = JSON.parse(data)
6
- Eh::Settings.new(json)
37
+ Eh::Settings.new(file)
38
+ end
39
+
40
+ def write
41
+ File.open(file,"w") do |f|
42
+ f.write(data.to_json)
43
+ end
7
44
  end
8
45
 
9
46
  def self.current=(value)
@@ -14,40 +51,44 @@ class Eh::Settings
14
51
  Thread.current[:eh_settings]
15
52
  end
16
53
 
17
- def initialize(data)
18
- @data = data
54
+ def repository
55
+ repositories.find do |repository|
56
+ repository.current?
57
+ end if repositories
19
58
  end
20
59
 
21
- def repository_root_dir
22
- File.expand_path(data['repository_root_dir'])
60
+ def repositories
61
+ data["repositories"].map do |json|
62
+ Eh::Settings::Repository.new(json)
63
+ end if data["repositories"]
23
64
  end
24
65
 
25
- def releases_dir
26
- File.join(repository_root_dir, 'releases')
66
+ def releases_dir(*extra_paths)
67
+ File.join(repository.dir, 'releases', *extra_paths)
27
68
  end
28
69
 
29
70
  def rails_release_dir
30
- File.join(releases_dir, 'rails')
71
+ releases_dir('rails')
31
72
  end
32
73
 
33
74
  def ruby_release_dir
34
- File.join(releases_dir, 'ruby')
75
+ releases_dir('ruby')
35
76
  end
36
77
 
37
78
  def processors_src_dir
38
- File.join(repository_root_dir, 'src', 'ruby')
79
+ File.join(repository.dir, 'src', 'ruby')
39
80
  end
40
81
 
41
82
  def deployment_dir
42
- File.join(repository_root_dir, 'src', 'deployment')
83
+ File.join(repository.dir, 'src', 'deployment')
43
84
  end
44
85
 
45
86
  def rails_src_dir
46
- File.join(repository_root_dir, 'src', 'rails', 'console')
87
+ File.join(repository.dir, 'src', 'rails', 'console')
47
88
  end
48
89
 
49
90
  def source_config_dir
50
- File.join(repository_root_dir, 'config')
91
+ File.join(repository.dir, 'config')
51
92
  end
52
93
 
53
94
  def processor_template_repository_url
@@ -67,6 +108,6 @@ class Eh::Settings
67
108
  end
68
109
 
69
110
  def stages_dir
70
- File.expand_path("~/.eh-stages")
111
+ File.join(repository.dir, 'config', 'stages')
71
112
  end
72
113
  end
data/lib/eh/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eh
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventhub-command
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pascal Betz
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-12-19 00:00:00.000000000 Z
12
+ date: 2015-02-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -142,22 +142,25 @@ files:
142
142
  - bin/eh
143
143
  - eh.gemspec
144
144
  - eh.rdoc
145
- - features/eh.feature
146
- - features/step_definitions/eh_steps.rb
147
- - features/support/env.rb
148
145
  - lib/deployer.rb
146
+ - lib/deployer/base_deployer.rb
147
+ - lib/deployer/config_deployer.rb
149
148
  - lib/deployer/executor.rb
149
+ - lib/deployer/mule_deployer.rb
150
150
  - lib/deployer/net_ssh_extension.rb
151
+ - lib/deployer/ruby_deployer.rb
151
152
  - lib/deployer/stage.rb
152
153
  - lib/eh-commands.rb
153
154
  - lib/eh.rb
154
155
  - lib/eh/commands/copy_config.rb
155
156
  - lib/eh/commands/deploy.rb
157
+ - lib/eh/commands/deploy_config.rb
156
158
  - lib/eh/commands/deploy_mule.rb
157
159
  - lib/eh/commands/deploy_ruby.rb
158
160
  - lib/eh/commands/generate_processor.rb
159
- - lib/eh/commands/package.rb
160
- - lib/eh/commands/package_rails.rb
161
+ - lib/eh/commands/list_stages.rb
162
+ - lib/eh/commands/package_ruby.rb
163
+ - lib/eh/commands/repository.rb
161
164
  - lib/eh/settings.rb
162
165
  - lib/eh/version.rb
163
166
  - test/default_test.rb
data/features/eh.feature DELETED
@@ -1,8 +0,0 @@
1
- Feature: My bootstrapped app kinda works
2
- In order to get going on coding my awesome app
3
- I want to have aruba and cucumber setup
4
- So I don't have to do it myself
5
-
6
- Scenario: App just runs
7
- When I get help for "eh"
8
- Then the exit status should be 0
@@ -1,6 +0,0 @@
1
- When /^I get help for "([^"]*)"$/ do |app_name|
2
- @app_name = app_name
3
- step %(I run `#{app_name} help`)
4
- end
5
-
6
- # Add more step definitions here
@@ -1,15 +0,0 @@
1
- require 'aruba/cucumber'
2
-
3
- ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
4
- LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
5
-
6
- Before do
7
- # Using "announce" causes massive warnings on 1.9.2
8
- @puts = true
9
- @original_rubylib = ENV['RUBYLIB']
10
- ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
11
- end
12
-
13
- After do
14
- ENV['RUBYLIB'] = @original_rubylib
15
- end
@@ -1,68 +0,0 @@
1
- desc 'Packages Rails Console to zip file'
2
- command :package_rails do |c|
3
- c.flag([:d, :destination], :desc => "Destination directory to place created zip file.", :default_value => Eh::Settings.current.rails_release_dir)
4
- c.flag([:s, :source], :desc => "Source directory to read rails console from.", :default_value => Eh::Settings.current.rails_src_dir)
5
-
6
- c.action do |global_options, options, args|
7
- source_dir = options['s']
8
- destination_dir = options['d']
9
-
10
- skip_files = ["#{source_dir}/config/database.yml"]
11
-
12
- puts "Will package rails console from #{source_dir} to #{destination_dir}"
13
-
14
- console = Dir["#{source_dir}"]
15
-
16
- FileUtils.mkdir_p(destination_dir)
17
-
18
- zipfile_name = File.join(destination_dir, "console.zip")
19
- directory = source_dir
20
-
21
- # remove zip before we create a new one
22
- FileUtils.rm zipfile_name, :force => true
23
-
24
- Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
25
-
26
- #zipfile.add(processor_name, directory)
27
- [directory].each do |file_to_be_zipped|
28
- if File.directory?(file_to_be_zipped)
29
- # should skip directories
30
- next if options["directories-skip"]
31
-
32
- directory = file_to_be_zipped
33
- puts "zipper: archiving directory: #{directory}"
34
- directory_chosen_pathname = options["directories-recursively-splat"] ? directory : File.dirname(directory)
35
- directory_pathname = Pathname.new(directory_chosen_pathname)
36
- files = Dir[File.join(directory, '**', '**')]
37
-
38
- files.delete_if do |filename|
39
- ["#{source_dir}/log", "#{source_dir}/logs", "#{source_dir}/exceptions", "#{source_dir}/tmp"].any? do |prefix|
40
- filename.start_with?(prefix)
41
- end
42
- end
43
-
44
- files.each do |file|
45
- if skip_files.include? file
46
- puts "skipping #{file}"
47
- next
48
- end
49
-
50
- file_pathname = Pathname.new(file)
51
- file_relative_pathname = file_pathname.relative_path_from(directory_pathname)
52
- zipfile.add(file_relative_pathname,file)
53
- end
54
-
55
- next
56
- end
57
-
58
- filename = File.basename(file_to_be_zipped)
59
-
60
- puts "zipper: archiving #{file_to_be_zipped} as #{filename} into #{zipfile}"
61
-
62
- zipfile.add(filename,file_to_be_zipped)
63
- end
64
- end
65
-
66
- puts "Done packaging rails"
67
- end
68
- end