avodeploy 0.4 → 0.4.1

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.
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