postgresinator 0.0.5 → 0.1.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.
@@ -1,36 +1,28 @@
1
1
  require 'resolv'
2
2
  require 'hashie'
3
3
 
4
- namespace :pg do
4
+ namespace :postgresinator do
5
5
 
6
6
  desc 'Write example config files'
7
7
  task :write_example_configs do
8
8
  run_locally do
9
- execute "mkdir -p ./templates/postgresql"
10
-
11
- # example postgresinator.rb
12
- config = File.read(File.dirname(__FILE__) + '/examples/postgresinator_example.rb')
13
- File.open('./postgresinator_example.rb', 'w') { |f| f.write(config) }
14
- info "Wrote './postgresinator_example.rb'"
15
- info "Run `mv postgresinator_example.rb postgrestinator.rb` or diff those files and add the needed lines."
16
-
17
- # example postgresql.conf.erb
18
- config = File.read(File.dirname(__FILE__) + '/examples/postgresql_example.conf.erb')
19
- File.open('./templates/postgresql/postgresql_example.conf.erb', 'w') { |f| f.write(config) }
20
- info "Wrote './templates/postgresql/postgres_example.conf.erb'"
21
- info "Run `mv templates/postgresql/postgresql_example.conf.erb templates/postgresql/postgresql.conf.erb` or diff those files and add the needed lines."
22
-
23
- # example pg_hba.conf.erb
24
- config = File.read(File.dirname(__FILE__) + '/examples/pg_hba_example.conf.erb')
25
- File.open('./templates/postgresql/pg_hba_example.conf.erb', 'w') { |f| f.write(config) }
26
- info "Wrote './templates/postgresql/pg_hba_example.conf.erb'"
27
- info "Run `mv templates/postgresql/pg_hba_example.conf.erb templates/postgresql/pg_hba.conf.erb` or diff those files and add the needed lines."
28
-
29
- # example recovery.conf.erb
30
- config = File.read(File.dirname(__FILE__) + '/examples/recovery_example.conf.erb')
31
- File.open('./templates/postgresql/recovery_example.conf.erb', 'w') { |f| f.write(config) }
32
- info "Wrote './templates/postgresql/recovery_example.conf.erb'"
33
- info "Run `mv templates/postgresql/recovery_example.conf.erb templates/postgresql/recovery.conf.erb` or diff those files and add the needed lines."
9
+ execute "mkdir", "-p", "config/deploy", "templates/postgresql"
10
+ {
11
+ 'examples/Capfile' => 'Capfile_example',
12
+ 'examples/config/deploy.rb' => 'config/deploy_example.rb',
13
+ 'examples/config/deploy_postgresinator.rb' => 'config/deploy_postgresinator_example.rb',
14
+ 'examples/config/deploy/staging.rb' => 'config/deploy/staging_example.rb',
15
+ 'examples/config/deploy/staging_postgresinator.rb' => 'config/deploy/staging_postgresinator_example.rb',
16
+ 'examples/Dockerfile' => 'templates/postgresql/Dockerfile_example',
17
+ 'examples/postgresql.conf.erb' => 'templates/postgresql/postgresql_example.conf.erb',
18
+ 'examples/pg_hba.conf.erb' => 'templates/postgresql/pg_hba_example.conf.erb',
19
+ 'examples/recovery.conf.erb' => 'templates/postgresql/recovery_example.conf.erb'
20
+ }.each do |source, destination|
21
+ config = File.read(File.dirname(__FILE__) + "/#{source}")
22
+ File.open("./#{destination}", 'w') { |f| f.write(config) }
23
+ info "Wrote '#{destination}'"
24
+ end
25
+ info "Now remove the '_example' portion of their names or diff with existing files and add the needed lines."
34
26
  end
35
27
  end
36
28
 
@@ -38,16 +30,37 @@ end
38
30
 
39
31
  namespace :config do
40
32
 
33
+ # TODO refactor to load all settings via capistrano configs
41
34
  task :load_settings do
42
- cluster = Hashie::Mash.new(PostgresCluster.settings)
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
+
43
56
  cluster.ssh_user = ENV["USER"]
44
57
  cluster.servers.each do |server|
45
58
  server.ip = Resolv.getaddress(server.domain)
