pvcglue 0.1.39 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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