deployinator 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/deployinator.rb CHANGED
@@ -5,3 +5,4 @@ load 'deployinator/deploy.rb'
5
5
  load 'deployinator/check.rb'
6
6
  load 'deployinator/config.rb'
7
7
  load 'deployinator/helpers.rb'
8
+ load 'deployinator/built-in.rb'
@@ -0,0 +1,186 @@
1
+ set :deploy_log_level, "debug"
2
+ set :webserver_socket_path, -> { shared_path.join('run') }
3
+ set :deploy_templates_path, "templates/deploy"
4
+
5
+ # Default deploy_to directory is /var/www/my_app
6
+ # set :deploy_to, '/var/www/my_app'
7
+
8
+ # Default value for :log_level is :debug
9
+ # set :log_level, :debug
10
+
11
+ # Default value for :linked_files is []
12
+ # set :linked_files, %w{config/database.yml}
13
+
14
+ # Default value for linked_dirs is []
15
+ # set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
16
+
17
+ # Default value for default_env is {}
18
+ # set :default_env, { path: "/opt/ruby/bin:$PATH" }
19
+
20
+ # Default value for keep_releases is 5
21
+ # set :keep_releases, 5
22
+
23
+ #set :bundle_roles, :all # this is default
24
+ #set :bundle_servers, -> { release_roles(fetch(:bundle_roles)) } # this is default
25
+ #set :bundle_binstubs, -> { shared_path.join('bin') } # this is default
26
+ #set :bundle_binstubs, -> { shared_path.join('bundle', 'bin') } # this will be overwritten by deployinator
27
+ #set :bundle_gemfile, -> { release_path.join('Gemfile') } # this will be overwritten by deployinator
28
+ #set :bundle_path, -> { shared_path.join('bundle') } # this is default
29
+ #set :bundle_without, %w{development test}.join(' ') # this is default
30
+ #set :bundle_flags, '--deployment --quiet' # this is default
31
+ #set :bundle_flags, '--deployment'
32
+ #set :bundle_env_variables, {} # this is default
33
+ set :migration_role, :db # Defaults to 'db'
34
+ #set :conditionally_migrate, true # Defaults to false. If true, it's skip migration if files in db/migrate not modified
35
+ set :assets_roles, [:app] # Defaults to [:web]
36
+ #set :assets_prefix, 'prepackaged-assets' # Defaults to 'assets' this should match config.assets.prefix in your rails config/application.rb
37
+
38
+ # TODO: fix from_local, right now you have to copy-paste the set_scm method to your deploy.rb
39
+ # Use `cap <stage> deploy from_local=true` to deploy your locally changed code
40
+ # instead of the code in the git repo. You can also add --trace.
41
+ # You can set include_dir and exclude_dir settings (from capistrano-scm-copy gem).
42
+ # These will only apply when using the from_local=true option
43
+ # set :include_dir, '../.*'
44
+ # set :exclude_dir, ["../.$", "../..", '.././infrastructure']
45
+ def set_scm
46
+ if ENV['from_local']
47
+ if "#{fetch(:stage)}" == "production"
48
+ run_locally do
49
+ fatal("You are trying to deploy to production using from_local, " +
50
+ "this should pretty much never be done.")
51
+ end
52
+ ask :yes_no, "Are you positive you want to continue?"
53
+ case fetch(:yes_no).chomp.downcase
54
+ when "yes"
55
+ when "no"
56
+ exit
57
+ else
58
+ warn "Please enter 'yes' or 'no'"
59
+ set_scm
60
+ end
61
+ end
62
+ set :scm, :copy
63
+ else
64
+ set :scm, :git
65
+ end
66
+ end
67
+ set_scm
68
+
69
+ def deploy_run_bluepill(host)
70
+ execute(
71
+ "docker", "run", "--tty", "--detach",
72
+ "--name", fetch(:ruby_container_name),
73
+ "-e", "GEM_HOME=#{shared_path.join('bundle')}",
74
+ "-e", "GEM_PATH=#{shared_path.join('bundle')}",
75
+ "-e", "BUNDLE_GEMFILE=#{current_path.join('Gemfile')}",
76
+ "-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
77
+ "--restart", "always", "--memory", "#{fetch(:ruby_container_max_mem_mb)}m",
78
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
79
+ "--entrypoint", shared_path.join('bundle', 'bin', 'bluepill'),
80
+ fetch(:ruby_image_name), "load",
81
+ current_path.join('config', 'bluepill.rb')
82
+ )
83
+ end
84
+ def deploy_run_cadvisor(host)
85
+ execute(
86
+ "docker", "run", "--detach",
87
+ "--name", "cadvisor",
88
+ "--volume", "/:/rootfs:ro",
89
+ "--volume", "/var/run:/var/run:rw",
90
+ "--volume", "/sys:/sys:ro",
91
+ "--volume", "/var/lib/docker/:/var/lib/docker:ro",
92
+ "--publish", "127.0.0.1:8080:8080",
93
+ "--restart", "always",
94
+ "google/cadvisor:latest"
95
+ )
96
+ end
97
+ def deploy_rails_console(host)
98
+ [
99
+ "ssh", "-t", "#{host}", "\"docker", "exec", "--interactive", "--tty",
100
+ fetch(:ruby_container_name),
101
+ "bash", "-c", "'cd", current_path, "&&",
102
+ shared_path.join('bundle', 'bin', 'rails'),
103
+ "console", "#{fetch(:rails_env)}'\""
104
+ ].join(' ')
105
+ end
106
+ def deploy_rails_console_print(host)
107
+ [
108
+ "docker", "exec", "--interactive", "--tty",
109
+ fetch(:ruby_container_name),
110
+ "bash", "-c", "\"cd", current_path, "&&",
111
+ shared_path.join('bundle', 'bin', 'rails'),
112
+ "console", "#{fetch(:rails_env)}\""
113
+ ].join(' ')
114
+ end
115
+ def sshkit_bundle_command_map
116
+ [
117
+ "/usr/bin/env docker run --rm --tty",
118
+ "--user", fetch(:deployment_username),
119
+ "-e", "GEM_HOME=#{shared_path.join('bundle')}",
120
+ "-e", "GEM_PATH=#{shared_path.join('bundle')}",
121
+ "-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
122
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
123
+ "--volume", "$SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent",
124
+ "--volume", "/home:/home:rw",
125
+ "--volume", "/etc/passwd:/etc/passwd:ro",
126
+ "--volume", "/etc/group:/etc/group:ro",
127
+ "--entrypoint", "#{shared_path.join('bundle', 'bin', 'bundle')}",
128
+ fetch(:ruby_image_name)
129
+ ].join(' ')
130
+ end
131
+ def deploy_assets_precompile(host)
132
+ execute("docker", "run", "--rm", "--tty", "--user", fetch(:webserver_username),
133
+ "-w", release_path,
134
+ "--volume", "/home:/home:rw",
135
+ "--volume", "/etc/passwd:/etc/passwd:ro",
136
+ "--volume", "/etc/group:/etc/group:ro",
137
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
138
+ "--entrypoint", "/bin/bash",
139
+ fetch(:ruby_image_name), "-c",
140
+ "\"umask", "0007", "&&", "#{shared_path.join('bundle', 'bin', 'rake')}",
141
+ "assets:precompile\"")
142
+ end
143
+ def deploy_assets_cleanup(host)
144
+ execute("docker", "run", "--rm", "--tty",
145
+ "-e", "RAILS_ENV=#{fetch(:rails_env)}",
146
+ "-w", release_path,
147
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
148
+ "--entrypoint", shared_path.join('bundle', 'bin', 'bundle'),
149
+ fetch(:ruby_image_name), "exec", "rake", "assets:clean")
150
+ end
151
+ def deploy_rake_db_migrate(host)
152
+ execute("docker", "run", "--rm", "--tty",
153
+ "-w", release_path,
154
+ "-e", "RAILS_ENV=#{fetch(:rails_env)}",
155
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
156
+ "--entrypoint", shared_path.join('bundle', 'bin', 'rake'),
157
+ fetch(:ruby_image_name), "db:migrate")
158
+ end
159
+ def deploy_install_bundler(host)
160
+ execute("docker", "run", "--rm", "--tty", "--user", fetch(:deployment_username),
161
+ "-e", "GEM_HOME=#{shared_path.join('bundle')}",
162
+ "-e", "GEM_PATH=#{shared_path.join('bundle')}",
163
+ "-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
164
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
165
+ "--volume", "/home:/home:rw",
166
+ "--volume", "/etc/passwd:/etc/passwd:ro",
167
+ "--volume", "/etc/group:/etc/group:ro",
168
+ "--entrypoint", "/bin/bash",
169
+ fetch(:ruby_image_name), "-c",
170
+ "\"umask", "0007", "&&" "/usr/local/bin/gem", "install",
171
+ "--install-dir", "#{shared_path.join('bundle')}",
172
+ "--bindir", shared_path.join('bundle', 'bin'),
173
+ "--no-ri", "--no-rdoc", "--quiet", "bundler", "-v'#{fetch(:bundler_version)}'\"")
174
+ end
175
+ def deploy_bluepill_restart(host)
176
+ execute("docker", "exec", "--tty",
177
+ fetch(:ruby_container_name),
178
+ shared_path.join('bundle', 'bin', 'bluepill'),
179
+ fetch(:application), "restart")
180
+ end
181
+ def deploy_bluepill_stop(host)
182
+ execute("docker", "exec", "--tty",
183
+ fetch(:ruby_container_name),
184
+ shared_path.join('bundle', 'bin', 'bluepill'),
185
+ fetch(:application), "stop")
186
+ end
@@ -4,20 +4,7 @@ namespace :deploy do
4
4
  task :bundle_command_map => ['deployinator:deployment_user'] do
