dkdeploy-core 8.0.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 +7 -0
- data/.gitignore +20 -0
- data/.rubocop.yml +18 -0
- data/Berksfile +3 -0
- data/Berksfile.lock +46 -0
- data/CONTRIBUTORS.md +16 -0
- data/Gemfile +4 -0
- data/LICENSE +7 -0
- data/README.md +88 -0
- data/Rakefile +5 -0
- data/Vagrantfile +60 -0
- data/config/vm/cookbooks/dkdeploy-core/metadata.rb +10 -0
- data/config/vm/cookbooks/dkdeploy-core/recipes/default.rb +56 -0
- data/dkdeploy-core.gemspec +34 -0
- data/features/apache.feature +35 -0
- data/features/assets.feature +100 -0
- data/features/bower.feature +52 -0
- data/features/current_folder.feature +17 -0
- data/features/db.feature +93 -0
- data/features/deploy.feature +48 -0
- data/features/enhanced_symlinks.feature +17 -0
- data/features/error_handlers.feature +59 -0
- data/features/file_access.feature +120 -0
- data/features/maintenance.feature +25 -0
- data/features/project_version.feature +42 -0
- data/features/support/env.rb +22 -0
- data/features/utils.feature +81 -0
- data/lib/capistrano/copy.rb +2 -0
- data/lib/capistrano/dkdeploy/core.rb +88 -0
- data/lib/dkdeploy/constants.rb +156 -0
- data/lib/dkdeploy/copy.rb +121 -0
- data/lib/dkdeploy/core/version.rb +15 -0
- data/lib/dkdeploy/dsl.rb +23 -0
- data/lib/dkdeploy/helpers/assets.rb +50 -0
- data/lib/dkdeploy/helpers/common.rb +31 -0
- data/lib/dkdeploy/helpers/db.rb +49 -0
- data/lib/dkdeploy/helpers/file_system.rb +76 -0
- data/lib/dkdeploy/i18n.rb +143 -0
- data/lib/dkdeploy/interaction_handler/password.rb +27 -0
- data/lib/dkdeploy/rollback_manager.rb +18 -0
- data/lib/dkdeploy/tasks/apache.rake +29 -0
- data/lib/dkdeploy/tasks/assets.rake +96 -0
- data/lib/dkdeploy/tasks/bower.rake +54 -0
- data/lib/dkdeploy/tasks/copy.rake +26 -0
- data/lib/dkdeploy/tasks/current_folder.rake +16 -0
- data/lib/dkdeploy/tasks/db.rake +412 -0
- data/lib/dkdeploy/tasks/deploy.rake +77 -0
- data/lib/dkdeploy/tasks/enhanced_symlinks.rake +74 -0
- data/lib/dkdeploy/tasks/fail.rake +8 -0
- data/lib/dkdeploy/tasks/file_access.rake +89 -0
- data/lib/dkdeploy/tasks/maintenance.rake +73 -0
- data/lib/dkdeploy/tasks/project_version.rake +32 -0
- data/lib/dkdeploy/tasks/utils.rake +141 -0
- data/lib/dkdeploy.rb +1 -0
- data/spec/fixtures/application/Capfile +11 -0
- data/spec/fixtures/application/Gemfile +11 -0
- data/spec/fixtures/application/Version +1 -0
- data/spec/fixtures/application/config/assets_exclude_file.txt +1 -0
- data/spec/fixtures/application/config/deploy/dev.rb +35 -0
- data/spec/fixtures/application/config/deploy.rb +18 -0
- data/spec/fixtures/application/config/etc/apache2/conf/.htaccess.erb +12 -0
- data/spec/fixtures/application/config/etc/apache2/conf/dev.htaccess.erb +3 -0
- data/spec/fixtures/application/config/preseed/default_content.sql.gz +0 -0
- data/spec/fixtures/application/config/preseed/default_structure.sql.gz +0 -0
- data/spec/fixtures/application/config/preseed/fileadmin.tar.gz +0 -0
- data/spec/fixtures/application/config/preseed/uploads.tar.gz +0 -0
- data/spec/fixtures/application/htdocs/.hidden/.gitkeep +0 -0
- data/spec/fixtures/application/htdocs/Gemfile +0 -0
- data/spec/fixtures/application/htdocs/bower.json +15 -0
- data/spec/fixtures/application/htdocs/catalog/.hidden/.gitkeep +0 -0
- data/spec/fixtures/application/htdocs/catalog/index.html +1 -0
- data/spec/fixtures/application/htdocs/index.html +1 -0
- data/spec/fixtures/application/htdocs/stylesheets/test1/config.rb +3 -0
- data/spec/fixtures/application/htdocs/stylesheets/test1/css/.gitkeep +0 -0
- data/spec/fixtures/application/htdocs/stylesheets/test1/src/source.scss +5 -0
- data/spec/fixtures/application/htdocs/stylesheets/test2/config.rb +3 -0
- data/spec/fixtures/application/htdocs/stylesheets/test2/css/.gitkeep +0 -0
- data/spec/fixtures/application/htdocs/stylesheets/test2/src/source.scss +5 -0
- data/spec/fixtures/application/temp/dkdeploy_core.sql.gz +0 -0
- data/spec/fixtures/capistrano/configuration/add_output_after_create_symlink.rb +7 -0
- data/spec/fixtures/capistrano/configuration/custom_compass_sources.rb +4 -0
- data/spec/fixtures/capistrano/configuration/custom_file_access.rb +13 -0
- data/spec/fixtures/capistrano/configuration/default_deployment_behaviour.rb +9 -0
- metadata +346 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'i18n'
|
|
2
|
+
require 'dkdeploy/i18n'
|
|
3
|
+
require 'dkdeploy/helpers/common'
|
|
4
|
+
require 'dkdeploy/helpers/assets'
|
|
5
|
+
require 'dkdeploy/interaction_handler/password'
|
|
6
|
+
require 'dkdeploy/constants'
|
|
7
|
+
|
|
8
|
+
include Capistrano::DSL
|
|
9
|
+
include SSHKit::DSL
|
|
10
|
+
include Dkdeploy::Helpers::Common
|
|
11
|
+
include Dkdeploy::Helpers::Assets
|
|
12
|
+
include Dkdeploy::Constants
|
|
13
|
+
|
|
14
|
+
namespace :assets do
|
|
15
|
+
desc 'Compiles sass files'
|
|
16
|
+
task :compile_compass, :compass_sources, :compass_compile_arguments do |_, args|
|
|
17
|
+
compass_sources = ask_array_variable(args, :compass_sources, 'questions.compass_sources')
|
|
18
|
+
compass_compile_arguments = ask_array_variable(args, :compass_compile_arguments, 'questions.compass_compile_arguments')
|
|
19
|
+
compass_sources.each do |path|
|
|
20
|
+
config_path = File.join path, 'config.rb'
|
|
21
|
+
run_locally do
|
|
22
|
+
# noinspection RubyArgCount
|
|
23
|
+
if test "[ -f #{config_path} ]"
|
|
24
|
+
execute :compass, 'compile', path, '--config', config_path, *compass_compile_arguments
|
|
25
|
+
else
|
|
26
|
+
error I18n.t('file.not_exists', file: config_path, scope: :dkdeploy)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
desc 'Add .htpasswd file to assets folder'
|
|
33
|
+
task :add_htpasswd, :username, :password do |_, args|
|
|
34
|
+
username = ask_variable(args, :username, 'questions.username') { |question| question.default = 'dkdeploy' }
|
|
35
|
+
password = ask_variable(args, :password, 'questions.password') { |question| question.echo = '*' }
|
|
36
|
+
htpasswd_path = File.join(shared_path, '.htpasswd')
|
|
37
|
+
|
|
38
|
+
if password.empty?
|
|
39
|
+
run_locally do
|
|
40
|
+
error I18n.t('errors.password_was_empty', scope: :dkdeploy)
|
|
41
|
+
exit 1
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
on release_roles :web do
|
|
46
|
+
info I18n.t('directory.create', scope: :dkdeploy)
|
|
47
|
+
execute :mkdir, '-p', shared_path
|
|
48
|
+
execute :htpasswd, '-c', htpasswd_path, username, interaction_handler: Dkdeploy::InteractionHandler::Password.new(password)
|
|
49
|
+
info I18n.t('tasks.assets.add_htpasswd.successfully_created', scope: :dkdeploy)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
desc 'remove contents of the shared assets folder on the server'
|
|
54
|
+
task :cleanup, :asset_folders do |_, args|
|
|
55
|
+
asset_folders = ask_array_variable(args, :asset_folders, 'questions.asset_folder')
|
|
56
|
+
|
|
57
|
+
on release_roles :web do
|
|
58
|
+
asset_folders.each do |asset_folder|
|
|
59
|
+
info I18n.t('tasks.assets.cleanup', folder: asset_folder, scope: :dkdeploy)
|
|
60
|
+
path = File.join assets_path, asset_folder
|
|
61
|
+
execute :rm, '-rf', path
|
|
62
|
+
execute :mkdir, '-p', path
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc 'Copy contents of the configured asset folders on the server to the local ./temp/assets directory'
|
|
68
|
+
task :download, :asset_folders do |_, args|
|
|
69
|
+
asset_folders = ask_array_variable(args, :asset_folders, 'questions.asset_folders')
|
|
70
|
+
|
|
71
|
+
asset_folders.each do |folder|
|
|
72
|
+
assets_download folder
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
desc 'Copy asset contents from the local ./temp/assets directory to the server'
|
|
77
|
+
task :update, :asset_folders do |_, args|
|
|
78
|
+
asset_folders = ask_array_variable(args, :asset_folders, 'questions.asset_folders')
|
|
79
|
+
|
|
80
|
+
asset_folders.each do |tar|
|
|
81
|
+
assets_upload tar
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
desc 'Add default content from ./config/preseed/'
|
|
86
|
+
task :add_default_content, :asset_default_content do |_, args|
|
|
87
|
+
asset_default_content = ask_array_variable(args, :asset_default_content, 'questions.asset_default_content')
|
|
88
|
+
|
|
89
|
+
config_path = File.join 'config', 'preseed'
|
|
90
|
+
on release_roles :web do
|
|
91
|
+
asset_default_content.each do |asset|
|
|
92
|
+
assets_upload asset, config_path
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'capistrano/i18n'
|
|
2
|
+
require 'dkdeploy/i18n'
|
|
3
|
+
|
|
4
|
+
include Capistrano::DSL
|
|
5
|
+
include SSHKit::DSL
|
|
6
|
+
|
|
7
|
+
namespace :bower do
|
|
8
|
+
desc 'Runs given Bower command in given path'
|
|
9
|
+
task :run, :bower_command, :bower_path do |_, args|
|
|
10
|
+
bower_command = ask_variable(args, :bower_command, 'questions.bower.command') { |question| question.default = 'help' }
|
|
11
|
+
bower_path = ask_variable(args, :bower_path, 'questions.bower.path') { |question| question.default = 'htdocs' }
|
|
12
|
+
|
|
13
|
+
run_locally do
|
|
14
|
+
if test("[ -d #{bower_path} ]")
|
|
15
|
+
bower_file_path = File.join(bower_path, 'bower.json')
|
|
16
|
+
if test("[ -f #{bower_file_path} ]")
|
|
17
|
+
within bower_path do
|
|
18
|
+
execute :bower, bower_command
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
warn I18n.t('tasks.bower.skipping_directory_with_missing_bower_file', bower_path: bower_path, scope: :dkdeploy)
|
|
22
|
+
next
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
warn I18n.t('tasks.bower.skipping_missing_directory', bower_path: bower_path, scope: :dkdeploy)
|
|
26
|
+
next
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
task :run_all, :bower_command, :bower_paths do |_, args|
|
|
32
|
+
bower_command = ask_variable(args, :bower_command, 'questions.bower.command') { |question| question.default = 'help' }
|
|
33
|
+
bower_paths = ask_array_variable(args, :bower_paths, 'questions.bower.paths')
|
|
34
|
+
|
|
35
|
+
run_locally do
|
|
36
|
+
bower_paths.each do |bower_path|
|
|
37
|
+
if test("[ -d #{bower_path} ]")
|
|
38
|
+
current_bower_file_path = File.join(bower_path, 'bower.json')
|
|
39
|
+
if test("[ -f #{current_bower_file_path} ]")
|
|
40
|
+
within bower_path do
|
|
41
|
+
execute :bower, bower_command
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
warn I18n.t('tasks.bower.skipping_directory_with_missing_bower_file', bower_path: bower_path, scope: :dkdeploy)
|
|
45
|
+
next
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
warn I18n.t('tasks.bower.skipping_missing_directory', bower_path: bower_path, scope: :dkdeploy)
|
|
49
|
+
next
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require_relative '../copy'
|
|
2
|
+
|
|
3
|
+
include Capistrano::DSL
|
|
4
|
+
|
|
5
|
+
namespace :copy do
|
|
6
|
+
# Getter for copy strategy
|
|
7
|
+
#
|
|
8
|
+
def strategy
|
|
9
|
+
@strategy ||= Dkdeploy::Copy.new(self, fetch(:copy_strategy, Dkdeploy::Copy::DefaultStrategy))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc 'Check if all configuration variables and copy sources exist'
|
|
13
|
+
task :check do
|
|
14
|
+
strategy.check
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc 'Upload the source repository to releases'
|
|
18
|
+
task :create_release do
|
|
19
|
+
strategy.release
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc 'Determine the revision that will be deployed'
|
|
23
|
+
task :set_current_revision do
|
|
24
|
+
set :current_revision, strategy.fetch_revision
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
include Capistrano::DSL
|
|
2
|
+
|
|
3
|
+
require 'dkdeploy/i18n'
|
|
4
|
+
|
|
5
|
+
namespace :current_folder do
|
|
6
|
+
desc "Delete current folder unless it's a symlink"
|
|
7
|
+
task :remove_unlesss_symlinked do
|
|
8
|
+
on release_roles :all do
|
|
9
|
+
if test "[[ -d #{current_path} && ! -L #{current_path} ]]"
|
|
10
|
+
execute :rm, '-rf', current_path
|
|
11
|
+
else
|
|
12
|
+
info I18n.t('info.ignoring_current_folder', scope: :dkdeploy)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
require 'dkdeploy/constants'
|
|
2
|
+
require 'dkdeploy/helpers/common'
|
|
3
|
+
require 'dkdeploy/helpers/db'
|
|
4
|
+
require 'dkdeploy/interaction_handler/password'
|
|
5
|
+
require 'digest/md5'
|
|
6
|
+
require 'yaml'
|
|
7
|
+
|
|
8
|
+
include Dkdeploy::Constants
|
|
9
|
+
include Dkdeploy::Helpers::Common
|
|
10
|
+
include Dkdeploy::Helpers::DB
|
|
11
|
+
include Capistrano::DSL
|
|
12
|
+
|
|
13
|
+
namespace :db do
|
|
14
|
+
task :read_db_settings do
|
|
15
|
+
FileUtils.mkdir_p 'temp'
|
|
16
|
+
on release_roles :app do
|
|
17
|
+
unless test("[ -f #{remote_database_config_path} ]")
|
|
18
|
+
error I18n.t('errors.database_config_file_missing', scope: :dkdeploy)
|
|
19
|
+
exit 1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
set :db_settings, read_db_settings_for_context(self)
|
|
23
|
+
set :db_host, fetch(:db_settings).fetch('host')
|
|
24
|
+
set :db_port, fetch(:db_settings).fetch('port')
|
|
25
|
+
set :db_name, fetch(:db_settings).fetch('name')
|
|
26
|
+
set :db_username, fetch(:db_settings).fetch('username')
|
|
27
|
+
set :db_password, fetch(:db_settings).fetch('password')
|
|
28
|
+
set :db_charset, fetch(:db_settings).fetch('charset')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
File.write local_database_config_path, db_settings_hash.to_yaml
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
desc 'Upload database settings file'
|
|
35
|
+
task :upload_settings, :db_host, :db_port, :db_name, :db_username, :db_password, :db_charset do |_, args|
|
|
36
|
+
set :db_host, ask_variable(args, :db_host, 'questions.database.host') { |question| question.default = '127.0.0.1' }
|
|
37
|
+
set :db_port, ask_variable(args, :db_port, 'questions.database.port') { |question| question.default = '3306' }
|
|
38
|
+
set :db_name, ask_variable(args, :db_name, 'questions.database.name') { |question| question.default = [fetch(:application), fetch(:stage)].join('_').tr('-', '_') }
|
|
39
|
+
set :db_username, ask_variable(args, :db_username, 'questions.database.username') { |question| question.default = 'root' }
|
|
40
|
+
set :db_password, ask_variable(args, :db_password, 'questions.database.password') { |question| question.echo = '*' }
|
|
41
|
+
set :db_charset, ask_variable(args, :db_charset, 'questions.database.charset') { |question| question.default = 'utf8' }
|
|
42
|
+
|
|
43
|
+
if fetch(:db_password).empty?
|
|
44
|
+
run_locally do
|
|
45
|
+
error I18n.t('errors.password_was_empty', scope: :dkdeploy)
|
|
46
|
+
exit 1
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
on release_roles :app do
|
|
51
|
+
begin
|
|
52
|
+
execute :mysql,
|
|
53
|
+
'-u', fetch(:db_username),
|
|
54
|
+
'-p', '-h', fetch(:db_host), '-P', fetch(:db_port), '-e', 'exit',
|
|
55
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(fetch(:db_password))
|
|
56
|
+
rescue SSHKit::Command::Failed
|
|
57
|
+
error I18n.t('errors.connection_failed', scope: :dkdeploy)
|
|
58
|
+
exit 1
|
|
59
|
+
end
|
|
60
|
+
execute :mkdir, '-p', File.join(shared_path, 'config')
|
|
61
|
+
execute :rm, '-f', remote_database_config_path
|
|
62
|
+
upload! StringIO.new(db_settings_hash.to_yaml), remote_database_config_path
|
|
63
|
+
info I18n.t('success.settings_uploaded', scope: :dkdeploy)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc 'Upload, unzip and execute database script'
|
|
68
|
+
task :update, :file_path, :zipped_db_file do |_, args|
|
|
69
|
+
file_path = ask_variable(args, :file_path, 'questions.path') { |question| question.default = 'temp' }
|
|
70
|
+
zipped_db_file = ask_variable(args, :zipped_db_file, 'questions.database.zipped_db_file') { |question| question.default = 'database.sql.gz' }
|
|
71
|
+
|
|
72
|
+
local_zipped_file_name = File.join(file_path, zipped_db_file)
|
|
73
|
+
remote_zipped_file_name = File.join(fetch(:deploy_to), zipped_db_file)
|
|
74
|
+
remote_file_name = File.join(fetch(:deploy_to), zipped_db_file.slice(0..-4)) # we assume file name ending .sql.gz
|
|
75
|
+
|
|
76
|
+
unless File.exist?(local_zipped_file_name)
|
|
77
|
+
run_locally do
|
|
78
|
+
error I18n.t('errors.file_not_found', scope: :dkdeploy)
|
|
79
|
+
exit 1
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
on primary :backend do
|
|
84
|
+
begin
|
|
85
|
+
db_settings = read_db_settings_for_context(self)
|
|
86
|
+
execute :rm, '-f', remote_zipped_file_name
|
|
87
|
+
execute :rm, '-f', remote_file_name
|
|
88
|
+
upload! local_zipped_file_name, remote_zipped_file_name, via: :scp
|
|
89
|
+
execute :gunzip, remote_zipped_file_name
|
|
90
|
+
execute :mysql,
|
|
91
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
92
|
+
'-u', db_settings.fetch('username'),
|
|
93
|
+
'-p',
|
|
94
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), db_settings.fetch('name'),
|
|
95
|
+
'-e', "'source #{remote_file_name}'",
|
|
96
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
97
|
+
ensure
|
|
98
|
+
execute :rm, '-f', remote_zipped_file_name
|
|
99
|
+
execute :rm, '-f', remote_file_name
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
desc 'Dump complete database without cache table content to local temp folder'
|
|
105
|
+
task download: [:download_structure, :download_content]
|
|
106
|
+
|
|
107
|
+
desc 'Dumps complete database structure without content'
|
|
108
|
+
task :download_structure do
|
|
109
|
+
FileUtils.mkdir_p 'temp'
|
|
110
|
+
|
|
111
|
+
dump_file = db_dump_file_structure
|
|
112
|
+
remote_dump_file = File.join(fetch(:deploy_to), dump_file)
|
|
113
|
+
remote_zipped_dump_file = "#{remote_dump_file}.gz"
|
|
114
|
+
|
|
115
|
+
on primary :backend do
|
|
116
|
+
begin
|
|
117
|
+
db_settings = read_db_settings_for_context(self)
|
|
118
|
+
execute :rm, '-f', remote_dump_file
|
|
119
|
+
execute :rm, '-f', remote_zipped_dump_file
|
|
120
|
+
execute :mysqldump,
|
|
121
|
+
'--no-data', '--skip-set-charset',
|
|
122
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
123
|
+
'-u', db_settings.fetch('username'),
|
|
124
|
+
'-p',
|
|
125
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), db_settings.fetch('name'),
|
|
126
|
+
'>', remote_dump_file,
|
|
127
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
128
|
+
execute :gzip, remote_dump_file
|
|
129
|
+
download! remote_zipped_dump_file, 'temp', via: :scp
|
|
130
|
+
ensure
|
|
131
|
+
execute :rm, '-f', remote_dump_file
|
|
132
|
+
execute :rm, '-f', remote_zipped_dump_file
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
desc 'Dump complete database content without cache tables and structure to local temp folder'
|
|
138
|
+
task :download_content do
|
|
139
|
+
FileUtils.mkdir_p 'temp'
|
|
140
|
+
|
|
141
|
+
dump_file = db_dump_file_content
|
|
142
|
+
remote_dump_file = File.join(fetch(:deploy_to), dump_file)
|
|
143
|
+
remote_zipped_dump_file = "#{remote_dump_file}.gz"
|
|
144
|
+
|
|
145
|
+
on primary :backend do
|
|
146
|
+
begin
|
|
147
|
+
db_settings = read_db_settings_for_context(self)
|
|
148
|
+
execute :rm, '-f', remote_dump_file
|
|
149
|
+
execute :rm, '-f', remote_zipped_dump_file
|
|
150
|
+
|
|
151
|
+
ignore_tables_command_line = ignore_tables.inject('') do |command_line, table|
|
|
152
|
+
command_line << " --ignore-table=#{db_settings.fetch('name')}.#{table}"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
execute :mysqldump,
|
|
156
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
157
|
+
'--skip-set-charset',
|
|
158
|
+
'-u', db_settings.fetch('username'),
|
|
159
|
+
'-p',
|
|
160
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), ignore_tables_command_line, db_settings.fetch('name'),
|
|
161
|
+
'>', remote_dump_file,
|
|
162
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
163
|
+
execute :gzip, remote_dump_file
|
|
164
|
+
download! remote_zipped_dump_file, 'temp', via: :scp
|
|
165
|
+
ensure
|
|
166
|
+
execute :rm, '-f', remote_dump_file
|
|
167
|
+
execute :rm, '-f', remote_zipped_dump_file
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
desc 'Dump content of a database table to local temp folder'
|
|
173
|
+
task :dump_table, :table_name do |_, args|
|
|
174
|
+
table_name = ask_variable(args, :table_name, 'questions.database.table_name')
|
|
175
|
+
|
|
176
|
+
FileUtils.mkdir_p 'temp'
|
|
177
|
+
|
|
178
|
+
dump_file = db_dump_file table_name
|
|
179
|
+
zipped_dump_file = File.join('temp', "#{dump_file}.gz")
|
|
180
|
+
remote_dump_file = File.join(deploy_to, dump_file)
|
|
181
|
+
remote_zipped_dump_file = "#{remote_dump_file}.gz"
|
|
182
|
+
|
|
183
|
+
on primary :backend do
|
|
184
|
+
begin
|
|
185
|
+
db_settings = read_db_settings_for_context(self)
|
|
186
|
+
execute :rm, '-f', remote_dump_file
|
|
187
|
+
execute :rm, '-f', remote_zipped_dump_file
|
|
188
|
+
execute :mysqldump,
|
|
189
|
+
'--no-data', '--skip-set-charset',
|
|
190
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
191
|
+
'-u', db_settings.fetch('username'),
|
|
192
|
+
'-p',
|
|
193
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), db_settings.fetch('name'), table_name,
|
|
194
|
+
'>', remote_dump_file,
|
|
195
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
196
|
+
execute :gzip, remote_dump_file
|
|
197
|
+
download! remote_zipped_dump_file, zipped_dump_file, via: :scp
|
|
198
|
+
ensure
|
|
199
|
+
execute :rm, '-f', remote_dump_file
|
|
200
|
+
execute :rm, '-f', remote_zipped_dump_file
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
desc 'Dump content of a list of database tables to a local folder'
|
|
206
|
+
task :dump_tables, :table_names, :file_path, :file_name do |_, args|
|
|
207
|
+
table_names = ask_array_variable(args, :table_names, 'questions.database.table_names')
|
|
208
|
+
file_path = ask_variable(args, :file_path, 'questions.path') { |question| question.default = 'temp' }
|
|
209
|
+
file_name = ask_variable(args, :file_name, 'questions.file_name') { |question| question.default = [fetch(:application), fetch(:stage), table_names].join('_') }
|
|
210
|
+
|
|
211
|
+
local_file_name = File.join(file_path, file_name)
|
|
212
|
+
local_zipped_file = "#{local_file_name}.gz"
|
|
213
|
+
remote_file_name = File.join(fetch(:deploy_to), file_name)
|
|
214
|
+
remote_zipped_file = "#{remote_file_name}.gz"
|
|
215
|
+
|
|
216
|
+
FileUtils.mkdir_p file_path
|
|
217
|
+
|
|
218
|
+
on primary :backend do
|
|
219
|
+
begin
|
|
220
|
+
db_settings = read_db_settings_for_context(self)
|
|
221
|
+
execute :rm, '-f', remote_file_name
|
|
222
|
+
execute :rm, '-f', remote_zipped_file
|
|
223
|
+
execute :mysqldump,
|
|
224
|
+
'--no-data', '--skip-set-charset',
|
|
225
|
+
'--no-create-info', '--skip-comments',
|
|
226
|
+
'--skip-extended-insert', '--skip-set-charset',
|
|
227
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
228
|
+
'-u', db_settings.fetch('username'),
|
|
229
|
+
'-p',
|
|
230
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'),
|
|
231
|
+
db_settings.fetch('name'), table_names.join(' '),
|
|
232
|
+
'>', remote_file_name,
|
|
233
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
234
|
+
execute :gzip, remote_file_name
|
|
235
|
+
download! remote_zipped_file, local_zipped_file, via: :scp
|
|
236
|
+
ensure
|
|
237
|
+
execute :rm, '-f', remote_file_name
|
|
238
|
+
execute :rm, '-f', remote_zipped_file
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
run_locally do
|
|
243
|
+
execute :gunzip, local_zipped_file
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
desc 'Add default content from config/preseed/default_content.sql.gz to database'
|
|
248
|
+
task :add_default_content do
|
|
249
|
+
local_zipped_default_content_file = File.join('config', 'preseed', 'default_content.sql.gz')
|
|
250
|
+
remote_default_content_file = File.join(fetch(:deploy_to), 'default_content.sql')
|
|
251
|
+
remote_zipped_default_content_file = "#{remote_default_content_file}.gz"
|
|
252
|
+
|
|
253
|
+
on primary :backend do
|
|
254
|
+
begin
|
|
255
|
+
db_settings = read_db_settings_for_context(self)
|
|
256
|
+
execute :rm, '-f', remote_default_content_file
|
|
257
|
+
execute :rm, '-f', remote_zipped_default_content_file
|
|
258
|
+
upload! local_zipped_default_content_file, remote_zipped_default_content_file, via: :scp
|
|
259
|
+
execute :gunzip, remote_zipped_default_content_file
|
|
260
|
+
execute :mysql,
|
|
261
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
262
|
+
'-u', db_settings.fetch('username'),
|
|
263
|
+
'-p',
|
|
264
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), db_settings.fetch('name'),
|
|
265
|
+
'-e', "'source #{remote_default_content_file}'",
|
|
266
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
267
|
+
ensure
|
|
268
|
+
execute :rm, '-f', remote_default_content_file
|
|
269
|
+
execute :rm, '-f', remote_zipped_default_content_file
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
desc 'Add structure content from config/preseed/default_structure.sql.gz to database'
|
|
275
|
+
task :add_default_structure do
|
|
276
|
+
local_zipped_default_structure_file = File.join('config', 'preseed', 'default_structure.sql.gz')
|
|
277
|
+
remote_default_structure_file = File.join(fetch(:deploy_to), 'default_structure.sql')
|
|
278
|
+
remote_zipped_default_structure_file = "#{remote_default_structure_file}.gz"
|
|
279
|
+
|
|
280
|
+
on primary :backend do
|
|
281
|
+
begin
|
|
282
|
+
db_settings = read_db_settings_for_context(self)
|
|
283
|
+
execute :rm, '-f', remote_default_structure_file
|
|
284
|
+
execute :rm, '-f', remote_zipped_default_structure_file
|
|
285
|
+
upload! local_zipped_default_structure_file, remote_zipped_default_structure_file, via: :scp
|
|
286
|
+
execute :gunzip, remote_zipped_default_structure_file
|
|
287
|
+
execute :mysql,
|
|
288
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
289
|
+
'-u', db_settings.fetch('username'), '-p',
|
|
290
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), db_settings.fetch('name'),
|
|
291
|
+
'-e', "'source #{remote_default_structure_file}'",
|
|
292
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
293
|
+
ensure
|
|
294
|
+
execute :rm, '-f', remote_default_structure_file
|
|
295
|
+
execute :rm, '-f', remote_zipped_default_structure_file
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
desc 'Download database tables'
|
|
301
|
+
task :download_tables, :table_names, :file_path, :file_name do |_, args|
|
|
302
|
+
table_names = ask_array_variable(args, :table_names, 'questions.database.table_names')
|
|
303
|
+
file_path = ask_variable(args, :file_path, 'questions.path') { |question| question.default = 'temp' }
|
|
304
|
+
file_name = ask_variable(args, :file_name, 'questions.file_name') { |question| question.default = [fetch(:application), fetch(:stage), table_names].join('_') }
|
|
305
|
+
table_names = table_names.join(' ')
|
|
306
|
+
|
|
307
|
+
FileUtils.mkdir_p file_path
|
|
308
|
+
|
|
309
|
+
remote_file_name = File.join(fetch(:deploy_to), file_name)
|
|
310
|
+
remote_zipped_file = "#{remote_file_name}.gz"
|
|
311
|
+
local_file_name = File.join(file_path, file_name)
|
|
312
|
+
local_zipped_file = "#{local_file_name}.gz"
|
|
313
|
+
|
|
314
|
+
on primary :backend do
|
|
315
|
+
begin
|
|
316
|
+
db_settings = read_db_settings_for_context(self)
|
|
317
|
+
execute :rm, '-f', remote_file_name
|
|
318
|
+
execute :rm, '-f', remote_zipped_file
|
|
319
|
+
execute :mysqldump,
|
|
320
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
321
|
+
'--no-create-info', '--skip-comments',
|
|
322
|
+
'--skip-extended-insert', '--skip-set-charset',
|
|
323
|
+
'--complete-insert',
|
|
324
|
+
'-u', db_settings.fetch('username'),
|
|
325
|
+
'-p',
|
|
326
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'),
|
|
327
|
+
db_settings.fetch('name'), table_names,
|
|
328
|
+
'>', remote_file_name,
|
|
329
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
330
|
+
execute :gzip, remote_file_name
|
|
331
|
+
download! remote_zipped_file, local_zipped_file, via: :scp
|
|
332
|
+
ensure
|
|
333
|
+
execute :rm, '-f', remote_file_name
|
|
334
|
+
execute :rm, '-f', remote_zipped_file
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
run_locally do
|
|
339
|
+
execute :rm, '-f', local_file_name # Delete local file, before unzip
|
|
340
|
+
execute :gunzip, local_zipped_file
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
sql = File.read(local_file_name)
|
|
344
|
+
File.open(local_file_name, 'w') do |io|
|
|
345
|
+
table_names.split(' ').each do |table|
|
|
346
|
+
io.write("TRUNCATE TABLE #{table};\n")
|
|
347
|
+
end
|
|
348
|
+
io.write(sql)
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
desc 'Update database tables'
|
|
353
|
+
task :upload_tables, :file_path, :file_name do |task, args|
|
|
354
|
+
file_path = ask_variable(args, :file_path, 'questions.path') { |question| question.default = 'temp' }
|
|
355
|
+
file_name = ask_variable(args, :file_name, 'questions.file_name') { |question| question.default = [fetch(:application), fetch(:stage)].join('_') }
|
|
356
|
+
|
|
357
|
+
sql_dump_file = File.join(file_path, file_name)
|
|
358
|
+
remote_db_path = File.join(shared_path, '/db')
|
|
359
|
+
remote_dump_file = File.join(remote_db_path, file_name)
|
|
360
|
+
remote_dump_md5_file = File.join("#{remote_dump_file}.md5")
|
|
361
|
+
local_md5 = Digest::MD5.file(sql_dump_file).hexdigest
|
|
362
|
+
|
|
363
|
+
on primary :backend do
|
|
364
|
+
execute :mkdir, '-p', remote_db_path
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
run_locally do
|
|
368
|
+
info I18n.t('info.local_md5', md5_hash: local_md5, scope: :dkdeploy)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
remote_md5 = '' # to allow assignment in block and later comparison
|
|
372
|
+
on primary :backend do
|
|
373
|
+
if test("[ -f #{remote_dump_md5_file} ]")
|
|
374
|
+
remote_md5 = capture("cat #{remote_dump_md5_file}")
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
run_locally do
|
|
379
|
+
info I18n.t('info.remote_md5', md5_hash: remote_md5, scope: :dkdeploy)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
if local_md5 == remote_md5
|
|
383
|
+
run_locally do
|
|
384
|
+
info I18n.t('info.md5_match', scope: :dkdeploy)
|
|
385
|
+
end
|
|
386
|
+
next
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
begin
|
|
390
|
+
on primary :backend do
|
|
391
|
+
db_settings = read_db_settings_for_context(self)
|
|
392
|
+
upload! StringIO.new(local_md5), remote_dump_md5_file
|
|
393
|
+
upload! sql_dump_file, remote_dump_file
|
|
394
|
+
execute :mysql,
|
|
395
|
+
"--default-character-set=#{db_settings.fetch('charset')}",
|
|
396
|
+
'-u', db_settings.fetch('username'),
|
|
397
|
+
'-p',
|
|
398
|
+
'-h', db_settings.fetch('host'), '-P', db_settings.fetch('port'), db_settings.fetch('name'),
|
|
399
|
+
'-e', "'source #{remote_dump_file}'",
|
|
400
|
+
interaction_handler: Dkdeploy::InteractionHandler::Password.new(db_settings.fetch('password'))
|
|
401
|
+
end
|
|
402
|
+
rescue SSHKit::Command::Failed => exception
|
|
403
|
+
run_locally do
|
|
404
|
+
error "Removing #{remote_dump_file} and #{remote_dump_md5_file}"
|
|
405
|
+
execute :rm, '-f', remote_dump_md5_file
|
|
406
|
+
execute :rm, '-f', remote_dump_file
|
|
407
|
+
end
|
|
408
|
+
task.reenable
|
|
409
|
+
raise "upload_tables failed: #{exception.message}"
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
end
|