pvcglue 0.1.39 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/README.md +12 -3
- data/bin/pvc +4 -2
- data/lib/pvcglue.rb +106 -21
- data/lib/pvcglue/bootstrap.rb +1 -1
- data/lib/pvcglue/cli.rb +28 -17
- data/lib/pvcglue/cloud.rb +243 -56
- data/lib/pvcglue/configuration.rb +43 -5
- data/lib/pvcglue/connection.rb +236 -0
- data/lib/pvcglue/custom_hashie.rb +3 -0
- data/lib/pvcglue/db.rb +19 -13
- data/lib/pvcglue/digital_ocean.rb +21 -0
- data/lib/pvcglue/env.rb +52 -28
- data/lib/pvcglue/manager.rb +38 -25
- data/lib/pvcglue/minion.rb +182 -0
- data/lib/pvcglue/nodes.rb +1 -1
- data/lib/pvcglue/{packages → old_packages}/bootstrap.rb +15 -15
- data/lib/pvcglue/{packages → old_packages}/env.rb +8 -8
- data/lib/pvcglue/old_packages/firewall.rb +48 -0
- data/lib/pvcglue/old_packages/manager.rb +116 -0
- data/lib/pvcglue/{packages → old_packages}/monit-bootstrap.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/monit-web.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/nginx.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/nodejs.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/passenger.rb +0 -0
- data/lib/pvcglue/old_packages/postgresql.rb +10 -0
- data/lib/pvcglue/{packages → old_packages}/role_db.rb +9 -9
- data/lib/pvcglue/{packages → old_packages}/role_lb.rb +6 -6
- data/lib/pvcglue/{packages → old_packages}/role_memcached.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/role_redis.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/role_web.rb +9 -9
- data/lib/pvcglue/old_packages/rvm.rb +78 -0
- data/lib/pvcglue/{packages → old_packages}/timezone.rb +0 -0
- data/lib/pvcglue/{packages → old_packages}/ubuntu.rb +0 -0
- data/lib/pvcglue/packages.rb +192 -71
- data/lib/pvcglue/packages/apt.rb +74 -0
- data/lib/pvcglue/packages/apt_repos.rb +48 -0
- data/lib/pvcglue/packages/apt_update.rb +18 -0
- data/lib/pvcglue/packages/apt_upgrade.rb +20 -0
- data/lib/pvcglue/packages/authorized_keys.rb +33 -0
- data/lib/pvcglue/packages/bundler.rb +14 -0
- data/lib/pvcglue/packages/dir_base.rb +16 -0
- data/lib/pvcglue/packages/dir_shared.rb +16 -0
- data/lib/pvcglue/packages/firewall.rb +30 -46
- data/lib/pvcglue/packages/load_balancer.rb +71 -0
- data/lib/pvcglue/packages/maintenance_mode.rb +28 -0
- data/lib/pvcglue/packages/manager.rb +101 -99
- data/lib/pvcglue/packages/postgresql.rb +36 -8
- data/lib/pvcglue/packages/roles.rb +23 -0
- data/lib/pvcglue/packages/ruby.rb +13 -0
- data/lib/pvcglue/packages/rvm.rb +18 -71
- data/lib/pvcglue/packages/secrets.rb +36 -0
- data/lib/pvcglue/packages/ssh_key_check.rb +11 -0
- data/lib/pvcglue/packages/ssl.rb +45 -0
- data/lib/pvcglue/packages/ssl_acme.rb +29 -0
- data/lib/pvcglue/packages/swap.rb +14 -0
- data/lib/pvcglue/packages/unattended_upgrades.rb +20 -0
- data/lib/pvcglue/packages/users.rb +20 -0
- data/lib/pvcglue/packages/web.rb +50 -0
- data/lib/pvcglue/stack.rb +166 -0
- data/lib/pvcglue/templates/50unattended-upgrades.erb +63 -0
- data/lib/pvcglue/templates/capfile.erb +4 -1
- data/lib/pvcglue/templates/deploy.rb.erb +3 -2
- data/lib/pvcglue/templates/lb.sites-enabled.erb +15 -9
- data/lib/pvcglue/templates/letsencrypt-webroot.erb +3 -0
- data/lib/pvcglue/templates/pg_hba.conf.erb +1 -2
- data/lib/pvcglue/templates/postgresql.conf.erb +376 -291
- data/lib/pvcglue/templates/stage-deploy.rb.erb +2 -2
- data/lib/pvcglue/templates/web.bashrc.erb +16 -5
- data/lib/pvcglue/templates/web.nginx.conf.erb +1 -1
- data/lib/pvcglue/templates/web.sites-enabled.erb +1 -1
- data/lib/pvcglue/version.rb +1 -1
- data/pvcglue.gemspec +17 -12
- metadata +125 -22
@@ -1,10 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
action('restart') { sudo('service postgresql restart') }
|
5
|
-
end
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Postgresql < Pvcglue::Packages
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
def installed?
|
6
|
+
get_minion_state(:postgresql_updated_at)
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
Pvcglue::Env.initialize_stage_env
|
11
|
+
connection.write_to_file_from_template(:root, 'postgresql.conf.erb', '/etc/postgresql/9.6/main/postgresql.conf', 'postgres', 'postgres', '0644')
|
12
|
+
connection.write_to_file_from_template(:root, 'pg_hba.conf.erb', '/etc/postgresql/9.6/main/pg_hba.conf', 'postgres', 'postgres', '0644')
|
13
|
+
|
14
|
+
# connection.run_get_stdout(:root, '', 'service postgresql restart')
|
15
|
+
# unless $?.exitstatus == 0
|
16
|
+
# Pvcglue.logger.error { 'Unable to (re)start postgresql. Getting status...' }
|
17
|
+
# result = connection.run_get_stdout(:root, '', 'systemctl status postgresql.service')
|
18
|
+
# puts result
|
19
|
+
# raise('There was a problem restarting PostgreSQL.')
|
20
|
+
# end
|
21
|
+
|
22
|
+
username = Pvcglue.cloud.stage_env['DB_USER_POSTGRES_USERNAME']
|
23
|
+
password = Pvcglue.cloud.stage_env['DB_USER_POSTGRES_PASSWORD']
|
24
|
+
db_name = username # just for clarity in later statements. This also must match database.yml.
|
25
|
+
# TODO: Instead of ssh? below, use ssh!, but allow for the user having been already created. It's only an issue for when the minion state has been reset
|
26
|
+
connection.ssh?(:root, '', %Q[cd /var/lib/postgresql && sudo -u postgres psql -c "CREATE ROLE #{username} LOGIN CREATEDB PASSWORD '#{password}';"])
|
27
|
+
connection.ssh!(:root, '', %Q[cd /var/lib/postgresql && sudo -u postgres psql -c "ALTER ROLE #{username} PASSWORD '#{password}' CREATEDB LOGIN"])
|
28
|
+
connection.ssh?(:root, '', %Q[cd /var/lib/postgresql && sudo -u postgres psql -c "CREATE DATABASE #{db_name} WITH OWNER #{username}"])
|
29
|
+
connection.ssh!(:root, '', %Q[cd /var/lib/postgresql && sudo -u postgres psql #{db_name} -c "ALTER SCHEMA public OWNER TO #{username}"])
|
10
30
|
|
31
|
+
|
32
|
+
set_minion_state(:postgresql_updated_at, Time.now.utc)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Roles < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def post_install_check?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def install!
|
13
|
+
Pvcglue::Packages::Manager.apply(minion) if has_role?(:manager)
|
14
|
+
Pvcglue::Packages::LoadBalancer.apply(minion) if has_role?(:lb)
|
15
|
+
Pvcglue::Packages::Web.apply(minion) if has_role?(:web)
|
16
|
+
Pvcglue::Packages::Worker.apply(minion) if has_role?(:worker)
|
17
|
+
Pvcglue::Packages::Postgresql.apply(minion) if has_role?(:pg)
|
18
|
+
Pvcglue::Packages::Memcache.apply(minion) if has_role?(:mc)
|
19
|
+
Pvcglue::Packages::Redis.apply(minion) if has_role?(:redis)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Ruby < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
connection.run_get_stdout!(user_name, '', 'rvm list strings') =~ /#{Pvcglue.configuration.ruby_version.gsub('.', '\.')}/
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
connection.run!(user_name, '', "rvm install #{Pvcglue.configuration.ruby_version}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/pvcglue/packages/rvm.rb
CHANGED
@@ -1,78 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Rvm < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
connection.run_get_stdout!(user_name, '', 'type rvm | head -n 1') =~ /rvm is a function/
|
6
|
+
end
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
+
def install!
|
9
|
+
connection.write_to_file_from_template(user_name, 'gemrc.erb', "/home/#{user_name}/.gemrc") # sets: gem: --no-ri --no-rdoc
|
10
|
+
connection.write_to_file_from_template(user_name, 'web.bashrc.erb', "/home/#{user_name}/.bashrc")
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# run 'curl -sSL https://rvm.io/mpapis.asc | gpg --import -'
|
13
|
-
run '\curl -sSL https://get.rvm.io | bash -s stable --with-default-gems="bundler"'
|
14
|
-
run "rvm requirements"
|
15
|
-
end
|
12
|
+
connection.run_get_stdout!(user_name, '', 'gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3')
|
13
|
+
# Do it again, the first time only sets things up, and does not import the keys
|
14
|
+
connection.run!(user_name, '', '\curl -sSL https://get.rvm.io | bash -s stable --with-default-gems=bundler')
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
16
|
+
# TODO: set autolibs mode so there are not installed automatically, as the user won't have sudo permissions later.
|
17
|
+
# OR create a 'install' user that can sudo...might be easier...
|
18
|
+
# Installing required packages: libreadline6-dev, libyaml-dev, libsqlite3-dev, sqlite3, autoconf, libgmp-dev, libgdbm-dev, libncurses5-dev, automake, libtool, bison, pkg-config, libffi-dev...............
|
21
19
|
|
22
|
-
|
23
|
-
file({
|
24
|
-
:template => Pvcglue.template_file_name('web.bashrc.erb'),
|
25
|
-
:destination => '/home/deploy/.bashrc',
|
26
|
-
:create_dirs => false,
|
27
|
-
:permissions => 0644,
|
28
|
-
:user => 'deploy',
|
29
|
-
:group => 'deploy'
|
30
|
-
})
|
31
|
-
end
|
20
|
+
connection.run_get_stdout!(user_name, '', 'rvm requirements')
|
32
21
|
|
33
|
-
|
34
|
-
|
35
|
-
action 'exists' do |gem_name|
|
36
|
-
run("gem list -i #{gem_name}") =~ /true/
|
37
|
-
end
|
38
|
-
action 'install' do |gem_name|
|
39
|
-
sudo "gem install #{gem_name} --no-ri --no-rdoc"
|
22
|
+
end
|
23
|
+
end
|
40
24
|
end
|
41
|
-
action 'uninstall' do |gem_name|
|
42
|
-
sudo "gem uninstall #{gem_name} -x -a"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
package 'bundler' do
|
47
|
-
depends_on 'gem'
|
48
|
-
apply { trigger 'gem:install', 'bundler' }
|
49
|
-
remove { trigger 'gem:remove', 'bundler' }
|
50
|
-
validate { trigger 'gem:exists', 'bundler' }
|
51
25
|
end
|
52
|
-
|
53
|
-
package 'rvm-ruby' do
|
54
|
-
depends_on 'rvm'
|
55
|
-
|
56
|
-
validate do
|
57
|
-
run('rvm list strings') =~ /#{Pvcglue.configuration.ruby_version.gsub('.', '\.')}/
|
58
|
-
end
|
59
|
-
|
60
|
-
apply do
|
61
|
-
run "rvm install #{Pvcglue.configuration.ruby_version}"
|
62
|
-
# run "rvm --default use 2.0.0"
|
63
|
-
end
|
64
|
-
|
65
|
-
remove do
|
66
|
-
run "rvm remove --archive --gems #{Pvcglue.configuration.ruby_version}"
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
package 'no-rdoc' do
|
72
|
-
file({
|
73
|
-
:template => Pvcglue.template_file_name('gemrc.erb'),
|
74
|
-
:destination => '/home/deploy/.gemrc',
|
75
|
-
:create_dirs => false
|
76
|
-
})
|
77
|
-
end
|
78
|
-
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Secrets < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
Pvcglue::Env.initialize_stage_env
|
10
|
+
connection.write_to_file_from_template(user_name, 'web.env.erb', Pvcglue.cloud.env_file_name, nil, nil, '0640') # TODO: Double check permissions
|
11
|
+
restart_web_app!
|
12
|
+
end
|
13
|
+
|
14
|
+
def post_install_check?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def restart_web_app!
|
19
|
+
if connection.file_exists?(user_name, Pvcglue.cloud.deploy_to_app_current_temp_dir)
|
20
|
+
connection.ssh!(user_name, '', "touch #{Pvcglue.cloud.restart_txt_file_name}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.load_for_stage
|
25
|
+
data = Pvcglue::Packages::Manager.new.load_secrets
|
26
|
+
data = '' if data.nil?
|
27
|
+
Pvcglue.cloud.stage_env = TOML.parse(data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.save_for_stage
|
31
|
+
data = TOML.dump(Pvcglue.cloud.stage_env)
|
32
|
+
Pvcglue::Packages::Manager.new.save_secrets(data)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class SshKeyCheck < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
# This has the side effect of adding the server to known_hosts file, to prevent needing interactive prompt
|
6
|
+
connection.ssh_retry_wait(:root, '-o strictHostKeyChecking=no', 'echo', 30, 1)
|
7
|
+
true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Ssl < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
return true if Pvcglue.cloud.ssl_mode == :none
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
# TODO: Support using already created certs
|
11
|
+
return true unless Pvcglue.cloud.ssl_mode == :acme
|
12
|
+
|
13
|
+
Pvcglue::Packages::SslAcme.apply(minion)
|
14
|
+
|
15
|
+
# Issue Certificate
|
16
|
+
first_domain = Pvcglue.cloud.domains.first
|
17
|
+
domains = Pvcglue.cloud.domains.map { |domain| "-d #{domain}" }
|
18
|
+
first_domain_option = domains.first
|
19
|
+
domain_options = domains.join(' ')
|
20
|
+
staging_option = Pvcglue.command_line_options[:create_test_cert] ? '--staging ' : ''
|
21
|
+
force_option = Pvcglue.command_line_options[:force_cert] ? '--force ' : ''
|
22
|
+
debug_option = Pvcglue.logger.level == 0 ? '--debug ' : ''
|
23
|
+
|
24
|
+
unless Net::HTTP.get(first_domain, '/.well-known/acme-challenge/test.html') =~ /shiny/
|
25
|
+
Pvcglue.logger.error("Unable to connect to #{first_domain} at #{minion.public_ip}")
|
26
|
+
raise(Thor::Error, 'Please fix and then restart.')
|
27
|
+
end
|
28
|
+
|
29
|
+
result = connection.ssh?(:root, '', "/root/.acme.sh/acme.sh #{debug_option}#{staging_option}#{force_option}--issue #{domain_options} -w #{Pvcglue.cloud.letsencrypt_root}")
|
30
|
+
raise result.inspect unless result.exitstatus == 0 || result.exitstatus == 2
|
31
|
+
|
32
|
+
# Install Certificate
|
33
|
+
connection.mkdir_p(:root, Pvcglue.cloud.nginx_config_ssl_path)
|
34
|
+
# acme.sh --installcert -d theos.in --keypath /etc/nginx/ssl/theos.in/theos.in.key --fullchainpath /etc/nginx/ssl/theos.in/theos.in.cer --reloadcmd 'systemctl reload nginx'
|
35
|
+
|
36
|
+
connection.ssh!(:root, '', "/root/.acme.sh/acme.sh --installcert #{first_domain_option} --keypath #{Pvcglue.cloud.nginx_ssl_key_file_name} --fullchainpath #{Pvcglue.cloud.nginx_ssl_crt_file_name} --reloadcmd 'systemctl reload nginx'")
|
37
|
+
end
|
38
|
+
|
39
|
+
def post_install_check?
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class SslAcme < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
return true if Pvcglue.cloud.ssl_mode == :none
|
6
|
+
get_minion_state(:acme_sh_updated_at)
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
# Thanks to https://www.rmedgar.com/blog/using-acme-sh-with-nginx
|
11
|
+
|
12
|
+
connection.ssh!(:root, '', 'curl https://get.acme.sh | sh')
|
13
|
+
|
14
|
+
# mkdir -p /var/www/le_root/.well-known/acme-challenge
|
15
|
+
connection.mkdir_p(:root, Pvcglue.cloud.letsencrypt_full)
|
16
|
+
#chown -R root:www-data /var/www/le_root
|
17
|
+
connection.chown(:root, Pvcglue.cloud.letsencrypt_root, 'root', 'www-data', '-R')
|
18
|
+
|
19
|
+
# Test with http://www.example.com/.well-known/acme-challenge/test.html
|
20
|
+
connection.write_to_file(:root, "Everything's shiny, Cap'n. Not to fret.", File.join(Pvcglue.cloud.letsencrypt_full, 'test.html'), 'root', 'www-data', '660')
|
21
|
+
|
22
|
+
connection.ssh!(:root, '', 'systemctl reload nginx.service')
|
23
|
+
|
24
|
+
set_minion_state(:acme_sh_updated_at, Time.now.utc)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class UnattendedUpgrades < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
get_minion_state(:installed_unattended_upgrades_at)
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
connection.write_to_file_from_template(:root, '20auto-upgrades.erb', '/etc/apt/apt.conf.d/20auto-upgrades')
|
10
|
+
connection.write_to_file_from_template(:root, '50unattended-upgrades.erb', '/etc/apt/apt.conf.d/50unattended-upgrades')
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_install_check?
|
14
|
+
connection.run!(:root, '', 'service unattended-upgrades restart')
|
15
|
+
set_minion_state(:installed_unattended_upgrades_at, Time.now.utc)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Users < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
result = connection.run_get_stdout(:root, '', "getent passwd #{user_name} && groups #{user_name}")
|
6
|
+
result =~ /^#{user_name}:/ && result =~ /#{user_name} sudo/
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
# connection.run!(:root, '', 'mkdir -p ~/.pvc && chmod 600 ~/.pvc') # TODO: Still needed?
|
11
|
+
# connection.run!(:root, '', "useradd -d /home/#{user_name} -G sudo -m -U #{user_name} && usermod -s /bin/bash #{user_name}")
|
12
|
+
|
13
|
+
connection.run!(:root, '', "useradd -d /home/#{user_name} -G sudo -m -U #{user_name}")
|
14
|
+
connection.run!(:root, '', "usermod -s /bin/bash #{user_name}")
|
15
|
+
# TODO: Lock down the sudo permissions to just let the user deploy
|
16
|
+
connection.run!(:root, '', "echo '#{user_name} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Web < Pvcglue::Packages
|
4
|
+
|
5
|
+
def installed?
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
Pvcglue::Packages::DirBase.apply(minion)
|
11
|
+
Pvcglue::Packages::DirShared.apply(minion)
|
12
|
+
Pvcglue::Packages::Rvm.apply(minion)
|
13
|
+
Pvcglue::Packages::Ruby.apply(minion)
|
14
|
+
Pvcglue::Packages::Bundler.apply(minion)
|
15
|
+
Pvcglue::Packages::Secrets.apply(minion)
|
16
|
+
connection.write_to_file_from_template(:root, 'web.nginx.conf.erb', '/etc/nginx/nginx.conf')
|
17
|
+
|
18
|
+
set_passenger_ruby # needs to be set before rendering 'web.sites-enabled.erb'
|
19
|
+
connection.write_to_file_from_template(:root, 'web.sites-enabled.erb', "/etc/nginx/sites-enabled/#{Pvcglue.cloud.app_and_stage_name}")
|
20
|
+
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def post_install_check?
|
25
|
+
result = connection.run_get_stdout(:root, '', 'service nginx restart')
|
26
|
+
if $?.exitstatus == 0
|
27
|
+
# Pvcglue.logger.debug { result }
|
28
|
+
true
|
29
|
+
else
|
30
|
+
Pvcglue.logger.error { 'Unable to (re)start nginx. Getting status...' }
|
31
|
+
result = connection.run_get_stdout(:root, '', 'systemctl status nginx.service')
|
32
|
+
puts result
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO: Ping the server as a double check.
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_passenger_ruby
|
40
|
+
info = connection.run_get_stdout!(user_name, '', "rvm use #{Pvcglue.configuration.ruby_version} && $(which passenger-config) --ruby-command")
|
41
|
+
if info =~ /passenger_ruby (.*)/
|
42
|
+
Pvcglue.cloud.passenger_ruby = $1
|
43
|
+
else
|
44
|
+
raise "'passenger_ruby' not found." unless Pvcglue.cloud.passenger_ruby
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Stack
|
3
|
+
def self.build(minions, roles_filter)
|
4
|
+
Pvcglue::Stack.new(roles_filter).run(minions)
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(roles_filter)
|
8
|
+
@roles_filter = roles_filter
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply_role?(role)
|
12
|
+
@roles_filter == 'all' || role == @roles_filter
|
13
|
+
end
|
14
|
+
|
15
|
+
def run(minions)
|
16
|
+
# puts "Configuring nodes for #{@roles_filter}."
|
17
|
+
|
18
|
+
# ap Pvcglue.configuration
|
19
|
+
# ap Pvcglue.cloud.data
|
20
|
+
# ap Pvcglue.cloud.app_name
|
21
|
+
# ap Pvcglue.cloud.project
|
22
|
+
# ap Pvcglue.cloud.project.name
|
23
|
+
# ap Pvcglue.cloud.project.stages.map { |stage| stage.to_dot.stage }
|
24
|
+
# ap Pvcglue.cloud.project.stages.map { |stage| stage.name }
|
25
|
+
# ap Pvcglue.cloud.stage
|
26
|
+
# ap Pvcglue.cloud.minions
|
27
|
+
# ap Pvcglue.cloud.minions.map { |key, value| value.roles }
|
28
|
+
# minions.each do |minion_name, minion|
|
29
|
+
# ap minion_name
|
30
|
+
# ap minion.first
|
31
|
+
# end
|
32
|
+
# ap minions['staging-pg'].private_ip
|
33
|
+
# minions['staging-pg'].private_ip = '127.0.0.1'
|
34
|
+
# ap minions['staging-pg'].private_ip
|
35
|
+
new_minions = []
|
36
|
+
minions.each do |minion_name, minion|
|
37
|
+
Pvcglue.logger_current_minion = minion
|
38
|
+
# droplet = Pvcglue::DigitalOcean.client.droplets.find(id: 38371925)
|
39
|
+
# minion.droplet = droplet
|
40
|
+
# new_minions << minion if true || minion.provision!
|
41
|
+
unless minion.provisioned?
|
42
|
+
if droplets.detect { |droplet| droplet.name == minion_name }
|
43
|
+
raise(Thor::Error, "Machine with the name of '#{minion_name}' already exists!")
|
44
|
+
end
|
45
|
+
minion.provision!
|
46
|
+
new_minions << minion
|
47
|
+
end
|
48
|
+
end
|
49
|
+
Pvcglue.logger_current_minion = nil
|
50
|
+
|
51
|
+
if new_minions.size > 0
|
52
|
+
# ap new_minions
|
53
|
+
Pvcglue.logger.info("Checking status of new minions (#{new_minions.size})...")
|
54
|
+
time = Benchmark.realtime do
|
55
|
+
begin
|
56
|
+
lazy_minions = get_lazy_minions(minions)
|
57
|
+
unless lazy_minions.size == 0
|
58
|
+
# puts '*'*175
|
59
|
+
# ap waiting_for
|
60
|
+
Pvcglue.logger.info("Waiting for #{lazy_minions.map { |key, value| key }.join(', ')}...")
|
61
|
+
sleep(1.5)
|
62
|
+
end
|
63
|
+
end until lazy_minions.size == 0
|
64
|
+
updated_minions = write_config(new_minions)
|
65
|
+
updated_minions.each do |updated_minion|
|
66
|
+
minions[updated_minion.machine_name].private_ip = updated_minion.private_ip
|
67
|
+
minions[updated_minion.machine_name].public_ip = updated_minion.public_ip
|
68
|
+
minions[updated_minion.machine_name].cloud_id = updated_minion.cloud_id
|
69
|
+
minions[updated_minion.machine_name].connection = Pvcglue::Connection.new(minions[updated_minion.machine_name])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
Pvcglue.logger.info("Minions (finally) ready after #{time.round(2)} seconds!")
|
73
|
+
# Pvcglue.cloud.reload_minions!
|
74
|
+
end
|
75
|
+
|
76
|
+
minions.each do |minion_name, minion|
|
77
|
+
next unless minion.has_role?(@roles_filter)
|
78
|
+
Pvcglue.logger_current_minion = minion
|
79
|
+
minion.build!
|
80
|
+
end
|
81
|
+
Pvcglue.logger_current_minion = nil
|
82
|
+
|
83
|
+
# raise(Thor::Error, 'STOP!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
|
84
|
+
#
|
85
|
+
# %w(lb db web caching redis).each do |role|
|
86
|
+
# if apply_role?(role)
|
87
|
+
# Pvcglue::Packages.apply(role.to_sym, :build, Pvcglue.cloud.minions_filtered(role))
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
|
91
|
+
Pvcglue::Pvcify.run unless minions.values.first.minion_manager?
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
def write_config(minions)
|
96
|
+
# TODO: Just read and write the configuration from manager without writing to `minion.cloud.local_file_name`
|
97
|
+
Pvcglue::Manager.pull_configuration
|
98
|
+
data = File.read(Pvcglue.cloud.local_file_name)
|
99
|
+
updated_minions = minions.map do |minion|
|
100
|
+
# puts '-'*175
|
101
|
+
# ap minion.droplet
|
102
|
+
# Refresh droplet (didn't find a reload method)
|
103
|
+
droplet_id = minion.droplet.id.to_s
|
104
|
+
# ap droplet_id
|
105
|
+
minion.droplet = Pvcglue::DigitalOcean.client.droplets.find(id: droplet_id)
|
106
|
+
# puts '='*175
|
107
|
+
# ap minion.droplet
|
108
|
+
ip_addresses = Pvcglue::DigitalOcean.get_ip_addresses(minion.droplet)
|
109
|
+
data = update_minion_data(minion, ip_addresses, droplet_id, data)
|
110
|
+
minion.public_ip = ip_addresses.public
|
111
|
+
minion.private_ip = ip_addresses.private
|
112
|
+
minion.cloud_id = droplet_id
|
113
|
+
minion
|
114
|
+
end
|
115
|
+
File.write(Pvcglue.cloud.local_file_name, data)
|
116
|
+
Pvcglue::Manager.push_configuration
|
117
|
+
updated_minions
|
118
|
+
end
|
119
|
+
|
120
|
+
def update_minion_data(minion, ip_addresses, cloud_id, data)
|
121
|
+
unless minion.public_ip_address.nil? && minion.private_id_address.nil? && minion.cloud_id.nil?
|
122
|
+
raise(Thor::Error, "#{minion.machine_name} has previously defined ip address(es) or cloud_id, can not change.")
|
123
|
+
end
|
124
|
+
if ip_addresses.public.nil? || ip_addresses.private.nil? || cloud_id.nil?
|
125
|
+
raise(Thor::Error, "New IP addresses (#{ip_addresses}) or cloud_id (#{cloud_id}) are not valid.")
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
replacement = "\\1\\2\n\\1public_ip = '#{ip_addresses.public}'\n\\1private_ip = '#{ip_addresses.private}'\n\\1cloud_id = '#{cloud_id}'"
|
130
|
+
new_data = data.sub(/( *)(name\s*=\s*['"]#{Regexp.quote(minion.machine_name)}['"])/, replacement)
|
131
|
+
raise "Unable to update minion data for #{minion.machine_name}." if data == new_data
|
132
|
+
|
133
|
+
# replacement = "$1$2\n$1public_ip = '#{ip_addresses.public}'\n$1private_ip = '#{ip_addresses.private}'"
|
134
|
+
# new_data = data.sub(/( *)(name\s*=\s*['"]staging-lb['"])/) do |match|
|
135
|
+
# "#{$1}#{$2}\n#{$1}public_ip = '#{ip_addresses.public}'\n#{$1}private_ip = '#{ip_addresses.private}'"
|
136
|
+
# end
|
137
|
+
# puts new_data
|
138
|
+
|
139
|
+
|
140
|
+
Pvcglue.logger.debug("Updated configuration for machine named #{minion.machine_name}.")
|
141
|
+
new_data
|
142
|
+
end
|
143
|
+
|
144
|
+
def droplets
|
145
|
+
@droplets ||= Pvcglue::DigitalOcean.client.droplets.all
|
146
|
+
end
|
147
|
+
|
148
|
+
def get_lazy_minions(minions)
|
149
|
+
droplets = Pvcglue::DigitalOcean.client.droplets.all
|
150
|
+
|
151
|
+
minions.select do |minion_name, minion|
|
152
|
+
Pvcglue.logger_current_minion = minion
|
153
|
+
# next unless minion.machine_name == 'staging-lb'
|
154
|
+
# ap minion_name
|
155
|
+
found = droplets.detect do |droplet|
|
156
|
+
droplet[:name] == minion.machine_name
|
157
|
+
end
|
158
|
+
# ap found
|
159
|
+
# ap found[:status]
|
160
|
+
!found || found[:status] != 'active'
|
161
|
+
end
|
162
|
+
# ap minions
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|