5
5
  set :bundle_binstubs, -> { shared_path.join('bundle', 'bin') }
6
6
  set :bundle_gemfile, -> { release_path.join('Gemfile') }
7
- SSHKit.config.command_map[:bundle] = [
8
- "/usr/bin/env docker run --rm --tty",
9
- "--user", fetch(:deployment_user_id),
10
- "-e", "GEM_HOME=#{shared_path.join('bundle')}",
11
- "-e", "GEM_PATH=#{shared_path.join('bundle')}",
12
- "-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
13
- "--entrypoint", "#{shared_path.join('bundle', 'bin', 'bundle')}",
14
- "--volume $SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent",
15
- "--volume #{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
16
- "--volume /etc/passwd:/etc/passwd:ro",
17
- "--volume /etc/group:/etc/group:ro",
18
- "--volume /home:/home:rw",
19
- fetch(:ruby_image_name)
20
- ].join(' ')
7
+ SSHKit.config.command_map[:bundle] = sshkit_bundle_command_map
21
8
  end
22
9
  before 'bundler:install', 'deploy:check:bundle_command_map'
23
10
 
@@ -26,6 +13,14 @@ namespace :deploy do
26
13
  SSHKit.config.command_map[:rm] = "/usr/bin/env sudo rm"
27
14
  end
28
15
 
16
+ before 'deploy:check', :brakeman_reminder do
17
+ run_locally do
18
+ warn "Remember to run brakeman before deploying!"
19
+ ask :return_to_continue, nil
20
+ set :nothing, fetch(:return_to_continue)
21
+ end
22
+ end
23
+
29
24
  if Rake::Task.task_defined?("deploy:cleanup")
30
25
  # Append dependancy to existing cleanup task
31
26
  task 'deploy:cleanup' => 'deploy:check:rm_command_map'
@@ -45,13 +40,13 @@ namespace :deploy do
45
40
  # TODO make this better
46
41
  before 'deploy:check', :templates do
47
42
  run_locally do
48
- keys_template = File.expand_path("./templates/deploy/deployment_authorized_keys.erb")
49
- bluepill_template = File.expand_path("./templates/deploy/bluepill.rb.erb")
50
- unicorn_template = File.expand_path("./templates/deploy/unicorn.rb.erb")
43
+ keys_template = File.expand_path("./#{fetch(:deploy_templates_path)}/deployment_authorized_keys.erb")
44
+ bluepill_template = File.expand_path("./#{fetch(:deploy_templates_path)}/bluepill.rb.erb")
45
+ unicorn_template = File.expand_path("./#{fetch(:deploy_templates_path)}/unicorn.rb.erb")
51
46
  {
52
- "You need a templates/deploy/deployment_authorized_keys.erb file." => keys_template,
53
- "You need a templates/deploy/bluepill.rb.erb file." => bluepill_template,
54
- "You need a templates/deploy/unicorn.rb.erb file." => unicorn_template,
47
+ "You need a #{fetch(:deploy_templates_path)}/deployment_authorized_keys.erb file." => keys_template,
48
+ "You need a #{fetch(:deploy_templates_path)}/bluepill.rb.erb file." => bluepill_template,
49
+ "You need a #{fetch(:deploy_templates_path)}/unicorn.rb.erb file." => unicorn_template,
55
50
  }.each do |message, file|
56
51
  fatal(message) and raise unless File.exists? file
57
52
  end
@@ -64,9 +59,9 @@ namespace :deploy do
64
59
  task :root_dir_permissions => ['deployinator:deployment_user', 'deployinator:webserver_user'] do
65
60
  on roles(:app) do
66
61
  as :root do
67
- [fetch(:deploy_to), Pathname.new(fetch(:deploy_to)).join("../")].each do |dir|
62
+ [fetch(:deploy_to), Pathname.new(fetch(:deploy_to)).join("../"), shared_path].each do |dir|
68
63
  if directory_exists?(dir)
69
- execute "chown", "#{fetch(:deployment_user_id)}:#{fetch(:webserver_user_id)}", dir
64
+ execute "chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}", dir
70
65
  execute "chmod", "2750", dir
