avodeploy 0.4 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +14 -0
  3. data/README.md +8 -5
  4. data/avodeploy.gemspec +3 -4
  5. data/bin/avo +14 -12
  6. data/lib/avodeploy.rb +29 -0
  7. data/lib/{avocado → avodeploy}/bootstrap.rb +24 -30
  8. data/lib/{avocado → avodeploy}/command_execution_result.rb +1 -1
  9. data/lib/{avocado → avodeploy}/config.rb +8 -4
  10. data/lib/{avocado → avodeploy}/core_ext/hash_insert_at.rb +0 -0
  11. data/lib/{avocado → avodeploy}/core_ext/string_colors.rb +0 -0
  12. data/lib/{avocado → avodeploy}/deployment.rb +3 -3
  13. data/lib/{avocado → avodeploy}/multi_io.rb +1 -1
  14. data/lib/avodeploy/scm_provider/git_scm_provider.rb +73 -0
  15. data/lib/avodeploy/scm_provider/scm_provider.rb +70 -0
  16. data/lib/{avocado → avodeploy}/skel/manifest_template.rb.erb +1 -1
  17. data/lib/{avocado → avodeploy}/strategy/base.rb +1 -1
  18. data/lib/avodeploy/strategy/local_copy.rb +101 -0
  19. data/lib/{avocado → avodeploy}/target.rb +3 -1
  20. data/lib/avodeploy/task/local_task_execution_environment.rb +127 -0
  21. data/lib/avodeploy/task/remote_task_execution_environment.rb +114 -0
  22. data/lib/avodeploy/task/task.rb +76 -0
  23. data/lib/{avocado → avodeploy}/task/task_dependency.rb +8 -6
  24. data/lib/avodeploy/task/task_execution_environment.rb +88 -0
  25. data/lib/avodeploy/task/task_manager.rb +185 -0
  26. data/lib/{avocado → avodeploy}/version.rb +2 -2
  27. metadata +27 -40
  28. data/lib/avocado/Gemfile +0 -9
  29. data/lib/avocado/scm_provider/git_scm_provider.rb +0 -71
  30. data/lib/avocado/scm_provider/scm_provider.rb +0 -68
  31. data/lib/avocado/strategy/local_copy.rb +0 -99
  32. data/lib/avocado/task/local_task_execution_environment.rb +0 -127
  33. data/lib/avocado/task/remote_task_execution_environment.rb +0 -112
  34. data/lib/avocado/task/task.rb +0 -84
  35. data/lib/avocado/task/task_execution_environment.rb +0 -86
  36. data/lib/avocado/task/task_manager.rb +0 -183
@@ -0,0 +1,70 @@
1
+ =begin
2
+ AVOCADO
3
+ The flexible and easy to use deployment framework for web applications
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License Version 2
7
+ as published by the Free Software Foundation.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+ =end
18
+
19
+ module AvoDeploy
20
+ module ScmProvider
21
+ # scm provider facade
22
+ class ScmProvider
23
+
24
+ # Initializes the scm provider
25
+ #
26
+ # @param env [TaskExecutionEnvironment] env for the commands to be executed in
27
+ # @param scm [Symbol] the scm provider to user
28
+ def initialize(env, scm)
29
+ raise ArgumentError, 'env must be a TaskExecutionEnvironment' unless env.is_a?(AvoDeploy::Task::TaskExecutionEnvironment)
30
+
31
+ @env = env
32
+ @real_provider = nil
33
+
34
+ if scm == :git
35
+ @real_provider = GitScmProvider.new(env)
36
+ end
37
+ end
38
+
39
+ # Checks out repository code from a system and switches to the given branch
40
+ #
41
+ # @param url [String] the repository location
42
+ # @param local_dir [String] path to the working copy
43
+ # @param branch [String] the branch to check out
44
+ def checkout_from_remote(url, local_dir, branch)
45
+ @real_provider.checkout_from_remote(url, local_dir, branch)
46
+ end
47
+
48
+ # Returns the current revision of the working copy
49
+ #
50
+ # @return [String] the current revision of the working copy
51
+ def scm_files
52
+ @real_provider.scm_files
53
+ end
54
+
55
+ # Returns scm files to be executed in the deployment process
56
+ #
57
+ # @return [Array] array of scm control files
58
+ def cli_utils
59
+ @real_provider.cli_utils
60
+ end
61
+
62
+ # Returns the scm tools that have to be installed on specific systems
63
+ #
64
+ # @return [Array] array of utilities
65
+ def revision
66
+ @real_provider.revision
67
+ end
68
+ end
69
+ end
70
+ end
@@ -1,4 +1,4 @@
1
- Avocado::Deployment.configure do
1
+ AvoDeploy::Deployment.configure do
2
2
 
