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
@@ -0,0 +1,74 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Apt < Pvcglue::Packages
|
4
|
+
WEB_WORKER_PACKAGES = %w[
|
5
|
+
build-essential
|
6
|
+
git
|
7
|
+
git-core
|
8
|
+
libpq-dev
|
9
|
+
libxml2
|
10
|
+
libxml2-dev
|
11
|
+
imagemagick
|
12
|
+
passenger
|
13
|
+
nginx
|
14
|
+
nginx-extras
|
15
|
+
nodejs
|
16
|
+
]
|
17
|
+
PACKAGES = {
|
18
|
+
common: %w[
|
19
|
+
htop
|
20
|
+
ufw
|
21
|
+
unattended-upgrades
|
22
|
+
curl
|
23
|
+
ncdu
|
24
|
+
],
|
25
|
+
manager: %w[
|
26
|
+
git
|
27
|
+
git-core
|
28
|
+
],
|
29
|
+
lb: %w[
|
30
|
+
nginx
|
31
|
+
nginx-extras
|
32
|
+
],
|
33
|
+
web: WEB_WORKER_PACKAGES,
|
34
|
+
worker: WEB_WORKER_PACKAGES,
|
35
|
+
pg: %w[
|
36
|
+
postgresql-9.6
|
37
|
+
postgresql-contrib-9.6
|
38
|
+
libpq-dev
|
39
|
+
],
|
40
|
+
mc: %w[
|
41
|
+
],
|
42
|
+
}
|
43
|
+
|
44
|
+
def installed?
|
45
|
+
false # just let apt take care of this for now
|
46
|
+
end
|
47
|
+
|
48
|
+
def install!
|
49
|
+
connection.run!(:root, '', "DEBIAN_FRONTEND=noninteractive apt install -y #{get_package_list}")
|
50
|
+
end
|
51
|
+
|
52
|
+
def post_install_check?
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_package_list
|
57
|
+
get_packages.join(' ')
|
58
|
+
end
|
59
|
+
|
60
|
+
def all_packages
|
61
|
+
@all_packages ||= PACKAGES.with_indifferent_access
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_packages
|
65
|
+
packages = all_packages[:common]
|
66
|
+
minion.roles.each do |role|
|
67
|
+
packages += all_packages[role] if all_packages[role]
|
68
|
+
end
|
69
|
+
packages
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class AptRepos < Pvcglue::Packages
|
4
|
+
PASSENGER_SOURCES_LIST_FILENAME = '/etc/apt/sources.list.d/passenger.list'
|
5
|
+
PASSENGER_SOURCES_LIST_DATA = 'deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main'
|
6
|
+
|
7
|
+
def nginx_needed?
|
8
|
+
has_roles? %w(lb web)
|
9
|
+
end
|
10
|
+
|
11
|
+
def node_js_needed?
|
12
|
+
has_roles? %w(web worker)
|
13
|
+
end
|
14
|
+
|
15
|
+
def postgresql_needed?
|
16
|
+
has_roles? %w(pg)
|
17
|
+
end
|
18
|
+
|
19
|
+
def installed?
|
20
|
+
get_minion_state(:apt_repos_updated_at)
|
21
|
+
end
|
22
|
+
|
23
|
+
def install!
|
24
|
+
# These could be refactored into packages. :)
|
25
|
+
|
26
|
+
if nginx_needed?
|
27
|
+
# Reference: https://www.phusionpassenger.com/library/install/nginx/install/oss/xenial/
|
28
|
+
connection.run!(:root, '', 'apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7')
|
29
|
+
connection.run!(:root, '', 'apt-get install -y apt-transport-https ca-certificates')
|
30
|
+
connection.write_to_file(:root, PASSENGER_SOURCES_LIST_DATA, PASSENGER_SOURCES_LIST_FILENAME)
|
31
|
+
end
|
32
|
+
|
33
|
+
if node_js_needed?
|
34
|
+
# Reference: http://tecadmin.net/install-latest-nodejs-npm-on-ubuntu/
|
35
|
+
connection.run!(:root, '', 'apt-get install -y apt-transport-https ca-certificates python-software-properties lsb-release')
|
36
|
+
connection.run!(:root, '', 'curl -sL https://deb.nodesource.com/setup_7.x | bash -')
|
37
|
+
end
|
38
|
+
|
39
|
+
if postgresql_needed?
|
40
|
+
connection.run!(:root, '', 'add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main"')
|
41
|
+
connection.run!(:root, '', 'wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -')
|
42
|
+
end
|
43
|
+
|
44
|
+
set_minion_state(:apt_repos_updated_at, Time.now.utc)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class AptUpdate < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
# TODO: Add a "force" option
|
6
|
+
updated_at = get_minion_state(:last_apt_updated_at)
|
7
|
+
return false unless updated_at
|
8
|
+
true
|
9
|
+
# updated_at > Time.now.utc - 8.hours # Unattended upgrades should take care of refreshing this automatically
|
10
|
+
end
|
11
|
+
|
12
|
+
def install!
|
13
|
+
connection.run!(:root, '', 'DEBIAN_FRONTEND=noninteractive apt-get update -y -qq')
|
14
|
+
set_minion_state(:last_apt_updated_at, Time.now.utc)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class AptUpgrade < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
# TODO: Add a "force" option
|
6
|
+
updated_at = get_minion_state(:apt_upgraded_at)
|
7
|
+
return false unless updated_at
|
8
|
+
|
9
|
+
# updated_at > Time.now.utc - 8.hours
|
10
|
+
# TODO: Give the user a warning after a period of time
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def install!
|
15
|
+
minion.connection.run!(:root, '', 'DEBIAN_FRONTEND=noninteractive apt-get upgrade -y')
|
16
|
+
set_minion_state(:apt_upgraded_at, Time.now.utc)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class AuthorizedKeys < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def post_install_check?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def install!
|
13
|
+
# TODO: Safety check to see if user is locking himself out. :)
|
14
|
+
data = minion.get_root_authorized_keys_data
|
15
|
+
if data.count == 0
|
16
|
+
raise('No authorized keys found for root users!')
|
17
|
+
# TODO: work out system for pvc-manager access
|
18
|
+
data = [`cat ~/.ssh/id_rsa.pub`.strip]
|
19
|
+
end
|
20
|
+
connection.write_to_file(:root, data.join("\n"), '/root/.ssh/authorized_keys')
|
21
|
+
|
22
|
+
connection.mkdir_p(:root, "/home/#{user_name}/.ssh", user_name, user_name, '0700')
|
23
|
+
data = minion.get_users_authorized_keys_data
|
24
|
+
if data.count == 0
|
25
|
+
raise('No authorized keys found for users!')
|
26
|
+
# TODO: work out system for pvc-manager access
|
27
|
+
data = [`cat ~/.ssh/id_rsa.pub`.strip]
|
28
|
+
end
|
29
|
+
connection.write_to_file(:root, data.join("\n"), "/home/#{user_name}/.ssh/authorized_keys", user_name, user_name, '0644')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Bundler < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
connection.run_get_stdout!(user_name, '', 'which bundler') =~ /bundler/
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
# TODO: Figure out why this isn't automatic
|
10
|
+
connection.run!(user_name, '', 'gem install bundler')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class DirBase < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
result = connection.run_get_stdout(user_name, '', "stat --format=%U:%G:%a #{Pvcglue.cloud.web_app_base_dir}").strip
|
6
|
+
result == "#{user_name}:#{user_name}:2755"
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
dir = Pvcglue.cloud.web_app_base_dir
|
11
|
+
# used following as a guide for next line: http://capistranorb.com/documentation/getting-started/authentication-and-authorisation/
|
12
|
+
connection.run!(user_name, '', "mkdir -p #{dir} && chown #{user_name}:#{user_name} #{dir} && chmod 0755 #{dir} && umask 0002 && chmod g+s #{dir}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class DirShared < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
result = connection.run_get_stdout(user_name, '', "stat --format=%U:%G:%a #{Pvcglue.cloud.deploy_to_app_shared_dir}").strip
|
6
|
+
result == "#{user_name}:#{user_name}:2755"
|
7
|
+
end
|
8
|
+
|
9
|
+
def install!
|
10
|
+
dir = Pvcglue.cloud.deploy_to_app_shared_dir
|
11
|
+
# used following as a guide for next line: http://capistranorb.com/documentation/getting-started/authentication-and-authorisation/
|
12
|
+
connection.run!(user_name, '', "mkdir -p #{dir} && chown #{user_name}:#{user_name} #{dir} && chmod 0755 #{dir} && umask 0002 && chmod g+s #{dir}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,48 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
sudo('ufw --force enable')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# TODO: add command line command for this
|
36
|
-
package 'update-firewall' do
|
37
|
-
# quick update of firewall settings only. Full bootstrap must be performed first.
|
38
|
-
depends_on 'firewall-config'
|
39
|
-
depends_on 'firewall-enabled'
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
# TODO: add command line command for this
|
44
|
-
package 'firewall-status' do
|
45
|
-
apply do
|
46
|
-
run "ufw status verbose"
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Firewall < Pvcglue::Packages
|
4
|
+
# Reference: http://manpages.ubuntu.com/manpages/xenial/en/man8/ufw-framework.8.html
|
5
|
+
# Examples: https://help.ubuntu.com/community/UFW
|
6
|
+
def installed?
|
7
|
+
result = connection.run_get_stdout!(:root, '', 'ufw status verbose')
|
8
|
+
result =~ /Status: active/ && result =~ /Default: deny \(incoming\), allow \(outgoing\)/
|
9
|
+
end
|
10
|
+
|
11
|
+
def install!
|
12
|
+
connection.run!(:root, '', 'ufw disable; ufw --force reset; ufw allow ssh; ufw --force enable')
|
13
|
+
# connection.run!(:root, '', 'ufw logging off')
|
14
|
+
connection.run!(:root, '', 'ufw logging low')
|
15
|
+
|
16
|
+
if has_role?(:lb)
|
17
|
+
connection.run!(:root, '', 'ufw allow http')
|
18
|
+
connection.run!(:root, '', 'ufw allow https')
|
19
|
+
end
|
20
|
+
|
21
|
+
unless has_role?(:manager)
|
22
|
+
minion.cloud.minions.each do |other_minion_name, other_minion|
|
23
|
+
next if other_minion_name == minion.machine_name
|
24
|
+
connection.run!(:root, '', "ufw allow from #{other_minion.private_ip}")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
47
31
|
end
|
48
32
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class LoadBalancer < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
if Pvcglue.cloud.ssl_mode == :acme && !connection.file_exists?(:root, Pvcglue.cloud.nginx_ssl_crt_file_name)
|
10
|
+
# Don't include the SSL stuff in the Nginx config until we have a cert,
|
11
|
+
# but Nginx has to be configured to get the cert from Let's Encrypt
|
12
|
+
Pvcglue.cloud.set_ssl_mode_override(:none)
|
13
|
+
end
|
14
|
+
|
15
|
+
apply_nginx_includes
|
16
|
+
apply_nginx_config
|
17
|
+
nginx_restart!
|
18
|
+
|
19
|
+
Pvcglue::Packages::Ssl.apply(minion)
|
20
|
+
|
21
|
+
if Pvcglue.cloud.ssl_mode_override
|
22
|
+
Pvcglue.cloud.set_ssl_mode_override(nil)
|
23
|
+
apply_nginx_config
|
24
|
+
nginx_restart!
|
25
|
+
end
|
26
|
+
|
27
|
+
sync_maintenance_files
|
28
|
+
end
|
29
|
+
|
30
|
+
def nginx_restart!
|
31
|
+
result = connection.run_get_stdout(:root, '', 'service nginx restart')
|
32
|
+
if $?.exitstatus == 0
|
33
|
+
# Pvcglue.logger.debug { result }
|
34
|
+
# true
|
35
|
+
else
|
36
|
+
Pvcglue.logger.error { 'Unable to (re)start nginx. Getting status...' }
|
37
|
+
result = connection.run_get_stdout(:root, '', 'systemctl status nginx.service')
|
38
|
+
puts result
|
39
|
+
raise
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def apply_nginx_includes
|
44
|
+
connection.mkdir_p(:root, '/etc/nginx/includes')
|
45
|
+
connection.write_to_file_from_template(:root, 'letsencrypt-webroot.erb', '/etc/nginx/includes/letsencrypt-webroot')
|
46
|
+
end
|
47
|
+
|
48
|
+
def apply_nginx_config
|
49
|
+
connection.write_to_file_from_template(:root, 'lb.nginx.conf.erb', '/etc/nginx/nginx.conf')
|
50
|
+
connection.write_to_file_from_template(:root, 'lb.sites-enabled.erb', "/etc/nginx/sites-enabled/#{Pvcglue.cloud.app_and_stage_name}")
|
51
|
+
end
|
52
|
+
|
53
|
+
def post_install_check?
|
54
|
+
# TODO: Ping the server as a double check.
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def sync_maintenance_files
|
59
|
+
source_dir = Pvcglue.configuration.app_maintenance_files_dir
|
60
|
+
dest_dir = Pvcglue.cloud.maintenance_files_dir
|
61
|
+
maintenance_file_name = File.join(source_dir, 'maintenance.html')
|
62
|
+
unless File.exists?(maintenance_file_name)
|
63
|
+
# TODO: Make this use a template
|
64
|
+
`mkdir -p #{source_dir}`
|
65
|
+
File.write(maintenance_file_name, '-Maintenance Mode-')
|
66
|
+
end
|
67
|
+
connection.rsync_up(user_name, '-rzv --exclude=maintenance.on --delete', source_dir, dest_dir, mkdir = true)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class MaintenanceMode < Pvcglue::Packages
|
4
|
+
def installed?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def install!
|
9
|
+
if options[:maintenance_mode] == 'on'
|
10
|
+
connection.run!(user_name, '', "touch #{Pvcglue.cloud.maintenance_mode_file_name}")
|
11
|
+
elsif options[:maintenance_mode] == 'off'
|
12
|
+
result = connection.run?(user_name, '', "rm #{Pvcglue.cloud.maintenance_mode_file_name}")
|
13
|
+
if result.exitstatus == 1
|
14
|
+
Pvcglue.logger.warn('Maintenance mode was already off.')
|
15
|
+
elsif result.exitstatus != 0
|
16
|
+
raise result.inspect
|
17
|
+
end
|
18
|
+
else
|
19
|
+
raise("Invalid maintenance_mode option: #{options[:maintenance_mode]}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def post_install_check?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,116 +1,118 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
package 'bootstrap-manager' do
|
6
|
-
# TODO: firewall and ssh port config
|
7
|
-
depends_on 'authenticate-host'
|
8
|
-
depends_on 'htop'
|
9
|
-
# depends_on 'ufw'
|
10
|
-
#depends_on 'deploy-user'
|
11
|
-
#depends_on 'sshd-config'
|
12
|
-
#depends_on 'firewall-config'
|
13
|
-
depends_on 'pvcglue-user'
|
14
|
-
depends_on 'manager-copy-id'
|
15
|
-
end
|
1
|
+
module Pvcglue
|
2
|
+
class Packages
|
3
|
+
class Manager < Pvcglue::Packages
|
16
4
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
5
|
+
def initialize(minion = nil, options = {})
|
6
|
+
minion = Pvcglue.cloud.manager_minion if minion.nil?
|
7
|
+
super
|
8
|
+
end
|
22
9
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
user_name = Pvcglue::Manager.user_name
|
27
|
-
home_dir = Pvcglue::Manager.home_dir
|
28
|
-
manager_dir = Pvcglue::Manager.manager_dir
|
29
|
-
ssh_dir = Pvcglue::Manager.ssh_dir
|
30
|
-
|
31
|
-
sudo "useradd -d #{home_dir} -m -U #{user_name}"
|
32
|
-
sudo "usermod -s /bin/bash #{user_name}"
|
33
|
-
sudo "mkdir -p #{manager_dir} && chown #{user_name}:#{user_name} #{manager_dir} && chmod 700 #{manager_dir}"
|
34
|
-
sudo "mkdir -p #{ssh_dir} && chown #{user_name}:#{user_name} #{ssh_dir} && chmod 700 #{ssh_dir}"
|
35
|
-
end
|
10
|
+
def installed?
|
11
|
+
get_minion_state(:manager_installed_at)
|
12
|
+
end
|
36
13
|
|
37
|
-
|
38
|
-
|
39
|
-
# user_name = Pvcglue::Manager.user_name
|
40
|
-
# home_dir = Pvcglue::Manager.home_dir
|
41
|
-
#sudo "userdel -f #{user_name}"
|
42
|
-
#sudo "rm -rf #{home_dir}"
|
43
|
-
end
|
14
|
+
def install!
|
15
|
+
connection.mkdir_p(user_name, manager_dir, nil, nil, 700)
|
44
16
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#sudo "userdel -f #{user_name}"; sudo "rm -rf #{home_dir}"; raise "User has been deleted"
|
49
|
-
sudo("getent passwd #{user_name}") =~ /^#{user_name}:/
|
50
|
-
end
|
51
|
-
end
|
17
|
+
connection.ssh!(user_name, '', 'git config --global user.name pvc_manager')
|
18
|
+
connection.ssh!(user_name, '', 'git config --global --global user.email pvc_manager@pvc.local')
|
19
|
+
connection.ssh!(user_name, '', "git init #{Pvcglue::Manager.manager_dir}")
|
52
20
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
auth.include?(user_key)
|
59
|
-
end
|
21
|
+
# TODO: Create example configuration file, if none exists
|
22
|
+
connection.write_to_file(user_name, "#{Time.now.utc.to_s}\n", manager_test_filename)
|
23
|
+
connection.ssh!(user_name, '', %Q(cd #{manager_dir} && git status))
|
24
|
+
git_commit!
|
25
|
+
connection.ssh!(user_name, '', %Q(cd #{manager_dir} && git status))
|
60
26
|
|
61
|
-
|
62
|
-
|
63
|
-
user_name = Pvcglue::Manager.user_name
|
64
|
-
copy_id = %Q[cat ~/.ssh/id_rsa.pub | ssh -o BatchMode=yes -o StrictHostKeyChecking=no #{node.get(:user)}@#{node.host} "cat >> #{authorized_keys_file_name}"]
|
65
|
-
system "#{copy_id}"
|
66
|
-
run(%Q[cat "" >> #{authorized_keys_file_name}])
|
67
|
-
sudo "chown #{user_name}:#{user_name} #{authorized_keys_file_name} && chmod 600 #{authorized_keys_file_name}"
|
68
|
-
end
|
69
|
-
end
|
27
|
+
# https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History
|
28
|
+
connection.ssh!(user_name, '', %Q(cd #{manager_dir} && git log --pretty=format:"%h - %an, %ar : %s" && echo))
|
70
29
|
|
71
|
-
|
72
|
-
|
73
|
-
if File.exists?(::Pvcglue.cloud.local_file_name)
|
74
|
-
# scp foobar.txt your_username@remotehost.edu:/some/remote/directory
|
75
|
-
cmd = %{scp #{::Pvcglue.cloud.local_file_name} #{node.get(:user)}@#{node.host}:#{::Pvcglue::Manager.manager_file_name}}
|
76
|
-
puts "Running `#{cmd}`"
|
30
|
+
set_minion_state(:manager_installed_at, Time.now.utc)
|
31
|
+
end
|
77
32
|
|
78
|
-
|
79
|
-
|
33
|
+
def post_install_check?
|
34
|
+
return false unless connection.file_exists?(user_name, manager_dir)
|
35
|
+
return false unless working_directory_clean?
|
36
|
+
connection.file_exists?(user_name, manager_test_filename)
|
80
37
|
end
|
81
38
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
39
|
+
def manager_dir
|
40
|
+
Pvcglue::Manager.manager_dir
|
41
|
+
end
|
88
42
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
cmd = %{scp #{node.get(:user)}@#{node.host}:#{::Pvcglue::Manager.manager_file_name} #{::Pvcglue.cloud.local_file_name}}
|
93
|
-
puts "Running `#{cmd}`"
|
43
|
+
def manager_test_filename
|
44
|
+
File.join(manager_dir, 'install.log')
|
45
|
+
end
|
94
46
|
|
95
|
-
|
96
|
-
|
97
|
-
|
47
|
+
def self.get_configuration
|
48
|
+
new.get_configuration
|
49
|
+
end
|
98
50
|
|
99
|
-
|
100
|
-
|
101
|
-
|
51
|
+
def get_configuration
|
52
|
+
# if connection.file_exists?(user_name, ::Pvcglue::Manager.manager_file_name)
|
53
|
+
# data = connection.read_from_file(user_name, ::Pvcglue::Manager.manager_file_name)
|
54
|
+
# else
|
55
|
+
# # raise(Thor::Error, "Remote manager file not found: #{::Pvcglue::Manager.manager_file_name}")
|
56
|
+
# raise("Remote manager file not found: #{::Pvcglue::Manager.manager_file_name}")
|
57
|
+
# end
|
58
|
+
data = '' # to use `data` in block
|
59
|
+
Pvcglue.filter_verbose do
|
60
|
+
data = connection.read_from_file(user_name, ::Pvcglue::Manager.manager_file_name)
|
61
|
+
end
|
62
|
+
::Pvcglue.cloud.data = TOML.parse(data)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.push_configuration
|
66
|
+
new.push_configuration
|
67
|
+
end
|
68
|
+
|
69
|
+
def push_configuration
|
70
|
+
connection.upload_file(user_name, ::Pvcglue.cloud.local_file_name, ::Pvcglue::Manager.manager_file_name, nil, nil, '600')
|
71
|
+
git_commit!
|
72
|
+
raise('Error saving configuration') unless working_directory_clean?
|
73
|
+
# TODO: Turn delete back on
|
74
|
+
# File.delete(::Pvcglue.cloud.local_file_name)
|
75
|
+
end
|
76
|
+
|
77
|
+
def git_commit!
|
78
|
+
connection.ssh!(user_name, '', %Q(cd #{manager_dir} && git add -A && git commit --allow-empty --author="pvc-$PVCGLUE_USER <>" -m "Change configuration"))
|
79
|
+
end
|
80
|
+
|
81
|
+
def working_directory_clean?
|
82
|
+
connection.run_get_stdout!(user_name, '', %Q(cd #{manager_dir} && git status)) =~ /working directory clean/
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.pull_configuration
|
86
|
+
new.pull_configuration
|
87
|
+
# new(Pvcglue.cloud.manager_minion).pull_configuration
|
88
|
+
end
|
89
|
+
|
90
|
+
def pull_configuration
|
91
|
+
# TODO: Rename to edit_config_start, and create Thor commands to match
|
92
|
+
if connection.file_exists?(user_name, ::Pvcglue::Manager.manager_file_name)
|
93
|
+
data = connection.read_from_file(user_name, ::Pvcglue::Manager.manager_file_name)
|
94
|
+
else
|
95
|
+
data = "# Pvcglue manager configuration file\n\n"
|
96
|
+
end
|
97
|
+
file_name = ::Pvcglue.cloud.local_file_name
|
98
|
+
if File.exist?(file_name)
|
99
|
+
backup_file_name = ::Pvcglue.configuration.versioned_filename(file_name)
|
100
|
+
File.rename(file_name, backup_file_name)
|
101
|
+
Pvcglue.logger.info("Existing local configuration file saved to #{backup_file_name}")
|
102
|
+
end
|
103
|
+
File.write(file_name, data)
|
104
|
+
puts "Configuration saved to #{file_name}. Now edit it and push it back up."
|
105
|
+
end
|
106
|
+
|
107
|
+
def load_secrets
|
108
|
+
connection.read_from_file_if_exists?(user_name, ::Pvcglue::Env.stage_env_file_name)
|
109
|
+
end
|
110
|
+
|
111
|
+
def save_secrets(data)
|
112
|
+
connection.write_to_file(user_name, data, ::Pvcglue::Env.stage_env_file_name, nil, nil, 600)
|
113
|
+
git_commit!
|
114
|
+
end
|
102
115
|
|
103
|
-
package 'manager-get-config' do
|
104
|
-
apply do
|
105
|
-
data = run("cat #{::Pvcglue::Manager.manager_file_name}")
|
106
|
-
#puts "*"*80
|
107
|
-
#puts data
|
108
|
-
#puts "*"*80
|
109
|
-
if data.empty?
|
110
|
-
raise "Remote manager file not found: #{::Pvcglue::Manager.manager_file_name}"
|
111
|
-
else
|
112
|
-
::Pvcglue.cloud.data = TOML.parse(data)
|
113
116
|
end
|
114
117
|
end
|
115
118
|
end
|
116
|
-
|