71
66
  end
72
67
  end
@@ -75,53 +70,29 @@ namespace :deploy do
75
70
  end
76
71
  before 'deploy:check:directories', 'deploy:check:root_dir_permissions'
77
72
 
78
- before 'deploy:check', :webserver_running do
79
- on roles(:app) do
80
- if container_exists?(fetch(:webserver_container_name))
81
- unless container_is_running?(fetch(:webserver_container_name))
82
- warn "The webserver container named #{fetch(:webserver_container_name)} exists but is not running. You can still deploy your code, but you need this, start it, or re-run setup with something like nginxinator."
83
- ask :return_to_continue, nil
84
- set :nothing, fetch(:return_to_continue)
85
- end
86
- else
87
- warn "No webserver container named #{fetch(:webserver_container_name)} exists! You can still deploy your code, but you need this, set it up with something like nginxinator."
88
- ask :return_to_continue, nil
89
- set :nothing, fetch(:return_to_continue)
90
- end
91
- end
92
- end
93
-
94
73
  before 'deploy:check', :postgres_running do
95
- on primary fetch(:migration_role) do
96
- if container_exists?(fetch(:postgres_container_name))
97
- if container_is_running?(fetch(:postgres_container_name))
98
- unless localhost_port_responding?(fetch(:postgres_port))
99
- fatal "Port #{fetch(:postgres_port)} is not responding, we won't be able to db:migrate!"
100
- raise
101
- end
102
- else
103
- fatal "#{fetch(:postgres_container_name)} exists but is not running, we won't be able to db:migrate!"
104
- raise
105
- end
106
- else
107
- fatal "#{fetch(:postgres_container_name)} does not exist, we won't be able to db:migrate!"
74
+ on roles(:app) do
75
+ unless localhost_port_responding?(fetch(:postgres_port))
76
+ fatal "Port #{fetch(:postgres_port)} is not responding, we won't be able to db:migrate!"
108
77
  raise
109
78
  end
110
79
  end
111
80
  end
112
81
 
113
82
  before 'deploy:check', :ensure_cadvisor do
114
- on roles(:app), in: :sequence, wait: 5 do
83
+ on roles(:app) do |host|
115
84
  if fetch(:use_cadvisor, true)
116
85
  if container_exists?("cadvisor")
117
86
  if container_is_running?("cadvisor")
118
87
  info "cadvisor is already running."
119
88
  else
120
- info "Restarting existing cadvisor container."
121
- execute "docker", "start", "cadvisor"
89
+ info "Starting existing cadvisor container."
90
+ start_container("cadvisor")
122
91
  end
123
92
  else
124
- execute("docker", "run", fetch(:docker_run_cadvisor_command))
93
+ warn "Starting a new container named 'cadvisor' on #{host}"
94
+ deploy_run_cadvisor(host)
95
+ check_stayed_running("cadvisor")
125
96
  end
126
97
  else
127
98
  info "Not using cadvisor."
@@ -1,24 +1,109 @@
1
+ module Capistrano
2
+ module TaskEnhancements
3
+ alias_method :deploy_original_default_tasks, :default_tasks
4
+ def default_tasks
5
+ deploy_original_default_tasks + [
6
+ "deployinator:write_built_in",
7
+ "deployinator:write_example_configs",
8
+ "deployinator:write_example_configs:in_place"
9
+ ]
10
+ end
11
+ end
12
+ end
13
+
1
14
  namespace :deployinator do
2
15
 
16
+ set :example, "_example"
17
+
3
18
  desc 'Write example config files'
4
19
  task :write_example_configs do
5
20
  run_locally do
6
- execute "mkdir", "-p", "config/deploy", "templates/deploy"
21
+ execute "mkdir", "-p", "config/deploy", fetch(:deploy_templates_path, 'templates/deploy')
7
22
  {
8
- "examples/Capfile" => "Capfile_example",
9
- "examples/config/deploy.rb" => "config/deploy_example.rb",
10
- "examples/config/deploy/staging.rb" => "config/deploy/staging_example.rb",
11
- "examples/Dockerfile" => "templates/deploy/Dockerfile_example",
12
- "examples/deployment_authorized_keys.erb" => "templates/deploy/deployment_authorized_keys_example.erb",
13
- "examples/unicorn.rb.erb" => "templates/deploy/unicorn_example.rb.erb",
14
- "examples/bluepill.rb.erb" => "templates/deploy/bluepill_example.rb.erb"
23
+ "examples/Capfile" => "Capfile#{fetch(:example)}",
24
+ "examples/config/deploy.rb" => "config/deploy#{fetch(:example)}.rb",
25
+ "examples/config/deploy/staging.rb" => "config/deploy/staging#{fetch(:example)}.rb",
26
+ "examples/Dockerfile" => "#{fetch(:deploy_templates_path, 'templates/deploy')}/Dockerfile#{fetch(:example)}",
27
+ "examples/deployment_authorized_keys.erb" => "#{fetch(:deploy_templates_path, 'templates/deploy')}/deployment_authorized_keys#{fetch(:example)}.erb",
28
+ "examples/unicorn.rb.erb" => "#{fetch(:deploy_templates_path, 'templates/deploy')}/unicorn#{fetch(:example)}.rb.erb",
29
+ "examples/bluepill.rb.erb" => "#{fetch(:deploy_templates_path, 'templates/deploy')}/bluepill#{fetch(:example)}.rb.erb"
15
30
  }.each do |source, destination|
16
31
  config = File.read(File.dirname(__FILE__) + "/#{source}")
17
32
  File.open("./#{destination}", 'w') { |f| f.write(config) }
18
33
  info "Wrote '#{destination}'"
19
34
  end