3
3
  # AVOCADO
4
4
  # The flexible and easy to use deployment framework for web applications
@@ -16,7 +16,7 @@
16
16
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
  =end
18
18
 
19
- Avocado::Deployment.configure do
19
+ AvoDeploy::Deployment.configure do
20
20
 
21
21
  task :deploy, visibility: :public do
22
22
  # stub for cli calls
@@ -0,0 +1,101 @@
1
+ =begin
2
+ AVOCADO
3
+ The flexible and easy to use deployment framework for web applications
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License Version 2
7
+ as published by the Free Software Foundation.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+ =end
18
+
19
+ AvoDeploy::Deployment.configure do
20
+
21
+ task :check_targets, before: :deploy do
22
+ raise RuntimeError, 'No target systems are configured' if targets.empty?
23
+ end
24
+
25
+ task :check_local_tools, before: :deploy do
26
+ check_util_availability [ 'tar' ].concat(@scm.cli_utils)
27
+ end
28
+
29
+ task :check_remote_system, before: :deploy do
30
+ check_util_availability [ 'tar' ]
31
+ end
32
+
33
+ task :check_temp_existance, after: :deploy do
34
+ if File.exist?('.avocado-tmp')
35
+ raise RuntimeError, 'The avocado tmp directory (.avocado-tmp) does already exist. That may indicate that another deployment is already running.'
36
+ end
37
+ end
38
+
39
+ task :switch_to_temp_dir, after: :check_temp_existance do
40
+ command "mkdir .avocado-tmp/"
41
+ chdir ".avocado-tmp/"
42
+ end
43
+
44
+ task :checkout_from_scm, after: :switch_to_temp_dir do
45
+ @scm.checkout_from_remote(get(:repo_url), 'working-copy', get(:branch))
46
+ end
47
+
48
+ task :chdir_to_working_copy, after: :checkout_from_scm do
49
+ chdir "working-copy/"
50
+ end
51
+
52
+ task :get_scm_info, after: :chdir_to_working_copy do
53
+ set :revision, @scm.revision
54
+ end
55
+
56
+ task :delete_ignored_files, after: :get_scm_info do
57
+ files_to_delete = [ 'Avofile' ].concat(get(:ignore_files)).concat(@scm.scm_files)
58
+
59
+ command "rm -rfv #{files_to_delete.join(' ')}"
60
+ end
61
+
62
+ task :create_revision_file, after: :delete_ignored_files do
63
+ command "echo '#{get(:revision)}' > REVISION"
64
+ end
65
+
66
+ task :create_deployment_tarball, after: :create_revision_file do
67
+ command "tar cvfz ../deploy.tar.gz ."
68
+ end
69
+
70
+ task :switch_to_parent_dir, after: :create_deployment_tarball do
71
+ chdir "../"
72
+ end
73
+
74
+ task :upload, after: :switch_to_parent_dir do
75
+ targets.each_pair do |key, target|
76
+ copy_to_target(target, 'deploy.tar.gz', '/tmp/deploy.tar.gz')
77
+ end
78
+ end
79
+
80
+ task :create_deploy_dir, after: :upload, scope: :remote do
81
+ command "if [ ! -d '#{get(:deploy_dir)}' ]; then mkdir -p #{get(:deploy_dir)}; fi"
82
+ end
83
+
84
+ task :unpack, after: :create_deploy_dir, scope: :remote do
85
+ command "tar xvfz /tmp/deploy.tar.gz -C #{get(:deploy_dir)}/"
86
+ end
87
+
88
+ task :cleanup_remote, after: :unpack, scope: :remote do
89
+ command "rm /tmp/deploy.tar.gz"
90
+ end
91
+
92
+ task :log_deployment, after: :cleanup_remote, scope: :remote do
93
+ command "echo '[#{Time.now.strftime('%Y-%m-%d %H-%M-%S')}] revision #{get(:revision)} deployed by #{ENV['USER']}' >> #{get(:log_file)}"
94
+ end
95
+
96
+ task :cleanup_local, after: :cleanup_remote do
97
+ chdir "../"
98
+ command "rm -rf .avocado-tmp"
99
+ end
100
+
101
+ end
@@ -16,7 +16,7 @@
16
16
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
  =end