46
- server.master_or_slave = server.master ? "master" : "slave"
59
+ master_or_slave = server.master ? "master" : "slave"
47
60
  server.master_domain = cluster.servers.collect { |s| s.domain if s.master }.first
48
61
  server.master_ip = Resolv.getaddress(server.master_domain)
49
62
  server.master_port = cluster.servers.collect { |s| s.port if s.master }.first
50
- server.container_name = "#{server.master_domain}-postgres-#{server.port}-#{server.master_or_slave}"
63
+ server.container_name = "#{server.master_domain}-postgres-#{server.port}-#{master_or_slave}"
51
64
  server.data_path = "/#{server.container_name}-data"
52
65
  server.conf_path = "/#{server.container_name}-conf"
53
66
  server.docker_run_command = [
@@ -79,7 +92,7 @@ namespace :config do
79
92
  @cluster = cluster
80
93
  end
81
94
 
82
- task :ensure_cluster_data_uniqueness => :load_settings do
95
+ task :ensure_cluster_data_uniqueness do
83
96
  cluster = @cluster
84
97
  run_locally do
85
98
  names = cluster.servers.collect { |s| s.container_name }
@@ -133,7 +146,7 @@ namespace :config do
133
146
  run_locally do
134
147
  role_found = false
135
148
  cluster.databases.each do |database|
136
- next unless database.role == args.role_name
149
+ next unless database.db_role == args.role_name
137
150
  role_found = true
138
151
  end
139
152
  fatal "Role #{args.role_name} not found in the configuration" and raise unless role_found
@@ -0,0 +1,27 @@
1
+ # Load DSL and Setup Up Stages
2
+ require 'capistrano/setup'
3
+
4
+ # Includes default deployment tasks
5
+ require 'capistrano/deploy'
6
+
7
+ # Includes tasks from other gems included in your Gemfile
8
+ #
9
+ # For documentation on these, see for example:
10
+ #
11
+ # https://github.com/capistrano/rvm
12
+ # https://github.com/capistrano/rbenv
13
+ # https://github.com/capistrano/chruby
14
+ # https://github.com/capistrano/bundler
15
+ # https://github.com/capistrano/rails
16
+ #
17
+ # require 'capistrano/rvm'
18
+ # require 'capistrano/rbenv'
19
+ # require 'capistrano/chruby'
20
+ # require 'capistrano/bundler'
21
+ # require 'capistrano/rails/assets'
22
+ # require 'capistrano/rails/migrations'
23
+
24
+ require 'postgresinator'
25
+
26
+ # Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
27
+ Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
@@ -0,0 +1,11 @@
1
+ # vi: ft=config
2
+ FROM ubuntu:12.04
3
+ MAINTAINER david amick <docker@davidamick.com>
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"
7
+
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"]
@@ -0,0 +1,50 @@
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'
@@ -0,0 +1,43 @@
1
+ ## For a standard Ubuntu 12.04 Nginx Docker image you should only
2
+ ## need to change the following values to get started:
3
+
4
+ set :domain, "my-app.example.com"
5
+ set :postgres_image_name, "snarlysodboxer/postgresql:0.0.1"
6
+ set :postgres_config_files, ["postgresql.conf", "pg_hba.conf", "recovery.conf"]
7
+ set :postgres_data_path, "/var/lib/postgresql/9.1/main"
8
+ set :postgres_conf_path, "/etc/postgresql/9.1/main"
9
+ set :postgres_sock_path, "/var/run/postgresql"
10
+ set :postgres_uid, "101"
11
+ set :postgres_gid, "104"
12
+ set :databases, [
13
+ {
14
+ "name" => "client",
15
+ "db_role" => "client",
16
+ "pass" => "client"
17
+ }
18
+ ]
19
+ set :servers, -> {
20
+ [
21
+ {
22
+ "master" => true,
23
+ "domain" => fetch(:domain),
24
+ "port" => "5432"
25
+ },
26
+ {
27
+ "master" => false,
28
+ "domain" => "my-app-other.example.com",
29
+ "port" => "5433"
30
+ }
31
+ ]
32
+ }
33
+
34
+
35
+
36
+ ## The values below may be commonly changed to match specifics
37
+ ## relating to a particular Docker image or setup:
38
+
39
+
40
+
41
+ ## The values below are not meant to be changed and shouldn't
42
+ ## need to be under the majority of circumstances:
43
+
@@ -0,0 +1,60 @@
1
+ # config valid only for Capistrano 3.1
2
+ lock '3.2.1'
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'
@@ -0,0 +1 @@
1
+ # Only stage-specific postgresinator config options are needed.
@@ -1,12 +1,10 @@
1
1
  require 'erb'
2
2
 
3
- require './postgresinator.rb' if File.exists?('./postgresinator.rb')
4
-
5
3
  ## NOTES:
6
4
  # tasks without 'desc' description lines are for manual debugging of this
7
5
  # deployment code.
8
6
  #
9
- # we've choosen to only pass strings (if anything) to tasks. this allows tasks to be
7
+ # only pass strings (if anything) to tasks. this allows tasks to be
10
8
  # debugged individually. only private methods take ruby objects.
11
9
 
12
10
  namespace :pg do
@@ -70,9 +68,9 @@ namespace :pg do
70
68
  Rake::Task['pg:create_role'].reenable
71
69
  end
72
70
  cluster.databases.each do |database|
73
- unless pg_role_exists?(cluster, server, database.role)
74
- info "Creating role #{database.role} on #{server.domain}"
75
- Rake::Task['pg:create_role'].invoke(server.domain, database.role)
71
+ unless pg_role_exists?(cluster, server, database.db_role)
72
+ info "Creating role #{database.db_role} on #{server.domain}"
73
+ Rake::Task['pg:create_role'].invoke(server.domain, database.db_role)
76
74
  Rake::Task['pg:create_role'].reenable
77
75
  end
78
76
  unless pg_database_exists?(cluster, server, database)
@@ -351,7 +349,7 @@ namespace :pg do
351
349
  server = cluster.servers.select { |s| s.domain == args.domain }.first
352
350
  on "#{cluster.ssh_user}@#{args.domain}" do
353
351
  execute("echo", "\"CREATE", "DATABASE", "\\\"#{database.name}\\\"",
354
- "WITH", "OWNER", "\\\"#{database.role}\\\"", "TEMPLATE",
352
+ "WITH", "OWNER", "\\\"#{database.db_role}\\\"", "TEMPLATE",
355
353
  "template0", "ENCODING", "'UTF8';\"", "|",
356
354
  "docker", "run", "--rm", "--interactive",
357
355
  "--entrypoint", "/bin/bash",
@@ -367,7 +365,7 @@ namespace :pg do
367
365
  server = cluster.servers.select { |s| s.domain == args.domain }.first
368
366
  on "#{cluster.ssh_user}@#{args.domain}" do
369
367
  execute("echo", "\"GRANT", "ALL", "PRIVILEGES", "ON", "DATABASE",
370
- "\\\"#{database.name}\\\"", "to", "\\\"#{database.role}\\\";\"", "|",
368
+ "\\\"#{database.name}\\\"", "to", "\\\"#{database.db_role}\\\";\"", "|",
371
369
  "docker", "run", "--rm", "--interactive",
372
370
  "--entrypoint", "/bin/bash",
373
371
  "--volumes-from", server.container_name,
@@ -389,7 +387,11 @@ namespace :pg do
389
387
  "--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
390
388
  cluster.image.name, "-s", "/etc/ssl/certs/ssl-cert-snakeoil.pem", inner_server_crt
391
389
  )
392
- execute("chown", "root.", outer_server_crt)
390
+ execute("docker", "run",
391
+ "--rm", "--user", "root", "--entrypoint", "/bin/chown",
392
+ "--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
393
+ cluster.image.name, "root:root", inner_server_crt
394
+ )
393
395
  end
394
396
  inner_server_key = "#{cluster.image.data_path}/server.key"
395
397
  outer_server_key = "#{server.data_path}/server.key"
@@ -399,7 +401,11 @@ namespace :pg do
399
401
  "--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
400
402
  cluster.image.name, "-s", "/etc/ssl/private/ssl-cert-snakeoil.key", inner_server_key
401
403
  )
402
- execute("chown", "root.", outer_server_key)
404
+ execute("docker", "run",
405
+ "--rm", "--user", "root", "--entrypoint", "/bin/chown",
406
+ "--volume", "#{server.data_path}:#{cluster.image.data_path}:rw",
407
+ cluster.image.name, "root:root", inner_server_key
408
+ )
403
409
  end
404
410
  end
405
411
  end
@@ -448,14 +454,14 @@ namespace :pg do
448
454
  ERB.new(File.new(template_path).read).result(binding)
449
455
  end
450
456
 
451
- def pg_role_exists?(cluster, server, role)
452
- test("echo", "\"SELECT", "*", "FROM", "pg_user", "WHERE", "usename", "=", "'#{role}';\"", "|",
457
+ def pg_role_exists?(cluster, server, db_role)
458
+ test("echo", "\"SELECT", "*", "FROM", "pg_user", "WHERE", "usename", "=", "'#{db_role}';\"", "|",
453
459
  "docker", "run", "--rm", "--interactive",
454
460
  "--entrypoint", "/bin/bash",
455
461
  "--volumes-from", server.container_name,
456
462
  cluster.image.name,
457
463
  "-c", "'/usr/bin/psql", "-U", "postgres'", "|",
458
- "grep", "-q", "'#{role}'")
464
+ "grep", "-q", "'#{db_role}'")
459
465
  end
460
466
 
461
467
  def pg_database_exists?(cluster, server, database)
@@ -1,6 +1,5 @@
1
- require 'rake'
2
- require 'sshkit'
3
- require 'sshkit/dsl'
1
+ require 'capistrano/setup'
2
+ require 'capistrano/deploy'
4
3
 
5
4
  load 'postgresinator/pg.rb'
6
5
  load 'postgresinator/config.rb'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: postgresinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-05 00:00:00.000000000 Z
12
+ date: 2014-11-11 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.1
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rake
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -68,10 +84,15 @@ files:
68
84
  - lib/postgresinator.rb
69
85
  - lib/postgresinator/pg.rb
70
86
  - lib/postgresinator/config.rb
71
- - lib/postgresinator/examples/postgresinator_example.rb
72
- - lib/postgresinator/examples/postgresql_example.conf.erb
73
- - lib/postgresinator/examples/pg_hba_example.conf.erb
74
- - lib/postgresinator/examples/recovery_example.conf.erb
87
+ - lib/postgresinator/examples/Dockerfile
88
+ - lib/postgresinator/examples/Capfile
89
+ - lib/postgresinator/examples/config/deploy.rb
90
+ - lib/postgresinator/examples/config/deploy_postgresinator.rb
91
+ - lib/postgresinator/examples/config/deploy/staging.rb
92
+ - lib/postgresinator/examples/config/deploy/staging_postgresinator.rb
93
+ - lib/postgresinator/examples/postgresql.conf.erb
94
+ - lib/postgresinator/examples/pg_hba.conf.erb
95
+ - lib/postgresinator/examples/recovery.conf.erb
75
96
  homepage: https://github.com/snarlysodboxer/postgresinator
76
97
  licenses:
77
98
  - GNU
@@ -1,35 +0,0 @@
1
- class PostgresCluster
2
- def self.settings
3
- {
4
- "image" => {
5
- "name" => "snarlysodboxer/postgresql:0.0.1",
6
- "config_files" => ["postgresql.conf", "pg_hba.conf", "recovery.conf"],
7
- "data_path" => "/var/lib/postgresql/9.1/main",
8
- "conf_path" => "/etc/postgresql/9.1/main",
9
- "sock_path" => "/var/run/postgresql",
10
- "postgres_uid" => "101",
11
- "postgres_gid" => "104"
12
-
13
- },
14
- "databases" => [
15
- {
16
- "name" => "client",
17
- "role" => "client",
18
- "pass" => "client"
19
- }
20
- ],
21
- "servers" => [
22
- {
23
- "master" => true,
24
- "domain" => "client.example.com",
25
- "port" => "5432"
26
- },
27
- {
28
- "master" => false,
29
- "domain" => "client-other.example.com",
30
- "port" => "5433"
31
- }
32
- ]
33
- }
34
- end
35
- end