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
@@ -38,7 +38,10 @@ module Pvcglue
38
38
  init(:local_cloud_manager)
39
39
  @cloud_manager = @local_cloud_manager
40
40
  else
41
- init(:cloud_manager) || configure_manager
41
+ unless init(:cloud_manager)
42
+ say('The manager has not been configured.')
43
+ configure_manager
44
+ end
42
45
  end
43
46
 
44
47
  # raise(Thor::Error, "The manager has not been configured. :(") if cloud_manager.nil?
@@ -57,7 +60,6 @@ module Pvcglue
57
60
  end
58
61
 
59
62
  def configure_manager
60
- say('The manager has not been configured.')
61
63
  manager = ask('What is the IP address or host name of the manager?')
62
64
  default = !no?('Will this be the default manager? (Y/n)')
63
65
  file_name = default ? user_file_name : project_file_name
@@ -188,14 +190,50 @@ module Pvcglue
188
190
  end
189
191
  end
190
192
 
191
- def web_app_base_dir
192
- '/sites'
193
+ # def web_app_base_dir
194
+ # # '/sites'
195
+ # '~/www'
196
+ # # "/home/#{user_name}/.ssh"
197
+ # end
198
+
199
+ def build_log_extra_dir
200
+ @build_log_extra_dir ||= begin
201
+ option = Pvcglue.command_line_options[:save_before_upload]
202
+ if option != 'save_before_upload'
203
+ dir_name = option
204
+ else
205
+ dir_name = Time.now.strftime('%Y-%m-%d-%H%M%S')
206
+ end
207
+ result = File.join(pvcglue_tmp_dir, dir_name)
208
+ `mkdir -p '#{result}'`
209
+ raise $?.inspect unless $?.exitstatus == 0
210
+ result
211
+ end
212
+ end
213
+
214
+ def build_log_extra_filename(minion, user, remote_filename)
215
+ # local_filename = File.basename(remote_filename)
216
+ relative = remote_filename.sub(Pvcglue.cloud.web_app_base_dir, '/project')
217
+ local_filename = relative.sub(/\A\//, '').gsub(/\//, '__')
218
+ # local_filename = File.basename(remote_filename)
219
+ versioned_filename(File.join(build_log_extra_dir, "#{minion.machine_name}--#{user}--#{local_filename}"))
220
+ end
221
+
222
+ # TODO: Refactor to a utilities module or something
223
+ def versioned_filename(base, first_suffix='.00')
224
+ suffix = nil
225
+ filename = base
226
+ while File.exists?(filename)
227
+ suffix = (suffix ? suffix.succ : first_suffix)
228
+ filename = base + suffix
229
+ end
230
+ return filename
193
231
  end
194
232
  end
195
233
 
196
234
  end
197
235
 
198
- # --------------------------------------------------------------------------------------------------------------------
236
+ # --------------------------------------------------------------------------------------------------------------------
199
237
 
200
238
  def self.configuration
201
239
  @configuration ||= Configuration.new
@@ -0,0 +1,236 @@
1
+ module Pvcglue
2
+ # TODO: Check ssh config
3
+ ## https://puppet.com/blog/speed-up-ssh-by-reusing-connections
4
+ # ~/.ssh/config
5
+ #Host *
6
+ #ControlMaster auto
7
+ ##ControlPath ~/.ssh/sockets/%r@%h-%p
8
+ #ControlPath ~/.ssh/%r@%h-%p
9
+ #ControlPersist 600
10
+ #
11
+ # Way Faster!!!
12
+ #
13
+
14
+ class Connection
15
+ def initialize(minion)
16
+ @minion = minion
17
+ end
18
+
19
+ attr_accessor :minion
20
+ attr_accessor :minion_state_data
21
+
22
+ def file_exists?(user, file)
23
+ result = ssh?(user, '', "test -e #{file}")
24
+ result.exitstatus == 0
25
+ end
26
+
27
+ def mkdir_p(user, remote_dir, owner = nil, group = nil, permissions = nil)
28
+ ssh!(user, '', "mkdir -p #{remote_dir}")
29
+ chown_chmod(user, remote_dir, owner, group, permissions)
30
+ end
31
+
32
+ def ssh_retry_wait(user, options, cmd, times, wait)
33
+ tries = 0
34
+ begin
35
+ result = ssh?(user, options, cmd)
36
+ unless result.exitstatus == 0
37
+ Pvcglue.logger.info("Command `#{cmd}` failed, retrying...")
38
+ sleep(wait)
39
+ end
40
+ tries += 1
41
+ raise "Exceeded #{times} retries: #{result.inspect}" if tries >= times
42
+ end until result.exitstatus == 0
43
+ end
44
+
45
+ def escape_ssh_command(cmd)
46
+ # cmd.gsub(/'/, "\\'")
47
+ # cmd.gsub(/'/) { |match| "\\#{match}" }
48
+ # cmd.gsub(/'/) { |match| '\\' + match } # "CREATEDB PASSWORD 'monkey'" #=> "CREATEDB PASSWORD \'monkey\'"
49
+ # if cmd.include?("'") || cmd.include?('"')
50
+ # # if cmd.include?('"')
51
+ # # "<<'EOF'\n#{cmd}\nEOF"
52
+ # # cmd.gsub(/'/) { |match| %Q('"'"') }
53
+ # # "$'" + cmd.gsub(/'/) { |match| '\\' + match } + "'"
54
+ # '"' + cmd.gsub(/"/) { |match| '\\' + match } + '"'
55
+ # else
56
+ # "'#{cmd}'"
57
+ # end
58
+ # Another possible solution: http://stackoverflow.com/a/21761956/444774
59
+ '"' + cmd.gsub(/"/) { |match| '\\' + match } + '"'
60
+ end
61
+
62
+ def ssh?(user, options, cmd)
63
+ # if cmd.include?("'") # DONE: Quick fix, should be refactored to do proper escaping
64
+ # system_command?(%Q(ssh #{user}@#{minion.public_ip} #{options} "#{cmd}"))
65
+ # else
66
+ # system_command?(%Q(ssh #{user}@#{minion.public_ip} #{options} '#{cmd}'))
67
+ # end
68
+ system_command?(%Q(ssh #{user}@#{minion.public_ip} #{options} #{escape_ssh_command(cmd)}))
69
+ end
70
+
71
+ def ssh!(user, options, cmd)
72
+ result = ssh?(user, options, cmd)
73
+ raise result.inspect unless result.exitstatus == 0
74
+ end
75
+
76
+ def system_command?(cmd)
77
+ Pvcglue.logger.debug { cmd }
78
+ system(cmd)
79
+ Pvcglue.logger.debug { "exit_code=#{$?.exitstatus}" }
80
+ $?
81
+ end
82
+
83
+ def system_command!(cmd)
84
+ result = system_command?(cmd)
85
+ raise result.inspect unless result.exitstatus == 0
86
+ end
87
+
88
+ def run_get_stdout(user, options, cmd)
89
+ full_cmd = "ssh #{user}@#{minion.public_ip} #{options} #{escape_ssh_command(cmd)}"
90
+ Pvcglue.logger.debug { full_cmd }
91
+ result = `#{full_cmd}`
92
+ Pvcglue.verbose? { result }
93
+ Pvcglue.logger.debug { "exit_code=#{$?.to_i}" }
94
+ result
95
+ end
96
+
97
+ def run_get_stdout!(user, options, cmd)
98
+ result = run_get_stdout(user, options, cmd)
99
+ raise $?.inspect unless $?.exitstatus == 0
100
+ result
101
+ end
102
+
103
+ def run!(user, options, cmd)
104
+ ssh!(user, options, cmd)
105
+ end
106
+
107
+ def run?(user, options, cmd)
108
+ ssh?(user, options, cmd)
109
+ # puts user.inspect
110
+ # cmd = 'pwd'
111
+ # full_command = "ssh root@#{minion.public_ip} '#{cmd}'"
112
+ # full_command = "ssh root@#{minion.public_ip} 'ls -ahl'"
113
+ # puts "running: #{full_command}"
114
+ # puts `#{full_command}`
115
+ # 1.times do
116
+ # 100.times do
117
+ # puts "running: #{full_command}"
118
+ # puts `#{full_command}`
119
+ # puts `ls -ahl ~/.ssh/config`
120
+ # system %Q(ssh root@#{minion.public_ip} -o strictHostKeyChecking=no -t 'pwd')
121
+ # ap system %Q(ssh root@#{minion.public_ip} 'test -e test')
122
+ # ap system %Q(ssh root@#{minion.public_ip} -t 'test -e test')
123
+ # ap $?
124
+ # ap system %Q(ssh root@#{minion.public_ip} 'test -e .bashrc')
125
+ # ap $?
126
+ # ap file_exists?(:root, 'test')
127
+ # ap file_exists?(:root, '.bashrc')
128
+ # end
129
+ end
130
+
131
+ def read_from_file(user, file)
132
+ tmp_file = Tempfile.new('pvc')
133
+ begin
134
+ download_file(user, file, tmp_file.path)
135
+ data = tmp_file.read
136
+ Pvcglue.verbose? { data }
137
+ ensure
138
+ tmp_file.close
139
+ tmp_file.unlink # deletes the temp file
140
+ end
141
+ data
142
+ end
143
+
144
+ def read_from_file_if_exists?(user, file)
145
+ tmp_file = Tempfile.new('pvc')
146
+ begin
147
+ result = download_file(user, file, tmp_file.path, false)
148
+ if result.exitstatus == 0
149
+ data = tmp_file.read
150
+ elsif result.exitstatus == 1
151
+ data = nil
152
+ else
153
+ raise $?.inspect
154
+ end
155
+ Pvcglue.verbose? { data }
156
+ ensure
157
+ tmp_file.close
158
+ tmp_file.unlink # deletes the temp file
159
+ end
160
+ data
161
+
162
+ end
163
+
164
+ def write_to_file_from_template(user, template_file_name, file, owner = nil, group = nil, permissions = nil)
165
+ Pvcglue.logger.debug { "Writing to #{file} from template '#{template_file_name}'" }
166
+ template = Tilt.new(Pvcglue.template_file_name(template_file_name))
167
+ data = template.render(self, minion: minion)
168
+
169
+ write_to_file(user, data, file, owner, group, permissions)
170
+ end
171
+
172
+ def write_to_file(user, data, file, owner = nil, group = nil, permissions = nil)
173
+ tmp_file = Tempfile.new('pvc')
174
+ begin
175
+ tmp_file.write(data)
176
+ tmp_file.flush
177
+ upload_file(user, tmp_file.path, file, owner, group, permissions)
178
+ Pvcglue.verbose? { data }
179
+ ensure
180
+ tmp_file.close
181
+ tmp_file.unlink # deletes the temp file
182
+ end
183
+ end
184
+
185
+ def download_file(user, remote_file, local_file, raise_error = true)
186
+ cmd = %{scp #{user}@#{minion.public_ip}:#{remote_file} #{local_file}}
187
+ if raise_error
188
+ system_command!(cmd)
189
+ else
190
+ system_command?(cmd)
191
+ end
192
+ end
193
+
194
+ def upload_file(user, local_file, remote_file, owner = nil, group = nil, permissions = nil)
195
+ if Pvcglue.command_line_options[:save_before_upload] && file_exists?(user, remote_file)
196
+ download_file(user, remote_file, Pvcglue.configuration.build_log_extra_filename(minion, user, remote_file))
197
+ end
198
+ system_command!(%{scp #{local_file} #{user}@#{minion.public_ip}:#{remote_file}})
199
+ chown_chmod(user, remote_file, owner, group, permissions)
200
+ end
201
+
202
+ def chown_chmod(user, remote, owner, group, permissions = nil)
203
+ unless owner.nil? && group.nil?
204
+ raise('Invalid owner or group for chown') if owner.nil? || group.nil?
205
+ chown(user, remote, owner, group)
206
+ end
207
+ unless permissions.nil?
208
+ chmod(user, remote, permissions)
209
+ end
210
+ end
211
+
212
+ def chown(user, remote, owner, group, options = nil)
213
+ ssh!(user, '', "chown #{options} #{owner}:#{group} #{remote}")
214
+ end
215
+
216
+ def chmod(user, remote, permissions, options = nil)
217
+ ssh!(user, '', "chmod #{options} #{permissions} #{remote}")
218
+ end
219
+
220
+ def file_matches?(user, data, remote_file)
221
+ # NOTE: This could be optimized
222
+ return false unless file_exists?(user, remote_file)
223
+ read_from_file(user, remote_file) == data
224
+ end
225
+
226
+ def rsync_up (user, options, local_source_dir, remote_destination_dir, mkdir = true)
227
+ mkdir_p(user, remote_destination_dir) if mkdir
228
+ cmd = ''
229
+ # cmd += "mkdir -p #{remote_destination_dir} && "
230
+ cmd += %(rsync #{options} #{local_source_dir}/ #{user}@#{minion.public_ip}:#{remote_destination_dir}/)
231
+ # cmd = (%(rsync -rzv --exclude=maintenance.on --delete -e 'ssh -p #{Pvcglue.cloud.port_in_node_context}' #{source_dir}/ #{node.get(:user)}@#{node.host}:#{dest_dir}/))
232
+ system_command!(cmd)
233
+ end
234
+
235
+ end
236
+ end
@@ -0,0 +1,3 @@
1
+ class SafeMash < Hashie::Mash
2
+ include Hashie::Extensions::Mash::SafeAssignment
3
+ end
data/lib/pvcglue/db.rb CHANGED
@@ -96,8 +96,8 @@ module Pvcglue
96
96
  end
97
97
 
98
98
  def self.db_host_public
99
- node = Pvcglue.cloud.find_node('db')
100
- node['db']['public_ip']
99
+ # Assume 1 pg server
100
+ Pvcglue.cloud.minions_filtered('pg').values.first.public_ip
101
101
  end
102
102
 
103
103
 
@@ -128,12 +128,15 @@ module Pvcglue
128
128
 
129
129
 
130
130
  def pg_dump(db, file_name, fast)
131
+ # TODO: Refactor into the db package
131
132
  file_name = self.class.file_helper(file_name)
132
133
 
133
134
  if db.kind == :remote
134
- host = Pvcglue.cloud.nodes_in_stage('db')['db']['public_ip']
135
+ minion = Pvcglue.cloud.minions_filtered('pg').values.first
136
+ # Assume 1 pg server
137
+ host = minion.public_ip
135
138
  port = Pvcglue.cloud.port_in_context(:shell)
136
- user = 'deploy'
139
+ user = minion.remote_user_name
137
140
  end
138
141
 
139
142
  cmd = "pg_dump -Fc --no-acl --no-owner -h #{db.host} -p #{db.port}"
@@ -153,43 +156,46 @@ module Pvcglue
153
156
  unless Pvcglue.run_remote(host, port, user, cmd)
154
157
  puts "ERROR:"
155
158
  puts $?.inspect
156
- raise(Thor::Error, "Error: #{$?}")
159
+ raise("Error: #{$?}")
157
160
  end
158
161
 
159
162
  cmd = %{scp -P #{port} #{user}@#{host}:#{file_name} #{file_name}}
160
163
  puts "Running `#{cmd}`"
161
164
 
162
165
  unless system cmd
163
- raise(Thor::Error, "Error: #{$?}")
166
+ raise("Error: #{$?}")
164
167
  end
165
168
  else
166
169
  unless system(cmd)
167
170
  puts "ERROR:"
168
171
  puts $?.inspect
169
- raise(Thor::Error, "Error: #{$?}")
172
+ raise("Error: #{$?}")
170
173
  end
171
174
  end
172
175
  end
173
176
 
174
177
  def pg_restore(db, file_name, fast = false)
178
+ # TODO: Refactor into the db package
175
179
  Pvcglue.cloud.stage_name == 'production' && destroy_prod?(db)
176
180
  file_name = self.class.file_helper(file_name)
177
181
 
182
+
178
183
  if db.kind == :remote
179
- host = Pvcglue.cloud.nodes_in_stage('db')['db']['public_ip']
184
+ minion = Pvcglue.cloud.minions_filtered('pg').values.first
185
+ host = minion.public_ip
180
186
  port = Pvcglue.cloud.port_in_context(:shell)
181
- user = 'deploy'
187
+ user = minion.remote_user_name
182
188
 
183
189
  # cmd = %{scp -P #{port} #{file_name} #{user}@#{host}:#{file_name}}
184
190
  cmd = %{rsync -avhPe "ssh -p #{port}" --progress #{file_name} #{user}@#{host}:#{file_name}}
185
191
  unless system cmd
186
- raise(Thor::Error, "Error: #{$?}")
192
+ raise("Error: #{$?}")
187
193
  end
188
194
 
189
195
  unless fast
190
196
  # Drop and recreate DB
191
- Pvcglue::Packages.apply('postgresql-app-stage-db-drop'.to_sym, :build, Pvcglue.cloud.nodes_in_stage('db'))
192
- Pvcglue::Packages.apply('postgresql-app-stage-conf'.to_sym, :build, Pvcglue.cloud.nodes_in_stage('db'))
197
+ Pvcglue::Packages.apply('postgresql-app-stage-db-drop'.to_sym, :build, Pvcglue.cloud.minions_filtered('db'))
198
+ Pvcglue::Packages.apply('postgresql-app-stage-conf'.to_sym, :build, Pvcglue.cloud.minions_filtered('db'))
193
199
  end
194
200
  end
195
201
 
@@ -205,7 +211,7 @@ module Pvcglue
205
211
  end
206
212
  else
207
213
  unless system(" PGPASSWORD=#{db.password} #{cmd}")
208
- raise(Thor::Error, "Error: #{$?}")
214
+ raise("Error: #{$?}")
209
215
  end
210
216
  end
211
217
 
@@ -0,0 +1,21 @@
1
+ module Pvcglue
2
+ class DigitalOcean
3
+
4
+ def self.client
5
+ @@client ||= get_client
6
+ end
7
+
8
+ def self.get_client
9
+ access_token = YAML::load(File.open(File.join(ENV['HOME'], '.config/doctl/config.yaml')))['access-token']
10
+ ::DropletKit::Client.new(access_token: access_token)
11
+ end
12
+
13
+ def self.get_ip_addresses(droplet)
14
+ ips = ::SafeMash.new
15
+ droplet.networks.v4.each do |network|
16
+ ips[network.type] = network.ip_address
17
+ end
18
+ ips
19
+ end
20
+ end
21
+ end
data/lib/pvcglue/env.rb CHANGED
@@ -6,16 +6,18 @@ module Pvcglue
6
6
  desc "push", "push"
7
7
 
8
8
  def push
9
- Pvcglue::Packages.apply('env-push'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
10
- self.class.clear_stage_env_cache
11
- Pvcglue::Packages.apply('app-env-file'.to_sym, :env, Pvcglue.cloud.nodes_in_stage('web'))
9
+ raise('Not implemented')
10
+ # Pvcglue::Packages.apply('env-push'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
11
+ # self.class.clear_stage_env_cache
12
+ # Pvcglue::Packages.apply('app-env-file'.to_sym, :env, Pvcglue.cloud.nodes_in_stage('web'))
12
13
  end
13
14
 
14
15
  desc "pull", "pull"
15
16
 
16
17
  def pull
17
- Pvcglue::Packages.apply('env-pull'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
18
- self.class.clear_stage_env_cache
18
+ raise('Not implemented')
19
+ # Pvcglue::Packages.apply('env-pull'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
20
+ # self.class.clear_stage_env_cache
19
21
  end
20
22
 
21
23
  desc "list", "list"
@@ -38,10 +40,12 @@ module Pvcglue
38
40
 
39
41
  def set(*args)
40
42
  self.class.initialize_stage_env
43
+ Pvcglue.logger.debug { args.each { |arg| arg.inspect } }
41
44
  options = Hash[args.each.map { |l| l.chomp.split('=') }]
45
+ Pvcglue.logger.debug { options.inspect }
42
46
  Pvcglue.cloud.stage_env.merge!(options)
43
47
  self.class.save_stage_env
44
- Pvcglue::Packages.apply('app-env-file'.to_sym, :env, Pvcglue.cloud.nodes_in_stage('web'))
48
+ self.class.apply_changes
45
49
  end
46
50
 
47
51
  desc "unset", "remove environment variable(s) for the stage XYZ [ZZZ]"
@@ -50,7 +54,7 @@ module Pvcglue
50
54
  self.class.initialize_stage_env
51
55
  args.each { |arg| puts "WARNING: Key '#{arg}' not found." unless Pvcglue.cloud.stage_env.delete(arg) }
52
56
  self.class.save_stage_env
53
- Pvcglue::Packages.apply('app-env-file'.to_sym, :env, Pvcglue.cloud.nodes_in_stage('web'))
57
+ self.class.apply_changes
54
58
  end
55
59
 
56
60
  desc "rm", "alternative to unset"
@@ -63,10 +67,11 @@ module Pvcglue
63
67
  # ------------------------------------------------------------------------------------------------------------------
64
68
 
65
69
  def self.initialize_stage_env
66
- unless read_cached_stage_env
67
- Pvcglue::Packages.apply('env-get-stage'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
68
- write_stage_env_cache
69
- end
70
+ Pvcglue::Packages::Secrets.load_for_stage
71
+ # unless read_cached_stage_env
72
+ # Pvcglue::Packages.apply('env-get-stage'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
73
+ # write_stage_env_cache
74
+ # end
70
75
  merged = stage_env_defaults.merge(Pvcglue.cloud.stage_env)
71
76
  if merged != Pvcglue.cloud.stage_env
72
77
  Pvcglue.cloud.stage_env = merged
@@ -75,35 +80,48 @@ module Pvcglue
75
80
  end
76
81
 
77
82
  def self.save_stage_env
78
- Pvcglue::Packages.apply('env-set-stage'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
79
- write_stage_env_cache
83
+ Pvcglue::Packages::Secrets.save_for_stage
84
+ # Pvcglue::Packages.apply('env-set-stage'.to_sym, :manager, Pvcglue::Manager.manager_node, 'pvcglue')
85
+ # write_stage_env_cache
80
86
  end
81
87
 
82
88
  def self.stage_env_defaults
83
- {
84
- 'RAILS_SECRET_TOKEN' => SecureRandom.hex(64),
85
- 'DB_USER_POSTGRES_HOST' => db_host,
86
- 'DB_USER_POSTGRES_PORT' => "5432",
87
- 'DB_USER_POSTGRES_USERNAME' => "#{Pvcglue.cloud.app_name}_#{Pvcglue.cloud.stage_name_validated}",
88
- 'DB_USER_POSTGRES_DATABASE' => "#{Pvcglue.cloud.app_name}_#{Pvcglue.cloud.stage_name_validated}",
89
- 'DB_USER_POSTGRES_PASSWORD' => new_password,
90
- 'MEMCACHE_SERVERS' => memcached_host,
91
- 'REDIS_SERVER' => redis_host
92
- }
89
+ defaults = {}
90
+
91
+ defaults['RAILS_SECRET_TOKEN'] = SecureRandom.hex(64) # From rails/railties/lib/rails/tasks/misc.rake
92
+ defaults['SECRET_KEY_BASE'] = SecureRandom.hex(64) # From rails/railties/lib/rails/tasks/misc.rake
93
+
94
+ if Pvcglue.cloud.minions_filtered('pg').any?
95
+ defaults['DB_USER_POSTGRES_HOST'] = db_host
96
+ defaults['DB_USER_POSTGRES_PORT'] = "5432"
97
+ defaults['DB_USER_POSTGRES_USERNAME'] = "#{Pvcglue.cloud.app_name}_#{Pvcglue.cloud.stage_name_validated}"
98
+ defaults['DB_USER_POSTGRES_DATABASE'] = "#{Pvcglue.cloud.app_name}_#{Pvcglue.cloud.stage_name_validated}"
99
+ defaults['DB_USER_POSTGRES_PASSWORD'] = new_password
100
+ end
101
+
102
+ if Pvcglue.cloud.minions_filtered('memcached').any?
103
+ defaults['MEMCACHE_SERVERS'] = memcached_host
104
+ end
105
+
106
+ if Pvcglue.cloud.minions_filtered('redis').any?
107
+ defaults['REDIS_SERVER'] = redis_host
108
+ end
109
+
110
+ defaults
93
111
  end
94
112
 
95
113
  def self.db_host
96
- node = Pvcglue.cloud.find_node('db')
97
- node['db']['private_ip']
114
+ # Assume 1 pg server
115
+ Pvcglue.cloud.minions_filtered('pg').values.first.private_ip
98
116
  end
99
117
 
100
118
  def self.memcached_host
101
- node = Pvcglue.cloud.find_node('memcached', false)
119
+ node = Pvcglue.cloud.find_minion_by_name('memcached', false)
102
120
  node ? "#{node['memcached']['private_ip']}:11211" : ""
103
121
  end
104
122
 
105
123
  def self.redis_host
106
- node = Pvcglue.cloud.find_node('redis', false)
124
+ node = Pvcglue.cloud.find_minion_by_name('redis', false)
107
125
  node ? "#{node['redis']['private_ip']}:6379" : ""
108
126
  end
109
127
 
@@ -143,7 +161,13 @@ module Pvcglue
143
161
  File.delete(stage_env_cache_file_name) if File.exists?(stage_env_cache_file_name)
144
162
  end
145
163
 
146
-
164
+ def self.apply_changes
165
+ Pvcglue.cloud.minions.each do |minion_name, minion|
166
+ if minion.has_roles? %w(web worker)
167
+ Pvcglue::Packages::Secrets.apply(minion)
168
+ end
169
+ end
170
+ end
147
171
  end
148
172
 
149
173
  end