18
18
 
19
- module Avocado
19
+ module AvoDeploy
20
20
  class Target
21
21
 
22
22
  attr_reader :name
@@ -29,6 +29,7 @@ module Avocado
29
29
  def initialize(name, config)
30
30
  @name = name
31
31
  @config = default_config.merge(config)
32
+ @config[:name] = name
32
33
  end
33
34
 
34
35
  private
@@ -37,6 +38,7 @@ module Avocado
37
38
  # @return [Hash] config defaults
38
39
  def default_config
39
40
  {
41
+ :name => '',
40
42
  :host => nil,
41
43
  :user => 'root',
42
44
  :auth => :pubkey,
@@ -0,0 +1,127 @@
1
+ =begin
2
+ AVOCADO
3
+ The flexible and easy to use deployment framework for web applications
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License Version 2
7
+ as published by the Free Software Foundation.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+ =end
18
+
19
+ module AvoDeploy
20
+ module Task
21
+ class LocalTaskExecutionEnvironment < TaskExecutionEnvironment
22
+
23
+ # Initialized the environment
24
+ #
25
+ # @param config [Hash] deployment configuration
26
+ def initialize(config)
27
+ super
28
+
29
+ @dir = Dir.pwd
30
+ end
31
+
32
+ # Checks, if all utilities are available for the deployment process
33
+ # to be executed
34
+ #
35
+ # @param utils [Array] array with utilities to check
36
+ def check_util_availability(utils)
37
+ super(utils, 'locally')
38
+ end
39
+
40
+ # Changes the directory for commands to be executed in
41
+ #
42
+ # @param dir [String] the directory to change to
43
+ def chdir(dir)
44
+ log.debug "changing directory [#{dir.yellow}] " + "locally".cyan
45
+
46
+ Dir.chdir(dir)
47
+ @dir = Dir.pwd
48
+ end
49
+
50
+ # Returns the current working directory
51
+ #
52
+ # @return [String] current working directory
53
+ def cwd
54
+ @dir
55
+ end
56
+
57
+ # Returns all target systems to deploy to
58
+ #
59
+ # @return [Hash] hash of target systems
60
+ def targets
61
+ AvoDeploy::Deployment.instance.config.targets
62
+ end
63
+
64
+ # Copies a file to a remote system (= target)
65
+ #
66
+ # @param target [Target] the target system to deploy to
67
+ # @param file [String] the local file to upload
68
+ # @param remote [String] path on the remote system
69
+ def copy_to_target(target, file, remote)
70
+ log = AvoDeploy::Deployment.instance.log
71
+
72
+ log.info "started upload of file #{file} to #{target.name}"
73
+
74
+ Net::SSH.start(
75
+ target.config[:host],
76
+ target.config[:user]
77
+ ) do |session|
78
+ session.scp.upload!(file, remote, :recursive => true) do |ch, name, sent, total|
79
+ percentage = 0
80
+
81
+ begin
82
+ percentage = (sent.to_f * 100 / total.to_f).to_i
83
+ rescue Exception => e
84
+ AvoDeploy::Deployment.instance.handle_abort(e)
85
+ end
86
+ end
87
+ end
88
+
89
+ log.info "upload completed"
90
+ end
91
+
92
+ # Executes a command locally in the current directory
93
+ #
94
+ # @param cmd [String] the command to execute
95
+ # @return [CommandExecutionResult] result of the command exection
96
+ def command(cmd)
97
+ log = AvoDeploy::Deployment.instance.log
98
+
99
+ log.info "Executing [" + cmd.yellow + "] " + "locally".cyan
100
+
101
+ result = AvoDeploy::CommandExecutionResult.new
102
+
103
+ begin
104
+ stdout, stderr, status = ::Open3.capture3(cmd, :chdir => cwd())
105
+
106
+ result.stdin = cmd
107
+ result.stdout = stdout
108
+ result.stderr = stderr
109
+ result.retval = status.exitstatus
110
+
111
+ if result.stdout.nil? == false && result.stdout.empty? == false
112
+ log.debug "Stdout: " + result.stdout.green
113
+ end
114
+
115
+ if result.stderr.nil? == false && result.stderr.empty? == false
116
+ log.debug "Stderr: " + result.stderr.red
117
+ end
118
+ rescue Exception => e
119
+ handle_abort e
120
+ end
121
+
122
+ result
123
+ end
124
+
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,114 @@
1
+ =begin
2
+ AVOCADO
3
+ The flexible and easy to use deployment framework for web applications
4
+
5
+ This program is free software; you can redistribute it and/or
6
+ modify it under the terms of the GNU General Public License Version 2
7
+ as published by the Free Software Foundation.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program; if not, write to the Free Software
16
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+ =end
18
+
19
+ module AvoDeploy
20
+ module Task
21
+ class RemoteTaskExecutionEnvironment < TaskExecutionEnvironment
22
+
23
+ attr_accessor :config
24
+
25
+ # Creates a connection between the local and the remote system over ssh
26
+ def establish_connection
27
+ AvoDeploy::Deployment.instance.log.info "connecting to #{get(:user)}@#{get(:host)}..."
28
+
29
+ begin
30
+ @session = ::Net::SSH.start(get(:host), get(:user))
31
+ rescue ::Net::SSH::AuthenticationFailed => e
32
+ handle_abort e
33
+ end
34
+ end
35
+
36
+ # Checks, if all utilities are available for the deployment process
37
+ # to be executed
38
+ #
39
+ # @param utils [Array] array with utilities to check
40
+ def check_util_availability(utils)
41
+ super(utils, 'remotely')
42
+ end
43
+
44
+ # Executes a command via ssh
45
+ #
46
+ # @param ssh [Net::SSH::Connection::Session] ssh session
47
+ # @param command [String] the command to execute
48
+ def ssh_exec!(ssh, command)
49
+ stdout_data = ""
50
+ stderr_data = ""
51
+ exit_code = nil
52
+ exit_signal = nil
53
+ ssh.open_channel do |channel|
54
+ channel.exec(command) do |ch, success|
55
+ unless success
56
+ abort "FAILED: couldn't execute command (ssh.channel.exec)"
57
+ end
58
+ channel.on_data do |ch,data|
59
+ stdout_data+=data
60
+ end
61
+
62
+ channel.on_extended_data do |ch,type,data|
63
+ stderr_data+=data
64
+ end
65
+
66
+ channel.on_request("exit-status") do |ch,data|
67
+ exit_code = data.read_long
68
+ end
69
+
70
+ channel.on_request("exit-signal") do |ch, data|
71
+ exit_signal = data.read_long
72
+ end
73
+ end
74
+ end
75
+ ssh.loop
76
+
77
+ result = AvoDeploy::CommandExecutionResult.new
78
+ result.stdin = command
79
+ result.stdout = stdout_data
80
+ result.stderr = stderr_data
81
+ result.retval = exit_code
82
+
83
+ result
84
+ end
85
+
86
+ # Executes a command on the remote system
87
+ #
88
+ # @param cmd [String] the command to execute
89
+ # @return [CommandExecutionResult] result of the command exection
90
+ def command(cmd)
91
+ AvoDeploy::Deployment.instance.log.info "Executing [" + cmd.yellow + "] on remote " + get(:name).to_s.cyan
92
+
93
+ result = AvoDeploy::CommandExecutionResult.new
94
+
95
+ begin
96
+ result = ssh_exec!(@session, cmd)
97
+
98
+ if result.stdout.nil? == false && result.stdout.empty? == false
99
+ AvoDeploy::Deployment.instance.log.debug "Stdout@#{get(:host)}: ".cyan + result.stdout.green
100
+ end
101
+
102
+ if result.stderr.nil? == false && result.stderr.empty? == false
103
+ AvoDeploy::Deployment.instance.log.debug "Stderr@#{get(:host)}: ".cyan + result.stderr.red
104
+ end
105
+ rescue Exception => e
106
+ handle_abort e
107
+ end
108
+
109
+ result
110
+ end
111
+
112
+ end
113
+ end
114
+ end