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.
@@ -0,0 +1,126 @@
1
+ namespace :pg do
2
+ namespace :db do
3
+
4
+ #desc "Idempotently setup one or more databases."
5
+ task :setup => ['pg:ensure_setup'] do
6
+ on roles(:db) do |host|
7
+ fetch(:postgres_databases).each do |database|
8
+ Rake::Task['pg:check:settings:database'].invoke(database[:name])
9
+ Rake::Task['pg:check:settings:database'].reenable
10
+ unless pg_role_exists?(database[:db_role])
11
+ info "Creating role #{database[:db_role]} on #{host}"
12
+ pg_create_role(database[:db_role], database[:pass])
13
+ end
14
+ unless pg_database_exists?(database[:name])
15
+ info "Creating database #{database[:name]} on #{host}"
16
+ pg_create_database(database)
17
+ pg_grant_database(database)
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ desc "Restore 'dump_file' in /tmp on the master server into 'database_name'."
24
+ task :restore, [:dump_file, :database_name] => ['pg:ensure_setup'] do |t, args|
25
+ on roles(:db) do |host|
26
+ if pg_database_empty?(args.database_name)
27
+ clean = ""
28
+ else
29
+ pg_confirm_database_overwrite?(args.database_name) ? clean = "--clean" : exit(0)
30
+ end
31
+ pg_restore(host, args, clean)
32
+ end
33
+ end
34
+
35
+ desc "Dump 'database_name' into /tmp/'dump_file' on the master server."
36
+ task :dump, [:dump_file, :database_name] => ['pg:ensure_setup'] do |t, args|
37
+ on roles(:db) do |host|
38
+ if file_exists?("/tmp/#{args.dump_file}")
39
+ exit unless(pg_confirm_file_overwrite?(args.dump_file))
40
+ end
41
+ pg_dump(host, args)
42
+ end
43
+ end
44
+
45
+ desc "Enter psql interactive mode on the master."
46
+ task :interactive => 'pg:ensure_setup' do
47
+ on roles(:db) do |host|
48
+ info "Entering psql interactive mode inside #{host.properties.postgres_container_name} on #{host}"
49
+ system pg_interactive(host)
50
+ end
51
+ end
52
+
53
+ namespace :interactive do
54
+ desc "Print the command to enter psql interactive mode on the master."
55
+ task :print => 'pg:ensure_setup' do
56
+ on roles(:db) do |host|
57
+ info ["You can paste the following command into a terminal on #{host}",
58
+ "to enter psql interactive mode for",
59
+ "#{host.properties.postgres_container_name}:"].join(' ')
60
+ info pg_interactive_print(host)
61
+ end
62
+ end
63
+ end
64
+
65
+ desc "List the databases from the master."
66
+ task :list => ['pg:ensure_setup'] do |t, args|
67
+ on roles(:db) do
68
+ pg_list_databases(host)
69
+ end
70
+ end
71
+
72
+ namespace :list do
73
+ desc "List the roles from the master."
74
+ task :roles => ['pg:ensure_setup'] do |t, args|
75
+ on roles(:db) do
76
+ pg_list_roles(host)
77
+ end
78
+ end
79
+ end
80
+
81
+ desc "Show the streaming replication status of each instance."
82
+ task :streaming => ['pg:ensure_setup'] do
83
+ on roles(:db) do |host|
84
+ info ""
85
+ info "Streaming status of #{host.properties.postgres_container_name} on #{host}:"
86
+ pg_streaming_master(host)
87
+ end
88
+ on roles(:db_slave, :in => :parallel) do
89
+ info ""
90
+ info "Streaming status of #{host.properties.postgres_container_name} on #{host}:"
91
+ pg_streaming_slave(host)
92
+ end
93
+ end
94
+
95
+
96
+ def pg_confirm_file_overwrite?(dump_file)
97
+ warn "A file named #{dump_file} already exists on #{host} in /tmp. If you continue, you will overwrite it."
98
+ ask :yes_or_no, "Are you positive?"
99
+ case fetch(:yes_or_no).chomp.downcase
100
+ when "yes"
101
+ true
102
+ when "no"
103
+ false
104
+ else
105
+ warn "Please enter 'yes' or 'no'"
106
+ pg_confirm_file_overwrite?(dump_file)
107
+ end
108
+ end
109
+
110
+ def pg_confirm_database_overwrite?(database_name)
111
+ warn "There is already data in the database '#{database_name}' on #{host} in the container " +
112
+ "'#{host.properties.postgres_container_name}' which stores it's data in #{fetch(:postgres_data_path)} on the host."
113
+ warn "If you continue, you must be positive you want to overwrite the existing data."
114
+ ask :yes_or_no, "Are you positive?"
115
+ case fetch(:yes_or_no).chomp.downcase
116
+ when "yes"
117
+ true
118
+ when "no"
119
+ false
120
+ else
121
+ warn "Please enter 'yes' or 'no'"
122
+ pg_confirm_database_overwrite?(database_name)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -2,7 +2,7 @@
2
2
  require 'capistrano/setup'
