pvcglue 0.1.39 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/README.md +12 -3
  5. data/bin/pvc +4 -2
  6. data/lib/pvcglue.rb +106 -21
  7. data/lib/pvcglue/bootstrap.rb +1 -1
  8. data/lib/pvcglue/cli.rb +28 -17
  9. data/lib/pvcglue/cloud.rb +243 -56
  10. data/lib/pvcglue/configuration.rb +43 -5
  11. data/lib/pvcglue/connection.rb +236 -0
  12. data/lib/pvcglue/custom_hashie.rb +3 -0
  13. data/lib/pvcglue/db.rb +19 -13
  14. data/lib/pvcglue/digital_ocean.rb +21 -0
  15. data/lib/pvcglue/env.rb +52 -28
  16. data/lib/pvcglue/manager.rb +38 -25
  17. data/lib/pvcglue/minion.rb +182 -0
  18. data/lib/pvcglue/nodes.rb +1 -1
  19. data/lib/pvcglue/{packages → old_packages}/bootstrap.rb +15 -15
  20. data/lib/pvcglue/{packages → old_packages}/env.rb +8 -8
  21. data/lib/pvcglue/old_packages/firewall.rb +48 -0
  22. data/lib/pvcglue/old_packages/manager.rb +116 -0
  23. data/lib/pvcglue/{packages → old_packages}/monit-bootstrap.rb +0 -0
  24. data/lib/pvcglue/{packages → old_packages}/monit-web.rb +0 -0
  25. data/lib/pvcglue/{packages → old_packages}/nginx.rb +0 -0
  26. data/lib/pvcglue/{packages → old_packages}/nodejs.rb +0 -0
  27. data/lib/pvcglue/{packages → old_packages}/passenger.rb +0 -0
  28. data/lib/pvcglue/old_packages/postgresql.rb +10 -0
  29. data/lib/pvcglue/{packages → old_packages}/role_db.rb +9 -9
  30. data/lib/pvcglue/{packages → old_packages}/role_lb.rb +6 -6
  31. data/lib/pvcglue/{packages → old_packages}/role_memcached.rb +0 -0
  32. data/lib/pvcglue/{packages → old_packages}/role_redis.rb +0 -0
  33. data/lib/pvcglue/{packages → old_packages}/role_web.rb +9 -9
  34. data/lib/pvcglue/old_packages/rvm.rb +78 -0
  35. data/lib/pvcglue/{packages → old_packages}/timezone.rb +0 -0
  36. data/lib/pvcglue/{packages → old_packages}/ubuntu.rb +0 -0
  37. data/lib/pvcglue/packages.rb +192 -71
  38. data/lib/pvcglue/packages/apt.rb +74 -0
  39. data/lib/pvcglue/packages/apt_repos.rb +48 -0
  40. data/lib/pvcglue/packages/apt_update.rb +18 -0
  41. data/lib/pvcglue/packages/apt_upgrade.rb +20 -0
  42. data/lib/pvcglue/packages/authorized_keys.rb +33 -0
  43. data/lib/pvcglue/packages/bundler.rb +14 -0
  44. data/lib/pvcglue/packages/dir_base.rb +16 -0
  45. data/lib/pvcglue/packages/dir_shared.rb +16 -0
  46. data/lib/pvcglue/packages/firewall.rb +30 -46
  47. data/lib/pvcglue/packages/load_balancer.rb +71 -0
  48. data/lib/pvcglue/packages/maintenance_mode.rb +28 -0
  49. data/lib/pvcglue/packages/manager.rb +101 -99
  50. data/lib/pvcglue/packages/postgresql.rb +36 -8
  51. data/lib/pvcglue/packages/roles.rb +23 -0
  52. data/lib/pvcglue/packages/ruby.rb +13 -0
  53. data/lib/pvcglue/packages/rvm.rb +18 -71
  54. data/lib/pvcglue/packages/secrets.rb +36 -0
  55. data/lib/pvcglue/packages/ssh_key_check.rb +11 -0
  56. data/lib/pvcglue/packages/ssl.rb +45 -0
  57. data/lib/pvcglue/packages/ssl_acme.rb +29 -0
  58. data/lib/pvcglue/packages/swap.rb +14 -0
  59. data/lib/pvcglue/packages/unattended_upgrades.rb +20 -0
  60. data/lib/pvcglue/packages/users.rb +20 -0
  61. data/lib/pvcglue/packages/web.rb +50 -0
  62. data/lib/pvcglue/stack.rb +166 -0
  63. data/lib/pvcglue/templates/50unattended-upgrades.erb +63 -0
  64. data/lib/pvcglue/templates/capfile.erb +4 -1
  65. data/lib/pvcglue/templates/deploy.rb.erb +3 -2
  66. data/lib/pvcglue/templates/lb.sites-enabled.erb +15 -9
  67. data/lib/pvcglue/templates/letsencrypt-webroot.erb +3 -0
  68. data/lib/pvcglue/templates/pg_hba.conf.erb +1 -2
  69. data/lib/pvcglue/templates/postgresql.conf.erb +376 -291
  70. data/lib/pvcglue/templates/stage-deploy.rb.erb +2 -2
  71. data/lib/pvcglue/templates/web.bashrc.erb +16 -5
  72. data/lib/pvcglue/templates/web.nginx.conf.erb +1 -1
  73. data/lib/pvcglue/templates/web.sites-enabled.erb +1 -1
  74. data/lib/pvcglue/version.rb +1 -1
  75. data/pvcglue.gemspec +17 -12
  76. metadata +125 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 463623f85adf15ee50e8f2c2425482c2c751f30b