20
- info "Now remove the '_example' portion of their names or diff with existing files and add the needed lines."
35
+ unless fetch(:example).empty?
36
+ info "Now remove the '#{fetch(:example)}' portion of their names or diff with existing files and add the needed lines."
37
+ end
38
+ end
39
+ end
40
+
41
+ desc 'Write example config files (will overwrite any existing config files).'
42
+ namespace :write_example_configs do
43
+ task :in_place do
44
+ set :example, ""
45
+ Rake::Task['deployinator:write_example_configs'].invoke
46
+ end
47
+ end
48
+
49
+ desc 'Write a file showing the built-in overridable settings.'
50
+ task :write_built_in do
51
+ run_locally do
52
+ {
53
+ 'built-in.rb' => 'built-in.rb',
54
+ }.each do |source, destination|
55
+ config = File.read(File.dirname(__FILE__) + "/#{source}")
56
+ File.open("./#{destination}", 'w') { |f| f.write(config) }
57
+ info "Wrote '#{destination}'"
58
+ end
59
+ info "Now examine the file and copy-paste into your deploy.rb or <stage>.rb and customize."
60
+ end
61
+ end
62
+
63
+ # These are the only two tasks using :preexisting_ssh_user
64
+ namespace :deployment_user do
65
+ #desc "Setup or re-setup the deployment user, idempotently"
66
+ task :setup do
67
+ on roles(:all) do |h|
68
+ on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
69
+ as :root do
70
+ deployment_user_setup(fetch(:deploy_templates_path, 'templates/deploy'))
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ task :deployment_user do
78
+ on roles(:all) do |h|
79
+ on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
80
+ as :root do
81
+ if unix_user_exists?(fetch(:deployment_username))
82
+ info "User #{fetch(:deployment_username)} already exists. You can safely re-setup the user with 'deployinator:deployment_user:setup'."
83
+ else
84
+ Rake::Task['deployinator:deployment_user:setup'].invoke
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ task :webserver_user do
92
+ on roles(:app) do
93
+ as :root do
94
+ unix_user_add(fetch(:webserver_username)) unless unix_user_exists?(fetch(:webserver_username))
95
+ end
96
+ end
97
+ end
98
+
99
+ task :file_permissions => [:deployment_user, :webserver_user] do
100
+ on roles(:app) do
101
+ as :root do
102
+ setup_file_permissions
103
+ end
21
104
  end
22
105
  end
106
+ after 'deploy:check', 'deployinator:file_permissions'
107
+ before 'deploy:restart', 'deployinator:file_permissions'
23
108
 
24
109
  end
@@ -3,6 +3,22 @@ lock '3.2.1'
3
3
 
4
4
  namespace :deploy do
5
5
 
6
+ before :starting, :log_level do
7
+ SSHKit.config.output_verbosity = fetch(:deploy_log_level)
8
+ end
9
+
10
+ before :starting, 'deployinator:sshkit_umask'
11
+
12
+ # Default branch is :master
13
+ before :starting, :set_branch do
14
+ unless ENV['from_local']
15
+ # Always use the master branch in production:
16
+ unless "#{fetch(:stage)}" == "production"
17
+ ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
18
+ end
19
+ end
20
+ end
21
+
6
22
  #desc 'Copies .git folder to support .gemspecs that run git commands'
7
23
  task :copy_git do
8
24
  unless ENV['from_local'] == "true"
@@ -17,22 +33,11 @@ namespace :deploy do
17
33
 
18
34
  if Rake::Task.task_defined?("deploy:assets:precompile")
19
35
  # Overwrite :assets:precompile to use docker
20
- Rake::Task["deploy:assets:precompile"].clear
36
+ Rake::Task["deploy:assets:precompile"].clear_actions
21
37
  namespace :assets do
22
38
  task :precompile => ['deployinator:deployment_user'] do
23
- on roles(fetch(:assets_roles)) do
24
- execute(
25
- "docker", "run", "--rm", "--tty", "--user", fetch(:webserver_username),
26
- "-w", release_path,
27
- "--link", "#{fetch(:postgres_container_name)}:postgres",
28
- "--entrypoint", "/bin/bash",
29
- "--volume", "/etc/passwd:/etc/passwd:ro",
30
- "--volume", "/etc/group:/etc/group:ro",
31
- "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
32
- fetch(:ruby_image_name), "-c",
33
- "\"umask", "0007", "&&", "#{shared_path.join('bundle', 'bin', 'rake')}",
34
- "assets:precompile\""
35
- )
39
+ on roles(fetch(:assets_roles)) do |host|
40
+ deploy_assets_precompile(host)
36
41
  end
37
42
  end
38
43
  end
@@ -40,64 +45,37 @@ namespace :deploy do
40
45
 
41
46
  if Rake::Task.task_defined?("deploy:cleanup_assets")
42
47
  # Overwrite :cleanup_assets to use docker
43
- Rake::Task["deploy:cleanup_assets"].clear
48
+ Rake::Task["deploy:cleanup_assets"].clear_actions
44
49
  desc 'Cleanup expired assets'
45
50
  task :cleanup_assets => [:set_rails_env] do
46
- on roles(fetch(:assets_roles)) do
47
- execute(
48
- "docker", "run", "--rm", "--tty",
49
- "-e", "RAILS_ENV=#{fetch(:rails_env)}",
50
- "-w", release_path,
51
- "--entrypoint", shared_path.join('bundle', 'bin', 'bundle'),
52
- "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
53
- fetch(:ruby_image_name), "exec", "rake", "assets:clean"
54
- )
51
+ on roles(fetch(:assets_roles)) do |host|
52
+ deploy_assets_cleanup(host)
55
53
  end
56
54
  end
57
55
  end
58
56
 
59
57
  if Rake::Task.task_defined?("deploy:migrate")
60
58
  # Overwrite :migrate to use docker
61
- Rake::Task["deploy:migrate"].clear
59
+ Rake::Task["deploy:migrate"].clear_actions
62
60
  desc 'Runs rake db:migrate if migrations are set'
63
61
  task :migrate => [:set_rails_env, 'deploy:check:postgres_running'] do
64
- on primary fetch(:migration_role) do
62
+ on primary fetch(:migration_role) do |host|
65
63
  conditionally_migrate = fetch(:conditionally_migrate)
66
64
  info '[deploy:migrate] Checking changes in /db/migrate' if conditionally_migrate
67
65
  if conditionally_migrate && test("diff -q #{release_path}/db/migrate #{current_path}/db/migrate")
68
66
  info '[deploy:migrate] Skip `deploy:migrate` (nothing changed in db/migrate)'
69
67
  else
70
68
  info '[deploy:migrate] Run `rake db:migrate`' if conditionally_migrate
71
- execute(
72
- "docker", "run", "--rm", "--tty",
73
- "--link", "#{fetch(:postgres_container_name)}:postgres",
74
- "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
75
- "-e", "RAILS_ENV=#{fetch(:rails_env)}",
76
- "--entrypoint", shared_path.join('bundle', 'bin', 'rake'),
77
- "-w", release_path,
78
- fetch(:ruby_image_name), "db:migrate"
79
- )
69
+ deploy_rake_db_migrate(host)
80
70
  end
81
71
  end
82
72
  end
83
73
  end
84
74
 
85
75
  task :install_bundler => ['deployinator:deployment_user'] do
86
- on roles(:app), in: :sequence, wait: 5 do
76
+ on roles(:app) do |host|
87
77
  unless file_exists?(shared_path.join('bundle', 'bin', 'bundle'))
88
- execute(
89
- "docker", "run", "--rm", "--tty", "--user", fetch(:deployment_user_id),
90
- "-e", "GEM_HOME=#{shared_path.join('bundle')}",
91
- "-e", "GEM_PATH=#{shared_path.join('bundle')}",
92
- "-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
93
- "--entrypoint", "/bin/bash",
94
- "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
95
- fetch(:ruby_image_name), "-c",
96
- "\"umask", "0007", "&&" "/usr/local/bin/gem", "install",
97
- "--install-dir", "#{shared_path.join('bundle')}",
98
- "--bindir", shared_path.join('bundle', 'bin'),
99
- "--no-ri", "--no-rdoc", "--quiet", "bundler", "-v'#{fetch(:bundler_version)}'\""
100
- )
78
+ deploy_install_bundler(host)
101
79
  end