3
3
 
4
4
  # Includes default deployment tasks
5
- require 'capistrano/deploy'
5
+ #require 'capistrano/deploy'
6
6
 
7
7
  # Includes tasks from other gems included in your Gemfile
8
8
  #
@@ -2,10 +2,11 @@
2
2
  FROM ubuntu:12.04
3
3
  MAINTAINER david amick <docker@davidamick.com>
4
4
 
5
- RUN /bin/bash -l -c "apt-get update -qq && apt-get install -qy postgresql-9.1 libpq-dev postgresql-contrib nodejs rsync"
6
- RUN /bin/bash -l -c "/etc/init.d/postgresql start && /etc/init.d/postgresql stop"
5
+ RUN ["/bin/bash", "-c", "apt-get update -qq && apt-get install -qy postgresql-9.1 libpq-dev postgresql-contrib nodejs rsync"]
6
+ RUN ["/bin/bash", "-c", "/etc/init.d/postgresql start && /etc/init.d/postgresql stop"]
7
+ RUN ["/bin/bash", "-c", "usermod -a -G www-data postgres"]
8
+ RUN ["/bin/bash", "-c", "rm /etc/ssl/certs/ssl-cert-snakeoil.pem"]
9
+ RUN ["/bin/bash", "-c", "rm /etc/ssl/private/ssl-cert-snakeoil.key"]
7
10
 