4
- data.tar.gz: fa759839920a81f2357b43311ead1622ff72ea5c
3
+ metadata.gz: 29094a42e1588de62c31f9259be0bc1d0f9d4c91
4
+ data.tar.gz: cc6c3e188893749c8082f821c751992168d1e02e
5
5
  SHA512:
6
- metadata.gz: c087b1c4ada832eae9d5cd1b4c4ca004b60269e6b08c8a917c7e1a9aa9996ef7020b64f8153edc38d8ea56061fbe707982f990970332bf5bc8f27b26f10c809b
7
- data.tar.gz: 103ab848521a649ccb76a42336d73c1ad71f3eaefeb2f2d5db0b0819bf0c45d655ff4ce0ba13595af9d3e8b7e53e961587dbaa186845a96ae3877f8b370c5e1e
6
+ metadata.gz: 7a87fabdd8819a42e894eaa53253f76585fadeb29edf55989e9e34df16ce720caed49205a425bdda95256b122b5a3cc8624db86cee24906cc95a0eb9950ded82
7
+ data.tar.gz: 2add0cab736ec4a2c00aef8e29717a7f3c603f4764f39ef2a3d40353557ec26675cb0bfef8aa722083666c8916d43725b0ea7a62517da824224e7e93b6a547d8
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ pvcglue
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.4.0
data/README.md CHANGED
@@ -14,14 +14,23 @@ An opinionated cloud application manager for Rails applications using your own s
14
14
 
15
15
  Currently supported stack:
16
16
 
17
- * Ubuntu 12.04 (with plans for supporting 14.04)
17
+ * SSL support: none, manual and automatic with Let's Encrypt
18
+ * Ubuntu 16.04 LTS
19
+ * Provision servers automatically on Digital Ocean (and Linode)
20
+ * No need to install anything on servers first (you just need SSH access)
18
21
  * Ruby >= 1.9 (multiple versions supported on same server)
19
22
  * Rails >= 3.2
20
23
  * RVM
21
- * Postgresql 9.1
24
+ * Postgresql 9.6
22
25
  * Nginx
23
- * Passenger > 4.0
26
+ * Passenger > 5.0
24
27
  * Memcached
28
+ * Redis
29
+
30
+ Workers:
31
+
32
+ * Delayed Job
33
+ * Rescue
25
34
 
26
35
  # This is a work in progress
27
36
 