102
80
  end
103
81
  end
@@ -105,26 +83,24 @@ namespace :deploy do
105
83
 
106
84
  desc 'Restart application using bluepill restart inside the docker container.'
107
85
  task :restart => ['deployinator:webserver_user', :install_config_files] do
108
- on roles(:app), in: :sequence, wait: 5 do
109
- if container_exists?(fetch(:ruby_container_name))
110
- if container_is_restarting?(fetch(:ruby_container_name))
111
- execute("docker", "stop", fetch(:ruby_container_name))
86
+ on roles(:app) do |host|
87
+ name = fetch(:ruby_container_name)
88
+ if container_exists?(name)
89
+ if container_is_restarting?(name)
90
+ execute("docker", "stop", name)
112
91
  end
113
- if container_is_running?(fetch(:ruby_container_name))
114
- execute(
115
- "docker", "exec", "--tty",
116
- fetch(:ruby_container_name),
117
- shared_path.join('bundle', 'bin', 'bluepill'),
118
- fetch(:application), "restart"
119
- )
92
+ if container_is_running?(name)
93
+ deploy_bluepill_restart(host)
120
94
  else
121
- execute("docker", "start", fetch(:ruby_container_name))
95
+ execute("docker", "start", name)
122
96
  end
123
97
  else
124
98
  as :root do
125
99
  execute("rm", "-f", fetch(:webserver_socket_path).join('unicorn.pid'))
126
100
  end
127
- execute("docker", "run", fetch(:docker_run_bluepill_command))
101
+ warn "Starting a new container named #{name} on #{host}"
102
+ deploy_run_bluepill(host)
103
+ check_stayed_running(name)
128
104
  end
129
105
  end
130
106
  end
@@ -133,15 +109,10 @@ namespace :deploy do
133
109
  desc 'Restart application by recreating the docker container.'
134
110
  namespace :restart do
135
111
  task :force do
136
- on roles(:app), in: :sequence, wait: 5 do
112
+ on roles(:app) do |host|
137
113
  if container_exists?(fetch(:ruby_container_name))
138
114
  if container_is_running?(fetch(:ruby_container_name))
139
- execute(
140
- "docker", "exec", "--tty",
141
- fetch(:ruby_container_name),
142
- shared_path.join('bundle', 'bin', 'bluepill'),
143
- fetch(:application), "stop"
144
- )
115
+ deploy_bluepill_stop(host)
145
116
  sleep 5
146
117
  execute("docker", "stop", fetch(:ruby_container_name))
147
118
  execute("docker", "wait", fetch(:ruby_container_name))
@@ -173,33 +144,37 @@ namespace :deploy do
173
144
  # end
174
145
 
175
146
  task :install_config_files => ['deployinator:deployment_user', 'deployinator:webserver_user'] do
176
- on roles(:app), in: :sequence, wait: 5 do
147
+ on roles(:app) do |host|
177
148
  set :bluepill_config, -> { "bluepill.rb" }
178
149
  set :unicorn_config, -> { "unicorn.rb" }
179
150
  set :socket_path, -> { fetch(:webserver_socket_path) }
180
151
  [fetch(:bluepill_config), fetch(:unicorn_config)].each do |config_file|
181
- template_path = File.expand_path("./templates/deploy/#{config_file}.erb")
152
+ template_path = File.expand_path("./#{fetch(:deploy_templates_path)}/#{config_file}.erb")
182
153
  generated_config_file = ERB.new(File.new(template_path).read).result(binding)
183
154
  set :final_path, -> { release_path.join('config', config_file) }
184
155
  upload! StringIO.new(generated_config_file), "/tmp/#{config_file}"
185
156
  execute("mv", "/tmp/#{config_file}", fetch(:final_path))
186
157
  as :root do
187
- execute("chown", "#{fetch(:deployment_user_id)}:#{fetch(:webserver_user_id)}", fetch(:final_path))
158
+ execute("chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}", fetch(:final_path))
188
159
  end
189
160
  end
190
161
  end
191
162
  end
192
163
 
193
- task :print_rails_console do
194
- run_locally do
195
- command = [
196
- "docker", "exec", "--interactive", "--tty",
197
- fetch(:ruby_container_name),
198
- "bash", "-c", "\"cd", current_path, "&&",
199
- shared_path.join('bundle', 'bin', 'rails'),
200
- "console", "#{fetch(:rails_env)}\""
201
- ].join(' ')
202
- info command
164
+ desc "Enter the Rails console."
165
+ task :rails_console do
166
+ on roles(:app) do |host|
167
+ info "Entering Rails Console inside #{fetch(:ruby_container_name)} on #{host}"
168
+ system deploy_rails_console(host)
169
+ end
170
+ end
171
+
172
+ namespace :rails_console do
173
+ task :print do
174
+ on roles(:app) do |host|
175
+ info "You can SSH into #{host} and run the following command to enter the Rails Console."
176
+ info deploy_rails_console_print(host)
177
+ end
203
178
  end
204
179
  end
205
180
 
@@ -1,99 +1,21 @@
1
- # config valid only for Capistrano 3.1
1
+ # config valid only for Capistrano 3.2.1
2
2
  lock '3.2.1'
3
3
 
4
- set :application, 'my_app_name'
5
- set :repo_url, 'git@example.com:me/my_repo.git'
6
- set :preexisting_ssh_user, ENV['USER']
7
- set :deployment_username, "deployer" # user with SSH access and passwordless sudo rights
8
- set :webserver_username, "www-data" # less trusted web server user with limited write permissions
9
-
10
- set :webserver_owned_dirs, [shared_path.join('tmp', 'cache'), shared_path.join('public', 'assets')]
11
- set :webserver_writeable_dirs, [shared_path.join('run'), shared_path.join("tmp"), shared_path.join("log")]
12
- set :webserver_executable_dirs, [shared_path.join("bundle", "bin")]
13
- set :ignore_permissions_dirs, [shared_path.join("postgres"), shared_path.join("nginx")]
14
- set :webserver_socket_path, shared_path.join('run')
15
-
16
- # Default branch is :master
17
- # Always use the master branch in production:
18
- set :current_stage, -> { fetch(:stage).to_s.strip }
19
- unless fetch(:current_stage) == "production"
20
- ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
21
- end
22
-
23
- # Default deploy_to directory is /var/www/my_app
24
- # set :deploy_to, '/var/www/my_app'
25
-
26
- # Default value for :log_level is :debug
27
- # set :log_level, :debug
28
-
29
- # Default value for :linked_files is []
30
- # set :linked_files, %w{config/database.yml}
4
+ ##### deployinator
5
+ ### ------------------------------------------------------------------
6
+ set :repo_url, 'git@example.com:me/my_repo.git'
7
+ set :application, 'my_app_name'
8
+ set :preexisting_ssh_user, ENV['USER']
9
+ set :deployment_username, "deployer" # user with SSH access and passwordless sudo rights
10
+ set :webserver_username, "www-data" # less trusted web server user with limited write permissions
11
+ set :webserver_owned_dirs, [shared_path.join('tmp', 'cache'), shared_path.join('public', 'assets')]
12
+ set :webserver_writeable_dirs, [shared_path.join('run'), shared_path.join("tmp"), shared_path.join("log")]
13
+ set :webserver_executable_dirs, [shared_path.join("bundle", "bin")]
14
+ set :ignore_permissions_dirs, [shared_path.join("postgres"), shared_path.join("nginx")]
31
15
 