8
- EXPOSE 5432
9
- USER postgres
10
- ENTRYPOINT ["/usr/lib/postgresql/9.1/bin/postgres"]
11
- CMD ["-D", "/var/lib/postgresql/9.1/main", "-c", "config_file=/etc/postgresql/9.1/main/postgresql.conf"]
11
+ ENTRYPOINT ["/bin/bash"]
12
+ CMD ["-l"]
@@ -1,50 +1,29 @@
1
- # Simple Role Syntax
2
- # ==================
3
- # Supports bulk-adding hosts to roles, the primary server in each group
4
- # is considered to be the first unless any hosts have the primary
5
- # property set. Don't declare `role :all`, it's a meta role.
6
-
7
- set :domain, "my-app.example.com"
8
- set :deploy_username, "deployer"
9
- set :user_host, "#{fetch(:deploy_username)}@#{fetch(:domain)}"
10
-
11
- role :app, fetch(:user_host)
12
- role :web, fetch(:user_host)
13
- role :db, fetch(:user_host)
14
-
15
- # Extended Server Syntax
16
- # ======================
17
- # This can be used to drop a more detailed server definition into the
18
- # server list. The second argument is a, or duck-types, Hash and is
19
- # used to set extended properties on the server.
20
-
21
- #server 'example.com', user: 'deploy', roles: %w{web app}, my_property: :my_value
22
-
23
-
24
- # Custom SSH Options
25
- # ==================
26
- # You may pass any option but keep in mind that net/ssh understands a
27
- # limited set of options, consult[net/ssh documentation](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start).
28
- #
29
- # Global options
30
- # --------------
31
- # set :ssh_options, {
32
- # keys: %w(/home/rlisowski/.ssh/id_rsa),
33
- # forward_agent: false,
34
- # auth_methods: %w(password)
35
- # }
36
- #
37
- # And/or per server (overrides global)
38
- # ------------------------------------
39
- # server 'example.com',
40
- # user: 'user_name',
41
- # roles: %w{web app},
42
- # ssh_options: {
43
- # user: 'user_name', # overrides user setting above
44
- # keys: %w(/home/user_name/.ssh/id_rsa),
45
- # forward_agent: false,
46
- # auth_methods: %w(publickey password)
47
- # # password: 'please use keys'
48
- # }
49
-
50
- require './config/deploy/staging_postgresinator.rb'
1
+ ##### postgresinator
2
+ ### ------------------------------------------------------------------
3
+ set :domain, "my-app.example.com"
4
+ server fetch(:domain),
5
+ :user => fetch(:deployment_username),
6
+ :roles => ["app", "web", "db"],
7
+ :postgres_port => "5432"
8
+ server 'my-app-db-slave.example.com',
9
+ :user => fetch(:deployment_username),
10
+ :roles => ["db_slave"],
11
+ :no_release => true,
12
+ :postgres_port => "5433"
13
+ server 'my-app-db-slave2.example.com',
14
+ :user => fetch(:deployment_username),
15
+ :roles => ["db_slave"],
16
+ :no_release => true,
17
+ :postgres_port => "5433"
18
+ # only for override, let postgresinator setup postgres_container_name
19
+ #:postgres_container_name => "my_custom_name"
20
+ set :postgres_image_name, "snarlysodboxer/postgresql:0.0.1"
21
+ set :postgres_replicator_pass, "yourpassword"
22
+ set :postgres_databases, [
23
+ {
24
+ :name => "name",
25
+ :db_role => "role",
26
+ :pass => "pass"
27
+ }
28
+ ]
29
+ ### ------------------------------------------------------------------
@@ -1,60 +1,10 @@
1
- # config valid only for Capistrano 3.1
1
+ # config valid only for Capistrano 3.2.1
2
2
  lock '3.2.1'
3
3
 
4
- set :application, 'my_app_name'
5
- set :repo_url, 'git@example.com:me/my_repo.git'
6
-
7
- # Default branch is :master
8
- # ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
9
-
10
- # Default deploy_to directory is /var/www/my_app
11
- # set :deploy_to, '/var/www/my_app'
12
-
13
- # Default value for :scm is :git
14
- # set :scm, :git
15
-
16
- # Default value for :format is :pretty
17
- # set :format, :pretty
18
-
19
- # Default value for :log_level is :debug
20
- # set :log_level, :debug
21
-
22
- # Default value for :pty is false
23
- # set :pty, true
24
-
25
- # Default value for :linked_files is []
26
- # set :linked_files, %w{config/database.yml}
27
-
28
- # Default value for linked_dirs is []
29
- # set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
30
-
31
- # Default value for default_env is {}
32
- # set :default_env, { path: "/opt/ruby/bin:$PATH" }
33
-
34
- # Default value for keep_releases is 5
35
- # set :keep_releases, 5
36
-
37
- namespace :deploy do
38
-
39
- desc 'Restart application'
40
- task :restart do
41
- on roles(:app), in: :sequence, wait: 5 do
42
- # Your restart mechanism here, for example:
43
- # execute :touch, release_path.join('tmp/restart.txt')
44
- end
45
- end
46
-
47
- after :publishing, :restart
48
-
49
- after :restart, :clear_cache do
50
- on roles(:web), in: :groups, limit: 3, wait: 10 do
51
- # Here we can do anything such as:
52
- # within release_path do
53
- # execute :rake, 'cache:clear'
54
- # end
55
- end
56
- end
57
-
58
- end
59
-
60
- require './config/deploy_postgresinator.rb'
4
+ ##### postgresinator
5
+ ### ------------------------------------------------------------------
6
+ set :application, "my_app_name"
7
+ set :preexisting_ssh_user, ENV['USER']
8
+ set :deployment_username, "deployer"
9
+ set :webserver_username, "www-data" # needed for intergration w/ deployinator
10
+ ### ------------------------------------------------------------------
@@ -71,21 +71,19 @@
71
71
  # (autovacuum, daily cronjob, replication, and similar tasks).
72
72
  #
