postgresinator 0.1.0 → 0.2.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.
- data/lib/postgresinator/built-in.rb +198 -0
- data/lib/postgresinator/check.rb +130 -0
- data/lib/postgresinator/config.rb +69 -118
- data/lib/postgresinator/db.rb +126 -0
- data/lib/postgresinator/examples/Capfile +1 -1
- data/lib/postgresinator/examples/Dockerfile +7 -6
- data/lib/postgresinator/examples/config/deploy/staging.rb +29 -50
- data/lib/postgresinator/examples/config/deploy.rb +8 -58
- data/lib/postgresinator/examples/pg_hba.conf.erb +5 -7
- data/lib/postgresinator/examples/postgresql.conf.erb +6 -6
- data/lib/postgresinator/examples/recovery.conf.erb +2 -2
- data/lib/postgresinator/pg.rb +117 -486
- data/lib/postgresinator.rb +4 -1
- metadata +25 -24
- data/lib/postgresinator/examples/config/deploy/staging_postgresinator.rb +0 -43
- data/lib/postgresinator/examples/config/deploy_postgresinator.rb +0 -1
@@ -0,0 +1,198 @@
|
|
1
|
+
set :postgres_templates_path, "templates/postgres"
|
2
|
+
set :postgres_config_files, ["postgresql.conf", "pg_hba.conf"]
|
3
|
+
set :postgres_recovery_conf, ["recovery.conf"]
|
4
|
+
set :postgres_root_path, -> { shared_path.join('postgres') }
|
5
|
+
set :postgres_data_path, -> { fetch(:postgres_root_path).join('data') }
|
6
|
+
set :postgres_config_path, -> { fetch(:postgres_root_path).join('conf') }
|
7
|
+
set :postgres_socket_path, -> { fetch(:postgres_root_path).join('run') }
|
8
|
+
set :postgres_recovery_conf, -> { "#{fetch(:postgres_data_path)}/recovery.conf" }
|
9
|
+
set :postgres_ssl_key, -> { "#{fetch(:postgres_data_path)}/server.key" }
|
10
|
+
set :postgres_ssl_csr, -> { "#{fetch(:postgres_data_path)}/server.csr" }
|
11
|
+
set :postgres_ssl_crt, -> { "#{fetch(:postgres_data_path)}/server.crt" }
|
12
|
+
set :postgres_log_level, "info"
|
13
|
+
|
14
|
+
def pg_run(host)
|
15
|
+
execute("docker", "run", "--detach", "--tty", "--user", "postgres",
|
16
|
+
"--name", host.properties.postgres_container_name,
|
17
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
18
|
+
"--expose", "5432",
|
19
|
+
"--publish", "0.0.0.0:#{host.properties.postgres_port}:5432",
|
20
|
+
"--restart", "always",
|
21
|
+
"--entrypoint", "/usr/lib/postgresql/9.1/bin/postgres",
|
22
|
+
fetch(:postgres_image_name),
|
23
|
+
"-D", shared_path.join('postgres', 'data'),
|
24
|
+
"-c", "config_file=#{shared_path.join('postgres', 'conf', 'postgresql.conf')}")
|
25
|
+
end
|
26
|
+
def pg_init(host)
|
27
|
+
execute("docker", "run", "--rm", "--user", "root",
|
28
|
+
"--volume", "#{fetch(:postgres_data_path)}:/postgresql-data:rw",
|
29
|
+
"--entrypoint", "/usr/bin/rsync",
|
30
|
+
fetch(:postgres_image_name), "-ah", "/var/lib/postgresql/9.1/main/", "/postgresql-data/")
|
31
|
+
end
|
32
|
+
def pg_replicate(host)
|
33
|
+
execute("docker", "run", "--rm", "--user", "postgres",
|
34
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
35
|
+
"--entrypoint", "/usr/bin/pg_basebackup",
|
36
|
+
fetch(:postgres_image_name),
|
37
|
+
"-w", "-h", fetch(:domain), "-p", fetch(:master_container_port),
|
38
|
+
"-U", "replicator", "-D", fetch(:postgres_data_path), "-v", "-x")
|
39
|
+
end
|
40
|
+
def pg_ssl_key(host)
|
41
|
+
execute("docker", "run", "--rm", "--user", "root",
|
42
|
+
"--entrypoint", "/usr/bin/openssl",
|
43
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
44
|
+
fetch(:postgres_image_name), "req", "-nodes", "-newkey", "rsa:2048",
|
45
|
+
"-keyout", fetch(:postgres_ssl_key),
|
46
|
+
"-out", fetch(:postgres_ssl_csr),
|
47
|
+
"-subj", "\"/C=US/ST=Oregon/L=Portland/O=My Company/OU=Operations/CN=localhost\"")
|
48
|
+
end
|
49
|
+
def pg_ssl_crt(host)
|
50
|
+
execute("docker", "run", "--rm", "--user", "root",
|
51
|
+
"--entrypoint", "/usr/bin/openssl",
|
52
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
53
|
+
fetch(:postgres_image_name), "req", "-x509", "-text",
|
54
|
+
"-in", fetch(:postgres_ssl_csr),
|
55
|
+
"-key", fetch(:postgres_ssl_key),
|
56
|
+
"-out", fetch(:postgres_ssl_crt))
|
57
|
+
end
|
58
|
+
def pg_restore(host, args, clean)
|
59
|
+
SSHKit.config.output_verbosity = "debug"
|
60
|
+
execute("docker", "run", "--rm",
|
61
|
+
"--volume", "/tmp:/tmp:rw",
|
62
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
63
|
+
"--entrypoint", "/bin/bash",
|
64
|
+
fetch(:postgres_image_name),
|
65
|
+
"-c", "'/usr/bin/pg_restore", "-U", "postgres",
|
66
|
+
"--host", fetch(:postgres_socket_path), clean,
|
67
|
+
"-d", args.database_name, "-F", "tar", "-v", "/tmp/#{args.dump_file}'")
|
68
|
+
SSHKit.config.output_verbosity = fetch(:postgres_log_level)
|
69
|
+
end
|
70
|
+
def pg_dump(host, args)
|
71
|
+
SSHKit.config.output_verbosity = "debug"
|
72
|
+
execute("docker", "run", "--rm",
|
73
|
+
"--volume", "/tmp:/tmp:rw",
|
74
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
75
|
+
"--entrypoint", "/bin/bash",
|
76
|
+
fetch(:postgres_image_name),
|
77
|
+
"-c", "'/usr/bin/pg_dump", "-U", "postgres",
|
78
|
+
"--host", fetch(:postgres_socket_path), "-F", "tar",
|
79
|
+
"-v", args.database_name, ">", "/tmp/#{args.dump_file}'")
|
80
|
+
SSHKit.config.output_verbosity = fetch(:postgres_log_level)
|
81
|
+
end
|
82
|
+
def pg_interactive(host)
|
83
|
+
[
|
84
|
+
"ssh", "-t", "#{host}", "\"docker", "run", "--rm", "--interactive", "--tty",
|
85
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
86
|
+
"--entrypoint", "/bin/bash",
|
87
|
+
"#{fetch(:postgres_image_name)}",
|
88
|
+
"-lic", "'/usr/bin/psql", "-U", "postgres",
|
89
|
+
"--host", "#{fetch(:postgres_socket_path)}'\""
|
90
|
+
].join(' ')
|
91
|
+
end
|
92
|
+
def pg_interactive_print(host)
|
93
|
+
[
|
94
|
+
"docker", "run", "--rm", "--interactive", "--tty",
|
95
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
96
|
+
"--entrypoint", "/bin/bash",
|
97
|
+
"#{fetch(:postgres_image_name)}",
|
98
|
+
"-lic", "'/usr/bin/psql", "-U", "postgres",
|
99
|
+
"--host", "#{fetch(:postgres_socket_path)}'"
|
100
|
+
].join(' ')
|
101
|
+
end
|
102
|
+
def pg_list_databases(host)
|
103
|
+
capture("docker", "run", "--rm",
|
104
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
105
|
+
"--entrypoint", "/bin/bash",
|
106
|
+
fetch(:postgres_image_name),
|
107
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
108
|
+
"--host", fetch(:postgres_socket_path),
|
109
|
+
"-a", "-c", "\"\\l\"'").lines.each { |l| info l }
|
110
|
+
end
|
111
|
+
def pg_list_roles(host)
|
112
|
+
capture("docker", "run", "--rm",
|
113
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
114
|
+
"--entrypoint", "/bin/bash",
|
115
|
+
fetch(:postgres_image_name),
|
116
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
117
|
+
"--host", fetch(:postgres_socket_path),
|
118
|
+
"-c", "\"\\du\"'").lines.each { |l| info l }
|
119
|
+
end
|
120
|
+
def pg_streaming_master(host)
|
121
|
+
capture("echo", "\"SELECT", "*", "FROM", "pg_stat_replication;\"", "|",
|
122
|
+
"docker", "run", "--rm", "--interactive",
|
123
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
124
|
+
"--entrypoint", "/bin/bash",
|
125
|
+
fetch(:postgres_image_name),
|
126
|
+
"-c", "'/usr/bin/psql", "-U", "postgres", "-xa",
|
127
|
+
"--host", "#{fetch(:postgres_socket_path)}'").lines.each { |l| info l }
|
128
|
+
end
|
129
|
+
def pg_streaming_slave(host)
|
130
|
+
capture("echo", "\"SELECT", "now()", "-", "pg_last_xact_replay_timestamp()",
|
131
|
+
"AS", "replication_delay;\"", "|",
|
132
|
+
"docker", "run", "--rm", "--interactive",
|
133
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
134
|
+
"--entrypoint", "/bin/bash",
|
135
|
+
fetch(:postgres_image_name),
|
136
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
137
|
+
"--host", "#{fetch(:postgres_socket_path)}'").lines.each { |l| info l }
|
138
|
+
end
|
139
|
+
def pg_create_role(db_role, password)
|
140
|
+
execute("echo", "\"CREATE", "ROLE", "\\\"#{db_role}\\\"",
|
141
|
+
"WITH", "LOGIN", "ENCRYPTED", "PASSWORD", "'#{password}'",
|
142
|
+
"REPLICATION", "CREATEDB;\"", "|",
|
143
|
+
"docker", "run", "--rm", "--interactive",
|
144
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
145
|
+
"--entrypoint", "/bin/bash",
|
146
|
+
fetch(:postgres_image_name),
|
147
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
148
|
+
"--host", "#{fetch(:postgres_socket_path)}'")
|
149
|
+
end
|
150
|
+
def pg_create_database(database)
|
151
|
+
execute("echo", "\"CREATE", "DATABASE", "\\\"#{database[:name]}\\\"",
|
152
|
+
"WITH", "OWNER", "\\\"#{database[:db_role]}\\\"", "TEMPLATE",
|
153
|
+
"template0", "ENCODING", "'UTF8';\"", "|",
|
154
|
+
"docker", "run", "--rm", "--interactive",
|
155
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
156
|
+
"--entrypoint", "/bin/bash",
|
157
|
+
fetch(:postgres_image_name),
|
158
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
159
|
+
"--host", "#{fetch(:postgres_socket_path)}'")
|
160
|
+
end
|
161
|
+
def pg_grant_database(database)
|
162
|
+
execute("echo", "\"GRANT", "ALL", "PRIVILEGES", "ON", "DATABASE",
|
163
|
+
"\\\"#{database[:name]}\\\"", "to", "\\\"#{database[:db_role]}\\\";\"", "|",
|
164
|
+
"docker", "run", "--rm", "--interactive",
|
165
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
166
|
+
"--entrypoint", "/bin/bash",
|
167
|
+
fetch(:postgres_image_name),
|
168
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
169
|
+
"--host", "#{fetch(:postgres_socket_path)}'")
|
170
|
+
end
|
171
|
+
def pg_role_exists?(db_role)
|
172
|
+
test("echo", "\"SELECT", "*", "FROM", "pg_user",
|
173
|
+
"WHERE", "usename", "=", "'#{db_role}';\"", "|",
|
174
|
+
"docker", "run", "--rm", "--interactive",
|
175
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
176
|
+
"--entrypoint", "/bin/bash",
|
177
|
+
fetch(:postgres_image_name),
|
178
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
179
|
+
"--host", "#{fetch(:postgres_socket_path)}'", "|",
|
180
|
+
"grep", "-q", "'#{db_role}'")
|
181
|
+
end
|
182
|
+
def pg_database_exists?(database_name)
|
183
|
+
test("docker", "run", "--rm",
|
184
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
185
|
+
"--entrypoint", "/bin/bash",
|
186
|
+
fetch(:postgres_image_name),
|
187
|
+
"-c", "'/usr/bin/psql", "-U", "postgres",
|
188
|
+
"--host", fetch(:postgres_socket_path), "-lqt", "|",
|
189
|
+
"cut", "-d\\|", "-f1", "|", "grep", "-w", "#{database_name}'")
|
190
|
+
end
|
191
|
+
def pg_database_empty?(database_name)
|
192
|
+
test("docker", "run", "--rm", "--tty",
|
193
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
194
|
+
"--entrypoint", "/bin/bash", fetch(:postgres_image_name), "-lc",
|
195
|
+
"'/usr/bin/psql", "-U", "postgres", "-d", database_name,
|
196
|
+
"--host", fetch(:postgres_socket_path),
|
197
|
+
"-c", "\"\\dt\"", "|", "grep", "-qi", "\"no relations found\"'")
|
198
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
namespace :pg do
|
2
|
+
namespace :check do
|
3
|
+
|
4
|
+
#desc 'Ensure all postgresinator specific settings are set, and warn and exit if not.'
|
5
|
+
before 'pg:setup', :settings do
|
6
|
+
require 'resolv' unless defined?(Resolv)
|
7
|
+
run_locally do
|
8
|
+
{
|
9
|
+
(File.dirname(__FILE__) + "/examples/config/deploy.rb") => 'config/deploy.rb',
|
10
|
+
(File.dirname(__FILE__) + "/examples/config/deploy/staging.rb") => "config/deploy/#{fetch(:stage)}.rb"
|
11
|
+
}.each do |abs, rel|
|
12
|
+
Rake::Task['deployinator:settings'].invoke(abs, rel)
|
13
|
+
Rake::Task['deployinator:settings'].reenable
|
14
|
+
end
|
15
|
+
end
|
16
|
+
on roles(:db, :db_slave, :in => :parallel) do |host|
|
17
|
+
unless host.properties.respond_to?(:postgres_port)
|
18
|
+
fatal "#{host} does not have postgres_port set." and exit
|
19
|
+
end
|
20
|
+
unless host.properties.respond_to?(:ip)
|
21
|
+
host.properties.set :ip, Resolv.getaddress(host.to_s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
on roles(:db) do |host|
|
25
|
+
unless host.properties.respond_to?(:postgres_container_name)
|
26
|
+
host.properties.set :postgres_container_name, "#{fetch(:domain)}-postgres-master_#{host.properties.postgres_port}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
on roles(:db_slave, :in => :parallel) do |host|
|
30
|
+
unless host.properties.respond_to?(:postgres_container_name)
|
31
|
+
host.properties.set :postgres_container_name, "#{fetch(:domain)}-postgres-slave_#{host.properties.postgres_port}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
run_locally do
|
35
|
+
unless roles(:db).length == 1
|
36
|
+
fatal "You can't set more than one master! (set only one host in the :db role.)"
|
37
|
+
fatal roles(:db)
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :settings do
|
44
|
+
desc 'Print example postgresinator specific settings for comparison.'
|
45
|
+
task :print do
|
46
|
+
set :print_all, true
|
47
|
+
Rake::Task['pg:check:settings'].invoke
|
48
|
+
end
|
49
|
+
|
50
|
+
task :database, [:database_name] do |t, args|
|
51
|
+
run_locally do
|
52
|
+
database_found = false
|
53
|
+
fetch(:postgres_databases).each do |database|
|
54
|
+
next unless database[:name] == args.database_name
|
55
|
+
database_found = true
|
56
|
+
end
|
57
|
+
fatal "Database #{args.domain} not found in the configuration" and exit unless database_found
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
task :domain, [:domain] do |t, args|
|
62
|
+
run_locally do
|
63
|
+
unless roles(:db, :db_slave).select { |host| host.to_s == args.domain }.length == 1
|
64
|
+
fatal "Server domain #{args.domain} not found in the configuration" and exit
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
task :postgres_uid_gid do
|
70
|
+
on roles(:db) do
|
71
|
+
set :postgres_uid, -> {
|
72
|
+
capture("docker", "run", "--rm", "--tty",
|
73
|
+
"--entrypoint", "/usr/bin/id",
|
74
|
+
fetch(:postgres_image_name), "-u", "postgres").strip
|
75
|
+
}
|
76
|
+
set :postgres_gid, -> {
|
77
|
+
capture("docker", "run", "--rm", "--tty",
|
78
|
+
"--entrypoint", "/usr/bin/id",
|
79
|
+
fetch(:postgres_image_name), "-g", "postgres").strip
|
80
|
+
}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
task :file_permissions => ['pg:ensure_setup', 'postgresinator:deployment_user', 'postgresinator:webserver_user'] do
|
86
|
+
on roles(:db, :db_slave, :in => :parallel) do |host|
|
87
|
+
as "root" do
|
88
|
+
execute "mkdir", "-p", fetch(:postgres_data_path),
|
89
|
+
fetch(:postgres_socket_path), fetch(:postgres_config_path)
|
90
|
+
["#{fetch(:deploy_to)}/..", fetch(:deploy_to), shared_path].each do |dir|
|
91
|
+
execute("chown", "#{fetch(:deployment_user_id)}:#{unix_user_get_gid(fetch(:webserver_username))}", dir.to_s)
|
92
|
+
execute("chmod", "2750", dir.to_s)
|
93
|
+
end
|
94
|
+
# chown everything
|
95
|
+
execute("chown", "-R", "#{fetch(:postgres_uid)}:#{fetch(:postgres_gid)}",
|
96
|
+
fetch(:postgres_root_path))
|
97
|
+
# chmod data_path
|
98
|
+
execute "find", fetch(:postgres_data_path), "-type", "d",
|
99
|
+
"-exec", "chmod", "2700", "{}", "+"
|
100
|
+
execute "find", fetch(:postgres_data_path), "-type", "f",
|
101
|
+
"-exec", "chmod", "0600", "{}", "+"
|
102
|
+
# chmod everything but data_path
|
103
|
+
execute "find", fetch(:postgres_root_path), "-type", "d",
|
104
|
+
"-not", "-path", "\"#{fetch(:postgres_data_path)}\"",
|
105
|
+
"-not", "-path", "\"#{fetch(:postgres_data_path)}/*\"",
|
106
|
+
"-exec", "chmod", "2775", "{}", "+"
|
107
|
+
execute "find", fetch(:postgres_root_path), "-type", "f",
|
108
|
+
"-not", "-path", "\"#{fetch(:postgres_data_path)}\"",
|
109
|
+
"-not", "-path", "\"#{fetch(:postgres_data_path)}/*\"",
|
110
|
+
"-exec", "chmod", "0660", "{}", "+"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
after 'pg:install_config_files', 'pg:check:file_permissions'
|
115
|
+
|
116
|
+
task :firewall => ['pg:ensure_setup', 'postgresinator:deployment_user'] do
|
117
|
+
on roles(:db, :db_slave, :in => :parallel) do |host|
|
118
|
+
as "root" do
|
119
|
+
if test "ufw", "status"
|
120
|
+
success = test("ufw", "allow", "#{host.properties.postgres_port}/tcp")
|
121
|
+
fatal "Error during opening UFW firewall" and exit unless success
|
122
|
+
else
|
123
|
+
warn "Uncomplicated Firewall does not appear to be installed, making no firewall action."
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
@@ -1,155 +1,106 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Capistrano
|
2
|
+
module TaskEnhancements
|
3
|
+
alias_method :pg_original_default_tasks, :default_tasks
|
4
|
+
def default_tasks
|
5
|
+
pg_original_default_tasks + [
|
6
|
+
'postgresinator:write_built_in',
|
7
|
+
'postgresinator:write_example_configs',
|
8
|
+
'postgresinator:write_example_configs:in_place'
|
9
|
+
]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
3
13
|
|
4
14
|
namespace :postgresinator do
|
5
15
|
|
6
|
-
|
16
|
+
set :example, "_example"
|
17
|
+
|
18
|
+
desc "Write example config files (with '_example' appended to their names)."
|
7
19
|
task :write_example_configs do
|
8
20
|
run_locally do
|
9
|
-
execute "mkdir", "-p", "config/deploy",
|
21
|
+
execute "mkdir", "-p", "config/deploy", fetch(:postgres_templates_path, 'templates/postgres')
|
10
22
|
{
|
11
|
-
'examples/Capfile'
|
12
|
-
'examples/config/deploy.rb'
|
13
|
-
'examples/config/
|
14
|
-
'examples/
|
15
|
-
'examples/
|
16
|
-
'examples/
|
17
|
-
'examples/
|
18
|
-
'examples/pg_hba.conf.erb' => 'templates/postgresql/pg_hba_example.conf.erb',
|
19
|
-
'examples/recovery.conf.erb' => 'templates/postgresql/recovery_example.conf.erb'
|
23
|
+
'examples/Capfile' => "Capfile#{fetch(:example)}",
|
24
|
+
'examples/config/deploy.rb' => "config/deploy#{fetch(:example)}.rb",
|
25
|
+
'examples/config/deploy/staging.rb' => "config/deploy/staging#{fetch(:example)}.rb",
|
26
|
+
'examples/Dockerfile' => "#{fetch(:postgres_templates_path, 'templates/postgres')}/Dockerfile#{fetch(:example)}",
|
27
|
+
'examples/postgresql.conf.erb' => "#{fetch(:postgres_templates_path, 'templates/postgres')}/postgresql#{fetch(:example)}.conf.erb",
|
28
|
+
'examples/pg_hba.conf.erb' => "#{fetch(:postgres_templates_path, 'templates/postgres')}/pg_hba#{fetch(:example)}.conf.erb",
|
29
|
+
'examples/recovery.conf.erb' => "#{fetch(:postgres_templates_path, 'templates/postgres')}/recovery#{fetch(:example)}.conf.erb"
|
20
30
|
}.each do |source, destination|
|
21
31
|
config = File.read(File.dirname(__FILE__) + "/#{source}")
|
22
32
|
File.open("./#{destination}", 'w') { |f| f.write(config) }
|
23
33
|
info "Wrote '#{destination}'"
|
24
34
|
end
|
25
|
-
|
35
|
+
unless fetch(:example).empty?
|
36
|
+
info "Now remove the '#{fetch(:example)}' portion of their names or diff with existing files and add the needed lines."
|
37
|
+
end
|
26
38
|
end
|
27
39
|
end
|
28
40
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
task :load_settings do
|
35
|
-
cluster = Hashie::Mash.new()
|
36
|
-
cluster.image = {}
|
37
|
-
set :pg_image_name, -> { fetch(:postgres_image_name) }
|
38
|
-
cluster.image.name = fetch(:pg_image_name)
|
39
|
-
set :pg_config_files, -> { fetch(:postgres_config_files) }
|
40
|
-
cluster.image.config_files = fetch(:pg_config_files)
|
41
|
-
set :pg_data_path, -> { fetch(:postgres_data_path) }
|
42
|
-
cluster.image.data_path = fetch(:pg_data_path)
|
43
|
-
set :pg_conf_path, -> { fetch(:postgres_conf_path) }
|
44
|
-
cluster.image.conf_path = fetch(:pg_conf_path)
|
45
|
-
set :pg_sock_path, -> { fetch(:postgres_sock_path) }
|
46
|
-
cluster.image.sock_path = fetch(:pg_sock_path)
|
47
|
-
set :pg_uid, -> { fetch(:postgres_uid) }
|
48
|
-
cluster.image.postgres_uid = fetch(:pg_uid)
|
49
|
-
set :pg_gid, -> { fetch(:postgres_gid) }
|
50
|
-
cluster.image.postgres_gid = fetch(:pg_gid)
|
51
|
-
set :pg_databases, -> { fetch(:databases) }
|
52
|
-
cluster.databases = fetch(:pg_databases)
|
53
|
-
set :pg_servers, -> { fetch(:servers) }
|
54
|
-
cluster.servers = fetch(:pg_servers)
|
55
|
-
|
56
|
-
cluster.ssh_user = ENV["USER"]
|
57
|
-
cluster.servers.each do |server|
|
58
|
-
server.ip = Resolv.getaddress(server.domain)
|
59
|
-
master_or_slave = server.master ? "master" : "slave"
|
60
|
-
server.master_domain = cluster.servers.collect { |s| s.domain if s.master }.first
|
61
|
-
server.master_ip = Resolv.getaddress(server.master_domain)
|
62
|
-
server.master_port = cluster.servers.collect { |s| s.port if s.master }.first
|
63
|
-
server.container_name = "#{server.master_domain}-postgres-#{server.port}-#{master_or_slave}"
|
64
|
-
server.data_path = "/#{server.container_name}-data"
|
65
|
-
server.conf_path = "/#{server.container_name}-conf"
|
66
|
-
server.docker_run_command = [
|
67
|
-
"--detach", "--tty", "--user", "postgres",
|
68
|
-
"--name", server.container_name,
|
69
|
-
"--volume", cluster.image.sock_path,
|
70
|
-
"--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
|
71
|
-
"--volume", "#{server.conf_path}:#{cluster.image.conf_path}:rw",
|
72
|
-
"--expose", "5432",
|
73
|
-
"--publish", "0.0.0.0:#{server.port}:5432",
|
74
|
-
"--restart", "always",
|
75
|
-
cluster.image.name
|
76
|
-
]
|
77
|
-
server.docker_init_command = [
|
78
|
-
"--rm", "--user", "root",
|
79
|
-
"--volume", "#{server.data_path}:/postgresql-data:rw",
|
80
|
-
"--entrypoint", "/usr/bin/rsync",
|
81
|
-
cluster.image.name, "-ah", "#{cluster.image.data_path}/", "/postgresql-data/"
|
82
|
-
]
|
83
|
-
server.docker_replicate_command = [
|
84
|
-
"--rm", "--user", "postgres",
|
85
|
-
"--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
|
86
|
-
"--entrypoint", "/usr/bin/pg_basebackup",
|
87
|
-
cluster.image.name,
|
88
|
-
"-w", "-h", server.master_domain, "-p", server.master_port,
|
89
|
-
"-U", "replicator", "-D", cluster.image.data_path, "-v", "-x"
|
90
|
-
]
|
41
|
+
desc 'Write example config files (will overwrite any existing config files).'
|
42
|
+
namespace :write_example_configs do
|
43
|
+
task :in_place do
|
44
|
+
set :example, ""
|
45
|
+
Rake::Task['postgresinator:write_example_configs'].invoke
|
91
46
|
end
|
92
|
-
@cluster = cluster
|
93
47
|
end
|
94
48
|
|
95
|
-
|
96
|
-
|
49
|
+
desc 'Write a file showing the built-in overridable settings.'
|
50
|
+
task :write_built_in do
|
97
51
|
run_locally do
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
52
|
+
{
|
53
|
+
'built-in.rb' => 'built-in.rb',
|
54
|
+
}.each do |source, destination|
|
55
|
+
config = File.read(File.dirname(__FILE__) + "/#{source}")
|
56
|
+
File.open("./#{destination}", 'w') { |f| f.write(config) }
|
57
|
+
info "Wrote '#{destination}'"
|
58
|
+
end
|
59
|
+
info "Now examine the file and copy-paste into your deploy.rb or <stage>.rb and customize."
|
103
60
|
end
|
104
61
|
end
|
105
62
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
63
|
+
# These are the only two tasks using :preexisting_ssh_user
|
64
|
+
namespace :deployment_user do
|
65
|
+
#desc "Setup or re-setup the deployment user, idempotently"
|
66
|
+
task :setup do
|
67
|
+
on roles(:all) do |h|
|
68
|
+
on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
|
69
|
+
as :root do
|
70
|
+
deployment_user_setup(fetch(:postgres_templates_path))
|
71
|
+
end
|
72
|
+
end
|
113
73
|
end
|
114
|
-
fatal "Config file #{args.config_file} not found in the configuration" and raise unless config_file_found
|
115
|
-
config_template_found = test("ls", "-A", "templates/postgresql/#{args.config_file}.erb")
|
116
|
-
fatal "Config template file templates/postgresql/#{args.config_file}.erb not found locally" and raise unless config_template_found
|
117
74
|
end
|
118
75
|
end
|
119
76
|
|
120
|
-
task :
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
77
|
+
task :deployment_user do
|
78
|
+
on roles(:all) do |h|
|
79
|
+
on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
|
80
|
+
as :root do
|
81
|
+
if unix_user_exists?(fetch(:deployment_username))
|
82
|
+
info "User #{fetch(:deployment_username)} already exists. You can safely re-setup the user with 'postgresinator:deployment_user:setup'."
|
83
|
+
else
|
84
|
+
Rake::Task['postgresinator:deployment_user:setup'].invoke
|
85
|
+
end
|
86
|
+
end
|
127
87
|
end
|
128
|
-
fatal "Database #{args.domain} not found in the configuration" and raise unless database_found
|
129
88
|
end
|
130
89
|
end
|
131
90
|
|
132
|
-
task :
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
cluster.servers.each do |server|
|
137
|
-
next unless server.domain == args.domain
|
138
|
-
domain_found = true
|
91
|
+
task :webserver_user do
|
92
|
+
on roles(:all) do
|
93
|
+
as :root do
|
94
|
+
unix_user_add(fetch(:webserver_username)) unless unix_user_exists?(fetch(:webserver_username))
|
139
95
|
end
|
140
|
-
fatal "Server domain #{args.domain} not found in the configuration" and raise unless domain_found
|
141
96
|
end
|
142
97
|
end
|
143
98
|
|
144
|
-
task :
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
cluster.databases.each do |database|
|
149
|
-
next unless database.db_role == args.role_name
|
150
|
-
role_found = true
|
99
|
+
task :file_permissions => [:deployment_user, :webserver_user] do
|
100
|
+
on roles(:app) do
|
101
|
+
as :root do
|
102
|
+
setup_file_permissions
|
151
103
|
end
|
152
|
-
fatal "Role #{args.role_name} not found in the configuration" and raise unless role_found
|
153
104
|
end
|
154
105
|
end
|
155
106
|
|