eventhub-command 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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