73
73
  # Database administrative login by UNIX sockets
74
- local all postgres ident
74
+ local all postgres trust
75
75
 
76
76
  # TYPE DATABASE USER CIDR-ADDRESS METHOD
77
- <% if @server.master %>
78
- <% @cluster.servers.each do |server| %>
79
- <% unless server.master %>
80
- hostssl replication replicator <%= server.ip %>/32 trust
81
- <% end %>
77
+ <% if host.has_role?(:db) %>
78
+ <% roles(:db_slave).each do |host| %>
79
+ hostssl replication replicator <%= host.properties.ip %>/32 trust
82
80
  <% end %>
83
81
  <% end %>
84
82
  host all postgres 172.16.0.0/12 trust # allow docker IPs for localhost access on the host
85
83
  host all all 172.16.0.0/12 md5
86
84
 
87
85
  # "local" is for Unix domain socket connections only
88
- local all all ident
86
+ #local all all ident
89
87
  # IPv4 local connections:
90
88
  host all all 127.0.0.1/32 md5
91
89
  # IPv6 local connections:
@@ -34,15 +34,15 @@
34
34
  # The default values of these variables are driven from the -D command-line
35
35
  # option or PGDATA environment variable, represented here as ConfigDir.
36
36
 
37
- data_directory = '<%= @cluster.image.data_path %>' # use data in another directory
37
+ data_directory = '<%= fetch(:postgres_data_path) %>' # use data in another directory
38
38
  # (change requires restart)
39
- hba_file = '<%= @cluster.image.conf_path %>/pg_hba.conf' # host-based authentication file
39
+ hba_file = '<%= fetch(:postgres_config_path) %>/pg_hba.conf' # host-based authentication file
40
40
  # (change requires restart)
41
- ident_file = '<%= @cluster.image.conf_path %>/pg_ident.conf' # ident configuration file
41
+ ident_file = '<%= fetch(:postgres_config_path) %>/pg_ident.conf' # ident configuration file
42
42
  # (change requires restart)
43
43
 
44
44
  # If external_pid_file is not explicitly set, no extra PID file is written.
45
- external_pid_file = '/var/run/postgresql/9.1-main.pid' # write an extra PID file
45
+ external_pid_file = '<%= fetch(:postgres_socket_path) %>/postgresql-9.1-main.pid' # write an extra PID file
46
46
  # (change requires restart)
47
47
 
48
48
  #------------------------------------------------------------------------------
@@ -59,7 +59,7 @@ wal_level = hot_standby
59
59
  max_wal_senders = 3
60
60
  checkpoint_segments = 8
61
61
  wal_keep_segments = 8
62
- <% unless @server.master %>
62
+ <% if host.has_role?(:db_slave) %>
63
63
  hot_standby = on
64
64
  <% end %>
65
65
  port = 5432 # (change requires restart)
@@ -68,7 +68,7 @@ max_connections = 100 # (change requires restart)
68
68
  # connection slot, plus lock space (see max_locks_per_transaction). You might
69
69
  # also need to raise shared_buffers to support more connections.
70
70
  #superuser_reserved_connections = 3 # (change requires restart)
71
- unix_socket_directory = '/var/run/postgresql' # (change requires restart)
71
+ unix_socket_directory = '<%= fetch(:postgres_socket_path) %>' # (change requires restart)
72
72
  #unix_socket_group = '' # (change requires restart)
73
73
  #unix_socket_permissions = 0777 # begin with 0 to use octal notation
74
74
  # (change requires restart)
@@ -1,3 +1,3 @@
1
1
  standby_mode = 'on'
2
- primary_conninfo = 'host=<%= @server.master_ip %> port=<%= @server.master_port %> user=replicator password=yourpassword sslmode=require'
3
- trigger_file = '<%= @cluster.image.data_path %>/postgresql.trigger'
2
+ primary_conninfo = 'host=<%= roles(:db).first.properties.ip %> port=<%= roles(:db).first.properties.postgres_port %> user=replicator password=<%= fetch(:postgres_replicator_pass) %> sslmode=require'
3
+ trigger_file = '<%= fetch(:postgres_data_path) %>/postgresql.trigger'