32
16
  # Default value for linked_dirs is []
33
17
  # set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
34
18
 
35
- # Default value for default_env is {}
36
- # set :default_env, { path: "/opt/ruby/bin:$PATH" }
37
-
38
- # Default value for keep_releases is 5
39
- # set :keep_releases, 5
40
-
41
-
42
- #----------------------------------------------------
43
- ## The values below shouldn't need changed under the majority of circumstances.
44
-
45
- # Use `cap <stage> deploy from_local=true` to deploy your
46
- # locally changed code instead of the code in the git repo. You can also add --trace.
47
- if ENV['from_local']
48
- if fetch(:current_stage) == "production"
49
- run_locally do
50
- fatal "You are trying to deploy to production using from_local, this should pretty much never be done."
51
- end
52
- ask :yes_no, "Are you positive you want to continue?"
53
- if fetch(:yes_no).chomp.downcase == "yes"
54
- set :scm, :copy
55
- else
56
- exit
57
- end
58
- end
59
- else
60
- set :scm, :git
61
- end
62
-
63
- #set :bundle_roles, :all # this is default
64
- #set :bundle_servers, -> { release_roles(fetch(:bundle_roles)) } # this is default
65
- #set :bundle_binstubs, -> { shared_path.join('bin') } # this is default
66
- #set :bundle_binstubs, -> { shared_path.join('bundle', 'bin') } # this will be overwritten by deployinator
67
- #set :bundle_gemfile, -> { release_path.join('Gemfile') } # this will be overwritten by deployinator
68
- #set :bundle_path, -> { shared_path.join('bundle') } # this is default
69
- #set :bundle_without, %w{development test}.join(' ') # this is default
70
- #set :bundle_flags, '--deployment --quiet' # this is default
71
- #set :bundle_flags, '--deployment'
72
- #set :bundle_env_variables, {} # this is default
73
-
74
- set :docker_run_bluepill_command, -> { [
75
- "--tty", "--detach",
76
- "--name", fetch(:ruby_container_name),
77
- "-e", "GEM_HOME=#{shared_path.join('bundle')}",
78
- "-e", "GEM_PATH=#{shared_path.join('bundle')}",
79
- "-e", "BUNDLE_GEMFILE=#{current_path.join('Gemfile')}",
80
- "-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
81
- "--link", "#{fetch(:postgres_container_name)}:postgres",
82
- "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
83
- "--entrypoint", shared_path.join('bundle', 'bin', 'bluepill'),
84
- "--restart", "always", "--memory", "#{fetch(:ruby_container_max_mem_mb)}m",
85
- fetch(:ruby_image_name), "load",
86
- current_path.join('config', 'bluepill.rb')
87
- ] }
88
-
89
- set :docker_run_cadvisor_command, -> { [
90
- "--detach",
91
- "--name", "cadvisor",
92
- "--volume", "/:/rootfs:ro",
93
- "--volume", "/var/run:/var/run:rw",
94
- "--volume", "/sys:/sys:ro",
95
- "--volume", "/var/lib/docker/:/var/lib/docker:ro",
96
- "--publish", "127.0.0.1:8080:8080",
97
- "--restart", "always",
98
- "google/cadvisor:latest"
99
- ] }
19
+ set :bundler_version, "1.7.4"
20
+ set :use_cadvisor, true
21
+ ### ------------------------------------------------------------------
@@ -1,21 +1,12 @@
1
- set :domain, "my-app-staging.example.com"
2
- set :user_host, "#{fetch(:deployment_username)}@#{fetch(:domain)}"
3
-
4
- role :app, fetch(:user_host)
5
- role :web, fetch(:user_host)
6
- role :db, fetch(:user_host)
7
-
8
- set :rails_env, 'production'
9
- set :migration_role, 'app' # Defaults to 'db'
10
- #set :conditionally_migrate, true # Defaults to false. If true, it's skip migration if files in db/migrate not modified
11
- set :assets_roles, [:app] # Defaults to [:web]
12
- #set :assets_prefix, 'prepackaged-assets' # Defaults to 'assets' this should match config.assets.prefix in your rails config/application.rb
13
-
14
- set :webserver_container_name, "my-app-staging.example.com-nginx-80-443"
15
- set :postgres_container_name, "my-app-staging.example.com-postgres-5432-master"
16
- set :postgres_port, "5432"
17
- set :ruby_image_name, "snarlysodboxer/ruby:1.9.3-p547"
18
- set :ruby_container_name, "#{fetch(:domain)}-ruby-bluepill"
19
- set :ruby_container_max_mem_mb, "1024"
20
- set :bundler_version, "1.7.4"
21
- set :use_cadvisor, true
1
+ ##### deployinator
2
+ ### ------------------------------------------------------------------
3
+ set :domain, "my-app-staging.example.com"
4
+ server fetch(:domain),
5
+ :user => fetch(:deployment_username),
6
+ :roles => ["app", "web", "db"]
7
+ set :rails_env, 'production'
8
+ set :ruby_image_name, "snarlysodboxer/ruby:1.9.3-p547"
9
+ set :ruby_container_name, "#{fetch(:domain)}-ruby-bluepill"
10
+ set :ruby_container_max_mem_mb, "1024"
11
+ set :postgres_port, "5432"
12
+ ### ------------------------------------------------------------------
@@ -1,141 +1,95 @@
1
1
  namespace :deployinator do
2
2
 