data/bin/pvc CHANGED
@@ -9,6 +9,8 @@ if ARGV.count >= 2 && %w[local vmtest test alpha beta gamma delta preview produc
9
9
  ARGV[0], ARGV[1] = ARGV[1], "--stage=#{ARGV[0]}"
10
10
  end
11
11
 
12
- # puts ARGV.inspect
12
+ Pvcglue.logger.info('Starting up...')
13
+ Pvcglue.logger.debug { ARGV.inspect }
13
14
  # puts Benchmark.measure { Pvcglue::CLI.start }
14
- puts "----- Done #{Benchmark.measure { Pvcglue::CLI.start }}"
15
+ # pvc_puts.warn("----- Done #{Benchmark.measure { Pvcglue::CLI.start }}")
16
+ Pvcglue.logger.info("----- Done #{Benchmark.measure { Pvcglue::CLI.start }}")
data/lib/pvcglue.rb CHANGED
@@ -1,29 +1,114 @@
1
- require "pvcglue/version"
2
- require "thor"
3
- require "pvcglue/configuration"
4
- require "pvcglue/manager"
5
- require "pvcglue/cloud"
6
- require "pvcglue/packages"
7
- require "pvcglue/bootstrap"
8
- require "pvcglue/nodes"
9
- require "pvcglue/env"
10
- require "pvcglue/deploy"
11
- require "pvcglue/capistrano"
12
- require "pvcglue/ssl"
13
- require "pvcglue/db"
14
- require "pvcglue/toml_pvc_dumper"
15
- require "pvcglue/local"
16
- require "pvcglue/monit"
17
- require "pvcglue/pvcify"
18
- require "tilt"
1
+ require 'pvcglue/version'
2
+ require 'thor'
3
+ require 'pvcglue/configuration'
4
+ require 'pvcglue/manager'
5
+ require 'pvcglue/cloud'
6
+ require 'pvcglue/packages'
7
+ Dir[File.dirname(__FILE__) + '/pvcglue/packages/*.rb'].each { |file| require file }
8
+ require 'pvcglue/bootstrap'
9
+ require 'pvcglue/nodes'
10
+ require 'pvcglue/stack'
11
+ require 'pvcglue/env'
12
+ require 'pvcglue/deploy'
13
+ require 'pvcglue/capistrano'
14
+ require 'pvcglue/ssl'
15
+ require 'pvcglue/db'
16
+ require 'pvcglue/toml_pvc_dumper'
17
+ require 'pvcglue/local'
18
+ require 'pvcglue/monit'
19
+ require 'pvcglue/pvcify'
20
+ require 'tilt'
21
+ require 'awesome_print'
22
+ require 'hashie'
23
+ require 'pvcglue/custom_hashie'
24
+ require 'pvcglue/minion'
25
+ require 'droplet_kit'
26
+ require 'pvcglue/digital_ocean'
27
+ require 'logger'
28
+ require 'pvcglue/connection'
29
+ require 'paint'
30
+ require 'pry'
19
31
 
20
32
  # puts File.join(File.dirname(__FILE__), 'pvcglue', 'packages', '*.rb')
33
+ # pvc manager bootstrap --cloud_manager_override=local_cloud.pvcglue.toml --save_before_upload=save --verbose
21
34
 
22
35
  module Pvcglue
23
36
  mattr_accessor :command_line_options do
24
37
  {}
25
38
  end
26
39
 
40
+ mattr_accessor :logger do
41
+
42
+ logger = Logger.new(STDOUT)
43
+ # logger.level = Logger::INFO # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
44
+ logger.level = Logger::DEBUG # DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
45
+ # logger.warn('Starting up...')
46
+ logger.formatter = proc do |severity, datetime, progname, msg|
47
+ minion_name = Pvcglue.logger_current_minion.try(:machine_name)
48
+ minion_name = "/#{minion_name}" if minion_name
49
+ description = Pvcglue.logger_package_description
50
+ if description
51
+ description = description.split('::').last || description
52
+ description = "/#{description.downcase}"
53
+ end
54
+ foreground = nil
55
+ # background = 'black'
56
+ background = nil
57
+ case severity[0..0]
58
+ when 'E'
59
+ foreground = 'red'
60
+ when 'W'
61
+ # foreground = 'black'
62
+ # background = 'yellow'
63
+ foreground = 'yellow'
64
+ when 'I'
65
+ foreground = 'purple'
66
+ when 'D'
67
+ foreground = 'cyan'
68
+ else
69
+ foreground = 'black'
70
+ background = 'red'
71
+ end
72
+ # case severity[0..0]
73
+ # when 'E'
74
+ # color = :redish
75
+ # when 'W'
76
+ # color = :yellowish
77
+ # when 'I'
78
+ # color = :purpleish
79
+ # when 'D'
80
+ # color = :cyanish
81
+ # else
82
+ # color = :yellowish
83
+ # end
84
+ # "#{severity[0..0]} [#{datetime.strftime('%H:%M:%S')}#{minion_name}#{description}] #{msg}\n".send(color)
85
+ Paint["#{severity[0..0]} [#{datetime.strftime('%H:%M:%S')}#{minion_name}#{description}] #{msg}\n", foreground, background]
86
+ end
87
+ logger
88
+ end
89
+ mattr_accessor :logger_package_description
90
+ mattr_accessor :logger_current_minion
91
+
92
+ def self.verbose?
93
+ return if @filtering_verbose
94
+ if Pvcglue.command_line_options[:verbose]
95
+ puts yield
96
+ end
97
+ end
98
+
99
+ def self.filter_verbose
100
+ @filtering_verbose = true
101
+ begin
102
+ yield
103
+ ensure
104
+ @filtering_verbose = false
105
+ end
106
+ end
107
+
108
+ def self.reset_minion_state?
109
+ !!Pvcglue.command_line_options[:rebuild]
110
+ end
111
+
27
112
  def self.gem_dir
28
113
  Gem::Specification.find_by_name('pvcglue').gem_dir
29
114
  end
@@ -33,8 +118,8 @@ module Pvcglue
33
118
  end
34
119
 
35
120
  def self.render_template(template, file_name = nil)
36
- puts '-'*80
37
- puts "---> render_template(template=#{template}, file_name=#{file_name}"
121
+ # puts '-'*80
122
+ # puts "---> render_template(template=#{template}, file_name=#{file_name}"
38
123
  data = Tilt.new(Pvcglue.template_file_name(template)).render
39
124
  if file_name
40
125
  File.write(file_name, data)
@@ -47,7 +132,7 @@ module Pvcglue
47
132
  # puts "Running `#{cmd}`"
48
133
 
49
134
  unless system cmd
50
- raise(Thor::Error, "Error: #{$?}")
135
+ raise("Error: #{$?}")
51
136
  end
52
137
  true
53
138
  end
@@ -2,7 +2,7 @@ module Pvcglue
2
2
  class Bootstrap
3
3
  def self.run(roles)
4
4
  # puts "This is where it should bootstrap #{Pvcglue.cloud.stage_name}. :)"
5
- Pvcglue::Packages.apply('bootstrap'.to_sym, :bootstrap, Pvcglue.cloud.nodes_in_stage(roles), 'root')
5
+ Pvcglue::Packages.apply('bootstrap'.to_sym, :bootstrap, Pvcglue.cloud.minions_filtered(roles), 'root')
6
6
  end
7
7
  end
8
8
  end
data/lib/pvcglue/cli.rb CHANGED
@@ -6,6 +6,11 @@ module Pvcglue
6
6
 
7
7
  class CLI < Thor
8
8
  class_option :cloud_manager_override
9
+ class_option :verbose
10
+ class_option :rebuild
11
+ class_option :save_before_upload
12
+ class_option :create_test_cert
13
+ class_option :force_cert
9
14
 
10
15
  def initialize(args = [], local_options = {}, config = {})
11
16
  super
@@ -48,22 +53,23 @@ module Pvcglue
48
53
  method_option :stage, :required => true, :aliases => "-s"
49
54
 
50
55
  def build(roles = 'all')
51
- Pvcglue::Nodes.build(roles)
56
+ Pvcglue::Stack.build(Pvcglue.cloud.minions, roles)
52
57
  end
53
58
 
54
59
  desc "console", "open rails console"
55
60
  method_option :stage, :required => true, :aliases => "-s"
56
61
 
57
62
  def console(server='web')
58
- node = Pvcglue.cloud.find_node(server)
59
- node_name = node.keys.first
60
- node_data = node.values.first
61
- # puts "*"*80
62
- # puts node.inspect
63
- puts "Connection to #{node_name} (#{node_data[:public_ip]}) as user 'deploy'..."
63
+ data = Pvcglue.cloud.minions_filtered(server)
64
+ minion_name = data.keys.first
65
+ minion = data.values.first
64
66
  working_dir = Pvcglue.cloud.deploy_to_app_current_dir
65
- system(%(ssh -t deploy@#{node_data[:public_ip]} "cd #{working_dir} && echo 'Starting #{options[:stage].upcase} Rails console in #{working_dir}' && bundle exec rails c #{options[:stage].downcase}"))
67
+ Pvcglue.logger.warn("Opening Rails console on #{minion_name} (#{minion.public_ip}) as user '#{minion.remote_user_name}'...")
68
+ Pvcglue.logger.debug("Project root: #{working_dir}")
66
69
 
70
+ cmd = "cd #{working_dir} && bundle exec rails c #{options[:stage].downcase}"
71
+ # system(%(ssh -t deploy@#{node_data[:public_ip]} "cd #{working_dir} && echo 'Starting #{options[:stage].upcase} Rails console in #{working_dir}' && bundle exec rails c #{options[:stage].downcase}"))
72
+ minion.connection.ssh!(minion.remote_user_name, '-t', cmd)
67
73
  end
68
74
 
69
75
  desc "c", "shortcut for console"
@@ -96,8 +102,11 @@ module Pvcglue
96
102
 
97
103
  def maintenance(mode)
98
104
  raise(Thor::Error, "invalid maintenance mode :( (Hint: try on or off.)") unless mode.in?(%w(on off))
99
- Pvcglue.cloud.maintenance_mode = mode
100
- Pvcglue::Packages.apply(:maintenance_mode, :maintenance, Pvcglue.cloud.nodes_in_stage('lb'))
105
+ # Pvcglue.cloud.maintenance_mode = mode
106
+ # Pvcglue::Packages.apply(:maintenance_mode, :maintenance, Pvcglue.cloud.nodes_in_stage('lb'))
107
+ Pvcglue.cloud.minions_filtered('lb').each do |minioin_name, minion|
108
+ Pvcglue::Packages::MaintenanceMode.apply(minion, {maintenance_mode: mode})
109
+ end
101
110
  end
102
111
 
103
112
  desc "maint", "enable or disable maintenance mode"
@@ -120,7 +129,7 @@ module Pvcglue
120
129
  def bypass(mode)
121
130
  raise(Thor::Error, "invalid maintenance bypass mode :( (Hint: try on or off.)") unless mode.in?(%w(on off))
122
131
  Pvcglue.cloud.bypass_mode = mode
123
- Pvcglue::Packages.apply(:bypass_mode, :maintenance, Pvcglue.cloud.nodes_in_stage('lb'))
132
+ Pvcglue::Packages.apply(:bypass_mode, :maintenance, Pvcglue.cloud.minions_filtered('lb'))
124
133
  end
125
134
 
126
135
  desc "b", "enable or disable maintenance mode bypass for developers"
@@ -135,13 +144,15 @@ module Pvcglue
135
144
  method_option :stage, :required => true, :aliases => "-s"
136
145
 
137
146
  def sh(server='web') # `shell` is a Thor reserved word
138
- node = Pvcglue.cloud.find_node(server)
139
- node_name = node.keys.first
140
- node_data = node.values.first
147
+ data = Pvcglue.cloud.minions_filtered(server)
148
+ minion_name = data.keys.first
149
+ minion = data.values.first
141
150
  # puts "*"*80
142
151
  # puts node.inspect
143
- puts "Connection to #{node_name} (#{node_data[:public_ip]}) as user 'deploy'..."
144
- system("ssh -p #{Pvcglue.cloud.port_in_context(:shell)} deploy@#{node_data[:public_ip]}")
152
+ Pvcglue.logger.warn("Connecting to #{minion_name} (#{minion.public_ip}) as user '#{minion.remote_user_name}'...")
153
+ # puts "Connection to #{minion_name} (#{minion.public_ip}) as user '#{minion.remote_user_name}'..."
154
+ # system("ssh -p #{Pvcglue.cloud.port_in_context(:shell)} #{minion.remote_user_name}@#{minion[:public_ip]}")
155
+ minion.connection.ssh!(minion.remote_user_name, '', '')
145
156
  end
146
157
 
147
158
  desc "s", "shell"
@@ -163,7 +174,7 @@ module Pvcglue
163
174
 
164
175
  def rake(*tasks)
165
176
  if Pvcglue.cloud.stage_name == 'production'
166
- # if Pvcglue.cloud.stage_name == 'local'
177
+ # if Pvcglue.cloud.stage_name == 'local'
167
178
  raise(Thor::Error, "\nDidn't think so!\n") unless yes?("\n\nStop! Think! Are you sure you want to do this on the #{Pvcglue.cloud.stage_name} stage? (y/N)")
168
179
  end
169
180
  Pvcglue::Capistrano.rake(tasks)
data/lib/pvcglue/cloud.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require "active_support"
2
2
  require "active_support/core_ext" # for `with_indifferent_access`
3
3
 
4
-
5
4
  module Pvcglue
6
5
  class Cloud
7
6
  attr_accessor :data
@@ -12,6 +11,7 @@ module Pvcglue
12
11
  attr_accessor :stage_env
13
12
  attr_accessor :passenger_ruby
14
13
  attr_accessor :port_in_node_context
14
+ # attr_accessor :stage_secrets
15
15
 
16
16
  def data
17
17
  ::Pvcglue::Manager.initialize_cloud_data unless @data
@@ -19,7 +19,10 @@ module Pvcglue
19
19
  end
20
20
 
21
21
  def data=(data)
22
- @data = data.with_indifferent_access # We may not want this dependency.
22
+ # @data = data.with_indifferent_access # We may not want this dependency.
23
+ # @data = data.to_dot # We may not want this dependency.
24
+ # @data = Hashie::Mash.new(data) # We may not want this dependency.
25
+ @data = ::SafeMash.new(data)
23
26
  end
24
27
 
25
28
  def current_node
@@ -57,11 +60,11 @@ module Pvcglue
57
60
  @stage_name
58
61
  end
59
62
 
60
- def stage
61
- # puts data[app_name].inspect
62
- # puts data[app_name][:stages].inspect
63
- # puts data[app_name][:stages][stage_name].inspect
64
- data[app_name][:stages][stage_name]
63
+ def old_stage
64
+ # puts project.inspect
65
+ # puts project[:stages].inspect
66
+ # puts project[:stages][stage_name].inspect
67
+ project[:stages][stage_name]
65
68
  end
66
69
 
67
70
  def stage_roles
@@ -83,39 +86,56 @@ module Pvcglue
83
86
  end
84
87
 
85
88
  # find node by full node_name or by matching prefix of node_name
86
- def find_node(node_name, raise_error = true)
87
- puts "*"*80
88
- raise(Thor::Error, "Node not specified.") if node_name.nil? || node_name.empty?
89
- return {node_name => nodes_in_stage[node_name]} if nodes_in_stage[node_name]
90
- puts "-"*80
91
- nodes_in_stage.each do |key, value|
92
- puts key
93
- return {key => value} if key.start_with?(node_name)
89
+ def find_minion_by_name(minion_name, raise_error = true)
90
+ # raise(Thor::Error, "Node not specified.") if node_name.nil? || node_name.empty?
91
+ raise('Minion not specified.') if minion_name.nil? || minion_name.empty?
92
+ return {minion_name => minions_filtered[minion_name]} if minions[minion_name]
93
+ minions.each do |key, value|
94
+ return {key => value} if key.start_with?(minion_name)
94
95
  end
95
- raise("Not found: #{node_name} in #{stage_name}.") if raise_error
96
+ raise("Not found: #{minion_name} in #{stage_name}.") if raise_error
96
97
  # raise(Thor::Error, "Not found: #{node_name} in #{stage_name}.")
97
- end
98
-
99
- def nodes_in_stage(role_filter = 'all')
100
- # puts (stage_roles.values.each_with_object({}) { |node, nodes| nodes.merge!(node) }).inspect
101
- # stage_roles.values.each_with_object({}) { |node, nodes| nodes.merge!(node) }
102
- nodes = stage_roles.each_with_object({}) do |(role, node), nodes|
103
- if role_filter == 'all' || role == role_filter
104
- nodes.merge!(node)
105
- end
98
+ nil
99
+ end
100
+
101
+ # # find node by full node_name or by matching prefix of node_name
102
+ # def find_node(node_name, raise_error = true)
103
+ # # raise(Thor::Error, "Node not specified.") if node_name.nil? || node_name.empty?
104
+ # raise('Node not specified.') if node_name.nil? || node_name.empty?
105
+ # return {node_name => nodes_in_stage[node_name]} if nodes_in_stage[node_name]
106
+ # nodes_in_stage.each do |key, value|
107
+ # return {key => value} if key.start_with?(node_name)
108
+ # end
109
+ # raise("Not found: #{node_name} in #{stage_name}.") if raise_error
110
+ # # raise(Thor::Error, "Not found: #{node_name} in #{stage_name}.")
111
+ # end
112
+ #
113
+ def minions_filtered(role_filter = 'all')
114
+ # # puts (stage_roles.values.each_with_object({}) { |node, nodes| nodes.merge!(node) }).inspect
115
+ # # stage_roles.values.each_with_object({}) { |node, nodes| nodes.merge!(node) }
116
+ # nodes = stage_roles.each_with_object({}) do |(role, node), nodes|
117
+ # if role_filter == 'all' || role == role_filter
118
+ # nodes.merge!(node)
119
+ # end
120
+ # end
121
+ # # puts nodes.inspect
122
+ # # puts "nodes_in_stage: only first returned"+"!*"*80
123
+ # # out = {}
124
+ # # out["memcached"] = nodes["memcached"]
125
+ # # puts out.inspect
126
+ # # out
127
+ if role_filter == 'all'
128
+ minions
129
+ else
130
+ minions.select { |minion_name, minion| minion.has_role?(role_filter) }
106
131
  end
107
- # puts nodes.inspect
108
- # puts "nodes_in_stage: only first returned"+"!*"*80
109
- # out = {}
110
- # out["memcached"] = nodes["memcached"]
111
- # puts out.inspect
112
- # out
132
+
113
133
  end
114
134
 
115
135
  # ENV['PVC_DEPLOY_TO_BASE'] = stage_data[:deploy_to] || '/sites'
116
136
  def deploy_to_base_dir
117
137
  # stage[:deploy_to] || '/sites' # TODO: verify if server setup supports `:deploy_to` override
118
- Pvcglue.configuration.web_app_base_dir # TODO: server setup does not yet support `:deploy_to` override, and would have to be refactored at a higher level than stage.
138
+ web_app_base_dir # TODO: server setup does not yet support `:deploy_to` override, and would have to be refactored at a higher level than stage.
119
139
  end
120
140
 
121
141
  # ENV['PVC_DEPLOY_TO_APP'] = "#{ENV['PVC_DEPLOY_TO_BASE']}/#{ENV['PVC_APP_NAME']}/#{ENV['PVC_STAGE']}"
@@ -172,28 +192,29 @@ module Pvcglue
172
192
  end
173
193
 
174
194
  def authorized_keys
175
- data[app_name][:authorized_keys]
195
+ project[:authorized_keys]
176
196
  end
177
197
 
178
198
  def ssh_ports
179
199
  ports = []
180
- from_all = data[app_name][:ssh_allowed_from_all_port].to_i
200
+ from_all = project[:ssh_allowed_from_all_port].to_i
181
201
  ports << from_all if from_all > 0
182
202
  ports
183
203
  end
184
204
 
185
205
  def timezone
186
- data[app_name][:time_zone] || 'America/Los_Angeles'
206
+ project[:time_zone] || 'America/Los_Angeles'
187
207
  end
188
208
 
189
209
  def exclude_tables
190
- data[app_name][:excluded_db_tables] || ['versions']
210
+ project[:excluded_db_tables] || ['versions']
191
211
  end
192
212
 
193
213
  def firewall_allow_incoming_on_port
214
+ raise 'Not used currently > 0.9'
194
215
  # These ports allow incoming connections from any ip address
195
216
  ports = []
196
- from_all = data[app_name][:ssh_allowed_from_all_port].to_i
217
+ from_all = project[:ssh_allowed_from_all_port].to_i
197
218
  ports << from_all if from_all > 0
198
219
  ports.concat [80, 443] if current_node.values.first[:allow_public_access]
199
220
  ports.concat ["2000:3000"] if stage_name == 'local'
@@ -201,6 +222,7 @@ module Pvcglue
201
222
  end
202
223
 
203
224
  def firewall_allow_incoming_from_ip
225
+ raise 'Not used currently > 0.9'
204
226
  # Incoming connections to any port are allowed from these ip addresses
205
227
  addresses = dev_ip_addresses
206
228
  addresses.concat(stage_internal_addresses)
@@ -213,11 +235,13 @@ module Pvcglue
213
235
  end
214
236
 
215
237
  def dev_ip_addresses
216
- data[app_name][:dev_ip_addresses].values.each_with_object([]) { |address, addresses| addresses << address }
238
+ return ['127.0.0.1']
239
+ # TODO: Add this functionality back in later
240
+ project[:dev_ip_addresses].values.each_with_object([]) { |address, addresses| addresses << address }
217
241
  end
218
242
 
219
243
  def stage_internal_addresses
220
- nodes_in_stage.values.each_with_object([]) do |value, addresses|
244
+ minions_filtered.values.each_with_object([]) do |value, addresses|
221
245
  addresses << value[:public_ip]
222
246
  addresses << value[:private_ip] if value[:private_ip]
223
247
  end
@@ -244,6 +268,14 @@ module Pvcglue
244
268
  stage[:ssl].to_sym || :none
245
269
  end
246
270
 
271
+ def ssl_mode_override
272
+ @ssl_mode_override || ssl_mode
273
+ end
274
+
275
+ def set_ssl_mode_override(mode)
276
+ @ssl_mode_override = mode
277
+ end
278
+
247
279
  def lb_nginx_load_balancing_method
248
280
  stage[:lb_nginx_load_balancing_method]
249
281
  end
@@ -253,51 +285,51 @@ module Pvcglue
253
285
  end
254
286
 
255
287
  def repo_url
256
- data[app_name][:repo_url]
288
+ project[:repo_url]
257
289
  end
258
290
 
259
291
  def dos_conn_limit_per_ip
260
- data[app_name][:dos_conn_limit_per_ip] || stage[:dos_conn_limit_per_ip] || "10"
292
+ project[:dos_conn_limit_per_ip] || stage[:dos_conn_limit_per_ip] || "10"
261
293
  end
262
294
 
263
295
  def dos_rate
264
- data[app_name][:dos_rate] || stage[:dos_rate] || "1"
296
+ project[:dos_rate] || stage[:dos_rate] || "1"
265
297
  end
266
298
 
267
299
  def dos_burst
268
- data[app_name][:dos_burst] || stage[:dos_burst] || "30"
300
+ project[:dos_burst] || stage[:dos_burst] || "30"
269
301
  end
270
302
 
271
303
  def additional_linked_dirs
272
- data[app_name][:additional_linked_dirs] || stage[:additional_linked_dirs] || ""
304
+ project[:additional_linked_dirs] || stage[:additional_linked_dirs] || ""
273
305
  end
274
306
 
275
307
  def client_header_timeout
276
- data[app_name][:client_header_timeout] || stage[:client_header_timeout] || "60s"
308
+ project[:client_header_timeout] || stage[:client_header_timeout] || "60s"
277
309
  end
278
310
 
279
311
  def client_body_timeout
280
- data[app_name][:client_body_timeout] || stage[:client_body_timeout] || "60s"
312
+ project[:client_body_timeout] || stage[:client_body_timeout] || "60s"
281
313
  end
282
314
 
283
315
  def proxy_read_timeout
284
- data[app_name][:proxy_read_timeout] || stage[:proxy_read_timeout] || "60s"
316
+ project[:proxy_read_timeout] || stage[:proxy_read_timeout] || "60s"
285
317
  end
286
318
 
287
319
  def proxy_send_timeout
288
- data[app_name][:proxy_send_timeout] || stage[:proxy_send_timeout] || "60s"
320
+ project[:proxy_send_timeout] || stage[:proxy_send_timeout] || "60s"
289
321
  end
290
322
 
291
323
  def client_max_body_size
292
- data[app_name][:client_max_body_size] || stage[:client_max_body_size] || "1m"
324
+ project[:client_max_body_size] || stage[:client_max_body_size] || "1m"
293
325
  end
294
326
 
295
327
  def swapfile_size
296
- data[app_name][:swapfile_size] || stage[:swapfile_size] || 1024
328
+ project[:swapfile_size] || stage[:swapfile_size] || 1024
297
329
  end
298
330
 
299
331
  def gems
300
- data[app_name][:gems] || {}
332
+ project[:gems] || {}
301
333
  end
302
334
 
303
335
  def db_rebuild
@@ -309,7 +341,7 @@ module Pvcglue
309
341
  end
310
342
 
311
343
  def nginx_config_ssl_path
312
- File.join(nginx_config_path, 'ssl')
344
+ File.join(nginx_config_path, 'ssl', "#{app_and_stage_name}")
313
345
  end
314
346
 
315
347
  def nginx_ssl_crt_file_name
@@ -333,7 +365,7 @@ module Pvcglue
333
365
  when :bootstrap, :manager
334
366
  port = "22"
335
367
  when :env, :build, :shell, :deploy, :maintenance
336
- port = data[app_name][:ssh_allowed_from_all_port] || "22"
368
+ port = project[:ssh_allowed_from_all_port] || "22"
337
369
  else
338
370
  raise "Context not specified or invalid"
339
371
  end
@@ -358,15 +390,170 @@ module Pvcglue
358
390
  end
359
391
 
360
392
  def monit_mailserver
361
- data[app_name][:monit_mailserver] || ""
393
+ project[:monit_mailserver] || ""
362
394
  end
363
395
 
364
396
  def monit_alert
365
- data[app_name][:monit_alert] || ""
397
+ project[:monit_alert] || ""
366
398
  end
367
399
 
368
400
  def monit_disk_usage_threshold
369
- stage[:monit_disk_usage_threshold] || data[app_name][:monit_disk_usage_threshold] || "80%"
401
+ stage[:monit_disk_usage_threshold] || project[:monit_disk_usage_threshold] || "80%"
402
+ end
403
+
404
+ def minion_manager_user_name
405
+ 'manager'
406
+ end
407
+
408
+ def letsencrypt_full
409
+ '/var/www/letsencrypt_root/.well-known/acme-challenge'
410
+ end
411
+
412
+ def letsencrypt_root
413
+ '/var/www/letsencrypt_root'
414
+ end
415
+
416
+
417
+ # ==============================================================================================
418
+
419
+ def manager_minion
420
+ @manager_minion ||= get_manager_minion
421
+ end
422
+
423
+ def get_manager_minion
424
+ minion = Pvcglue::Minion.new
425
+ minion.machine_name = 'pvcglue-manager'
426
+ minion.roles = ['manager']
427
+ minion.public_ip = Pvcglue.configuration.cloud_manager
428
+ minion.connection = Pvcglue::Connection.new(minion)
429
+ # minion.root_users = machine.root_users
430
+ # minion.users = machine.users
431
+ # minion.cloud_id = machine.cloud_id
432
+ minion.remote_user_name = minion_manager_user_name
433
+ # minion.all_data = data
434
+ # minion.project = project
435
+ # minion.stage = stage
436
+ # minion.cloud_provider = data.cloud_provider
437
+ # minion.cloud = ::Pvcglue.cloud
438
+ # minion.cloud_provider.name == 'not-supported'
439
+ minion
440
+
441
+ end
442
+
443
+ # def set_manager_as_project
444
+ #
445
+ # # raise('project already initialized') if @project
446
+ # # @project = find_or_raise(data.projects, 'pvcglue_manager')
447
+ # @app_name_override = 'pvcglue_manager'
448
+ # set_stage('manager')
449
+ # end
450
+
451
+ def reload_minions!
452
+ @data = nil
453
+ @project = nil
454
+ @stage = nil
455
+ @minions = nil
456
+ end
457
+
458
+ def web_app_base_dir
459
+ # '/sites'
460
+ "/home/#{minion_user_name}/www"
461
+ end
462
+
463
+
464
+ def minion_user_name_base
465
+ project[:user_name_base] || 'deploy'
466
+ end
467
+
468
+ def minion_user_name
469
+ "#{minion_user_name_base}-#{stage_name}"
470
+ end
471
+
472
+
473
+ def find_or_raise(data, name, key = 'name')
474
+ found = data.detect { |item| item[key] == name }
475
+ # raise(Thor::Error, "Error: #{name} not found.") unless found
476
+ unless found
477
+ puts "name=#{name}, key=#{key}, data="
478
+ ap data
479
+ raise("Error: #{name} not found.")
480
+ end
481
+ found
482
+ end
483
+
484
+ def project
485
+ @project ||= begin
486
+ get_project
487
+ end
488
+ end
489
+
490
+ def project_name
491
+ project.name
492
+ end
493
+
494
+ def get_project
495
+ find_or_raise(data.projects, @app_name_override || app_name)
496
+ end
497
+
498
+ def stage
499
+ @stage ||= begin
500
+ find_or_raise(project.stages, stage_name)
501
+ end
502
+ end
503
+
504
+ def minions
505
+ @minions ||= get_minions
506
+ end
507
+
508
+ def find_machine(name)
509
+ name.tr!('=', '') # "==dev-lb==" ==> "dev-lb"
510
+ find_or_raise(data.machines, name)
511
+ end
512
+
513
+ def get_minions
514
+ minions = ::SafeMash.new
515
+ stage.stack.each do |item|
516
+ # ap item
517
+ machine = find_machine(item.machine_name)
518
+ # ap machine
519
+ minion = minions[machine.name]
520
+ # ap minion
521
+ unless minion
522
+ # TODO: check for duplicate roles: ie. 2 web servers with the same id
523
+ minion = Pvcglue::Minion.new
524
+ minion.machine_name = item.machine_name
525
+ minion.roles = []
526
+ minion.private_ip = machine.private_ip
527
+ minion.public_ip = machine.public_ip
528
+ minion.connection = Pvcglue::Connection.new(minion)
529
+ minion.root_users = machine.root_users
530
+ minion.users = machine.users
531
+ minion.cloud_id = machine.cloud_id
532
+ minion.remote_user_name = minion_user_name
533
+ # TODO: sync all machine options here, automatically
534
+ end
535
+ # ap minion
536
+ # puts "*"*175
537
+ # ap minion.roles
538
+ # ap item.role
539
+ minion.roles << item.role
540
+ # ap minion.roles
541
+
542
+ # if item.role_index?
543
+ # minions
544
+ # end
545
+ # ap minion
546
+
547
+ minion.all_data = data
548
+ minion.project = project
549
+ minion.stage = stage
550
+ minion.cloud_provider = data.cloud_provider
551
+ minion.cloud = ::Pvcglue.cloud
552
+
553
+ minions[machine.name] = minion
554
+ end
555
+ # ap minions
556
+ minions
370
557
  end
371
558
  end
372
559