3
- # These are the only two tasks using :preexisting_ssh_user
4
- namespace :deployment_user do
5
- #desc "Setup or re-setup the deployment user, idempotently"
6
- task :setup do
7
- on "#{fetch(:preexisting_ssh_user)}@#{fetch(:domain)}" do
8
- as :root do
9
- unix_user_add(fetch(:deployment_username)) unless unix_user_exists?(fetch(:deployment_username))
10
- execute "usermod", "-a", "-G", "sudo,docker,#{fetch(:webserver_username)}", fetch(:deployment_username)
11
- execute "mkdir", "-p", "/home/#{fetch(:deployment_username)}/.ssh"
12
- template_path = File.expand_path("./templates/deploy/deployment_authorized_keys.erb")
13
- generated_config_file = ERB.new(File.new(template_path).read).result(binding)
14
- # upload! does not yet honor "as" and similar scoping methods
15
- upload! StringIO.new(generated_config_file), "/tmp/authorized_keys"
16
- execute "mv", "-b", "/tmp/authorized_keys", "/home/#{fetch(:deployment_username)}/.ssh/authorized_keys"
17
- execute "chown", "-R", "#{fetch(:deployment_username)}:#{fetch(:deployment_username)}", "/home/#{fetch(:deployment_username)}/.ssh"
18
- execute "chmod", "700", "/home/#{fetch(:deployment_username)}/.ssh"
19
- execute "chmod", "600", "/home/#{fetch(:deployment_username)}/.ssh/authorized_keys"
20
- end
21
- end
22
- end
23
- end
24
-
25
- task :deployment_user do
26
- on "#{fetch(:preexisting_ssh_user)}@#{fetch(:domain)}" do
27
- as :root do
28
- if unix_user_exists?(fetch(:deployment_username))
29
- info "User #{fetch(:deployment_username)} already exists. You can safely re-setup the user with 'deployinator:deployment_user:setup'."
30
- else
31
- Rake::Task['deployinator:deployment_user:setup'].invoke
32
- end
33
- set :deployment_user_id, unix_user_get_id(fetch(:deployment_username))
34
- end
35
- end
36
- end
37
-
38
- task :webserver_user do
39
- on roles(:app) do
40
- as :root do
41
- unix_user_add(fetch(:webserver_username)) unless unix_user_exists?(fetch(:webserver_username))
42
- set :webserver_user_id, unix_user_get_id(fetch(:webserver_username))
43
- end
44
- end
45
- end
46
-
47
3
  task :sshkit_umask do
48
4
  SSHKit.config.umask = "0027"
49
5
  end
50
- if Rake::Task.task_defined?('deploy:started')
51
- before 'deploy:started', 'deployinator:sshkit_umask'
52
- end
53
-
54
- task :file_permissions => [:deployment_user, :webserver_user] do
55
- on roles(:app) do
56
- as :root do
57
- ignore_options = fetch(:ignore_permissions_dirs).collect do |dir|
58
- ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
59
- end
60
-
61
- chown_ignore_options = fetch(:webserver_owned_dirs).collect do |dir|
62
- ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
63
- end
64
-
65
- # chown webserver owned
66
- fetch(:webserver_owned_dirs).each do |dir|
67
- if directory_exists?(dir)
68
- execute "find", dir, ignore_options,
69
- "-exec", "chown", "#{fetch(:webserver_user_id)}:#{fetch(:webserver_user_id)}", "{}", "+"
70
- end
71
- end
72
-
73
- # chown
74
- execute "find", fetch(:deploy_to), ignore_options, chown_ignore_options,
75
- "-exec", "chown", "#{fetch(:deployment_user_id)}:#{fetch(:webserver_user_id)}", "{}", "+"
76
-
77
- # chmod executable
78
- fetch(:webserver_executable_dirs).each do |dir|
79
- if directory_exists?(dir)
80
- execute "find", dir, "-type", "f",
81
- "-exec", "chmod", "0750", "{}", "+"
82
- end
83
- ignore_options += ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
84
- end
85
-
86
- # chmod writable
87
- fetch(:webserver_writeable_dirs).each do |dir|
88
- if directory_exists?(dir)
89
- execute "find", "-L", dir, "-type", "d",
90
- "-exec", "chmod", "2770", "{}", "+"
91
- execute "find", "-L", dir, "-type", "f",
92
- "-exec", "chmod", "0660", "{}", "+"
93
- end
94
- ignore_options += ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
95
- end
96
-
97
- # chmod
98
- execute "find", fetch(:deploy_to), "-type", "d", ignore_options,
99
- "-exec", "chmod", "2750", "{}", "+"
100
- execute "find", fetch(:deploy_to), "-type", "f", ignore_options,
101
- "-exec", "chmod", "0640", "{}", "+"
102
- end
103
- end
104
- end
105
- after 'deploy:check', 'deployinator:file_permissions'
106
- before 'deploy:restart', 'deployinator:file_permissions'
107
-
108
6
 
109
7
  task :settings, [:absolute_path, :relative_path] do |t, args|
110
8
  run_locally do
9
+ if fetch(:print_all)
10
+ lines = "\nThe following settings are needed in your config (#{args.relative_path}).\n"
11
+ lines += File.read(args.absolute_path)
12
+ info lines
13
+ break
14
+ end
15
+
111
16
  need_moar_settings = false
112
17
  settings = File.read(args.absolute_path).split("\nset").collect do |line|
113
18
  "set#{line}" if line =~ /^ :/
114
19
  end.compact
115
- if fetch(:print_all, false)
116
- lines = "\nThe following settings are needed in your config (#{args.relative_path}).\n"
117
- else
118
- lines = "\nAdd the following setting(s) to your config (#{args.relative_path}) and try again:\n"
119
- end
20
+ lines = "\nAdd the following setting(s) to your config (#{args.relative_path}) and try again:\n"
120
21
  settings.each do |setting|
121
- if fetch(setting.split(',')[0].split(':')[1].to_sym).nil? or fetch(:print_all, false)
22
+ if fetch(setting.split(',')[0].split(':')[1].to_sym).nil?
122
23
  lines += setting.chomp == setting ? "#{setting}\n" : setting
123
24
  need_moar_settings = true
124
25
  end
125
26
  end
126
- if need_moar_settings
127
- if fetch(:print_all, false)
128
- info lines
129
- else
130
- fatal lines if lines.lines.count > 2
131
- exit
132
- end
133
- end
27
+ fatal(lines) if(lines.lines.count > 2) if(need_moar_settings)
28
+ exit if need_moar_settings
134
29
  end
135
30
  end
136
31
 
137
32
  end
138
33
 
34
+
35
+ def deployment_user_setup(templates_path)
36
+ require 'erb' unless defined?(ERB)
37
+ name = fetch(:deployment_username)
38
+ unix_user_add(name) unless unix_user_exists?(name)
39
+ execute "usermod", "-a", "-G", "sudo,docker,#{fetch(:webserver_username)}", name
40
+ execute "mkdir", "-p", "/home/#{name}/.ssh"
41
+ template_path = File.expand_path("./#{templates_path}/deployment_authorized_keys.erb")
42
+ generated_config_file = ERB.new(File.new(template_path).read).result(binding)
43
+ # upload! does not yet honor "as" and similar scoping methods
44
+ upload! StringIO.new(generated_config_file), "/tmp/authorized_keys"
45
+ execute "mv", "-b", "/tmp/authorized_keys", "/home/#{name}/.ssh/authorized_keys"
46
+ execute "chown", "-R", "#{name}:#{name}", "/home/#{name}"
47
+ execute "chmod", "700", "/home/#{name}/.ssh"
48
+ execute "chmod", "600", "/home/#{name}/.ssh/authorized_keys"
49
+ end
50
+
51
+ def setup_file_permissions
52
+ ignore_options = fetch(:ignore_permissions_dirs).collect do |dir|
53
+ ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
54
+ end
55
+ chown_ignore_options = fetch(:webserver_owned_dirs).collect do |dir|
56
+ ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
57
+ end
58
+ # chown webserver owned
59
+ fetch(:webserver_owned_dirs).each do |dir|
60
+ if directory_exists?(dir)
61
+ execute "find", dir, ignore_options,
62
+ "-exec", "chown", "#{fetch(:webserver_username)}:#{fetch(:webserver_username)}", "{}", "+"
63
+ end
64
+ end
65
+ # chown
66
+ execute "find", fetch(:deploy_to), ignore_options, chown_ignore_options,
67
+ "-exec", "chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}", "{}", "+"
68
+ # chmod executable
69
+ fetch(:webserver_executable_dirs).each do |dir|
70
+ if directory_exists?(dir)
71
+ execute "find", dir, "-type", "f",
72
+ "-exec", "chmod", "0750", "{}", "+"
73
+ end
74
+ ignore_options += ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
75
+ end
76
+ # chmod writable
77
+ fetch(:webserver_writeable_dirs).each do |dir|
78
+ if directory_exists?(dir)
79
+ execute "find", "-L", dir, "-type", "d",
80
+ "-exec", "chmod", "2770", "{}", "+"
81
+ execute "find", "-L", dir, "-type", "f",
82
+ "-exec", "chmod", "0660", "{}", "+"
83
+ end
84
+ ignore_options += ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
85
+ end
86
+ # chmod
87
+ execute "find", fetch(:deploy_to), "-type", "d", ignore_options,
88
+ "-exec", "chmod", "2750", "{}", "+"
89
+ execute "find", fetch(:deploy_to), "-type", "f", ignore_options,
90
+ "-exec", "chmod", "0640", "{}", "+"
91
+ end
92
+
139
93
  def container_exists?(container_name)
140
94
  test "bash", "-c", "\"docker", "inspect", container_name, "&>", "/dev/null\""
141
95
  end
@@ -150,6 +104,30 @@ def container_is_restarting?(container_name)
150
104
  container_name, "2>&1`\"", "=", "\"true\"", "]"
151
105
  end
152
106
 
107
+ def check_stayed_running(name)
108
+ sleep 3
109
+ unless container_is_running?(name)
110
+ fatal "Container #{name} on #{fetch(:domain)} did not stay running more than 3 seconds"
111
+ exit
112
+ end
113
+ if container_is_restarting?(name)
114
+ fatal "Container #{name} on #{fetch(:domain)} is stuck restarting itself."
115
+ exit
116
+ end
117
+ end
118
+
119
+ def start_container(name)
120
+ warn "Starting an existing but non-running container named #{name}"
121
+ execute("docker", "start", name)
122
+ check_stayed_running(name)
123
+ end
124
+
125
+ def restart_container(name)
126
+ warn "Restarting a running container named #{name}"
127
+ execute("docker", "restart", name)
128
+ check_stayed_running(name)
129
+ end
130
+
153
131
  def localhost_port_responding?(port)
154
132
  test "nc", "127.0.0.1", port, "<", "/dev/null", ">", "/dev/null;",
155
133
  "[", "`echo", "$?`", "-eq", "0", "]"
@@ -163,10 +141,14 @@ def unix_user_add(user)
163
141
  execute "adduser", "--disabled-password", "--gecos", "\"\"", user
164
142
  end
165
143
 
166
- def unix_user_get_id(user)
144
+ def unix_user_get_uid(user)
167
145
  capture("id", "-u", user).strip
168
146
  end
169
147
 
148
+ def unix_user_get_gid(user)
149
+ capture("id", "-g", user).strip
150
+ end
151
+
170
152
  def file_exists?(file)
171
153
  test "[", "-f", file, "]"
172
154
  end
@@ -175,32 +157,6 @@ def directory_exists?(dir)
175
157
  test "[", "-d", dir, "]"
176
158
  end
177
159
 
178
- def check_stayed_running(name)
179
- sleep 3
180
- unless container_is_running?(name)
181
- fatal "Container #{name} on #{fetch(:domain)} did not stay running more than 3 seconds"
182
- exit
183
- end
184
- if container_is_restarting?(name)
185
- fatal "Container #{name} on #{fetch(:domain)} is stuck restarting itself."
186
- exit
187
- end
188
- end
189
-
190
- def create_container(name, command)
191
- warn "Starting a new container named #{name} on #{fetch(:domain)}"
192
- execute("docker", "run", command)
193
- check_stayed_running(name)
194
- end
195
-
196
- def start_container(name)
197
- warn "Starting an existing but non-running container named #{name}"
198
- execute("docker", "start", name)
199
- check_stayed_running(name)
200
- end
201
-
202
- def restart_container(name)
203
- warn "Restarting a running container named #{name}"
204
- execute("docker", "restart", name)
205
- check_stayed_running(name)
160
+ def files_in_directory?(dir)
161
+ test("[", "\"$(ls", "-A", "#{dir})\"", "]")
206
162
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deployinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,14 +9,14 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-06 00:00:00.000000000 Z
12
+ date: 2015-01-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: capistrano
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - '='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
21
  version: 3.2.1
22
22
  type: :runtime
@@ -24,10 +24,42 @@ dependencies:
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - '='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.2.1
30
- description: An Opinionated Deployment gem
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 10.3.2
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 10.3.2
46
+ - !ruby/object:Gem::Dependency
47
+ name: sshkit
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.5.1
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.5.1
62
+ description: Deploy Ruby on Rails using Capistrano and Docker
31
63
  email: davidamick@ctisolutionsinc.com
32
64
  executables: []
33
65
  extensions: []
@@ -38,6 +70,7 @@ files:
38
70
  - lib/deployinator/check.rb
39
71
  - lib/deployinator/config.rb
40
72
  - lib/deployinator/helpers.rb
73
+ - lib/deployinator/built-in.rb
41
74
  - lib/deployinator/examples/Capfile
42
75
  - lib/deployinator/examples/config/deploy.rb
43
76
  - lib/deployinator/examples/config/deploy/staging.rb
@@ -57,14 +90,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
90
  requirements:
58
91
  - - ! '>='
59
92
  - !ruby/object:Gem::Version
60
- version: '0'
93
+ version: 1.9.3
61
94
  required_rubygems_version: !ruby/object:Gem::Requirement
62
95
  none: false
63
96
  requirements:
64
97
  - - ! '>='
65
98
  - !ruby/object:Gem::Version
66
99
  version: '0'
67
- requirements: []
100
+ requirements:
101
+ - Docker ~> 1.3.1
68
102
  rubyforge_project:
69
103
  rubygems_version: 1.8.23.2
70
104
  signing_key: