Merge branch 'feature/160-postgres_replication' of kosmos/chef into master

This commit is contained in:
Râu Cao 2020-05-14 13:10:34 +00:00
commit 3c905dd51e
24 changed files with 510 additions and 91 deletions

View File

@ -30,7 +30,7 @@ cookbook 'nginx', '= 9.0.0'
# part of Chef 14 (https://docs.chef.io/resource_build_essential.html)
cookbook 'build-essential', '~> 8.2.1'
cookbook 'mysql', '~> 8.5.1'
cookbook 'postgresql', '= 7.1.4'
cookbook 'postgresql', '= 7.1.8'
cookbook 'apt', '~> 7.0.0'
cookbook 'git', '= 6.0.0'
cookbook 'hostsfile', '= 2.4.5'

View File

@ -44,7 +44,7 @@ DEPENDENCIES
poise-ruby-build (~> 1.1.0)
poise-service (~> 1.5.2)
postfix (= 5.0.2)
postgresql (= 7.1.4)
postgresql (= 7.1.8)
redis
git: https://github.com/phlipper/chef-redis.git
revision: 7476279fc9c8727f082b8d77b5e1922dc2ef437b
@ -154,7 +154,7 @@ GRAPH
poise-service (1.5.2)
poise (~> 2.0)
postfix (5.0.2)
postgresql (7.1.4)
postgresql (7.1.8)
redis (0.5.6)
apt (>= 0.0.0)
seven_zip (3.1.1)

View File

@ -2,34 +2,52 @@
This file is used to list changes made in the last 3 major versions of the postgresql cookbook.
## Unreleased
## v7.1.8 (2020-02-22)
## v7.1.4 (28-03-2019)
- Fix incorrect ubuntu platform family value in `postgresql_server_install`
- Re-add unit tests that were skipped
## v7.1.7 (2020-02-21)
- Correctly configure postgres-common on Ubuntu hosts (fixes #596)
## v7.1.6 (2020-02-20)
- Remove unnecessary nil default in resource properties
- Migrate to GitHub Actions for testing
## v7.1.5 (2019-11-18)
- Allow to install extensions with hyphens, ex: `postgresql_extension '"uuid-ossp"'`
- Update Circle CI config to match sous-chefs defaults #617
- Remove Fedora testing from CI, not an official supported OS by sous-chefs, PR welcome #617
## v7.1.4 (2019-03-28)
- Fix installation of extensions.
## v7.1.3 (15-01-2019)
## v7.1.3 (2019-01-15)
- Added support for dash in database role name.
## v7.1.2 (06-01-2019)
## v7.1.2 (2019-06-01)
- Cleanup and update the user resource documentation and code. Removed extraneous 'sensitive' property which is a common property in all Chef resources.
- Change default permissions on the postgres.conf to be world readable so that psql can work.
## v7.1.1 (26-09-2018)
## v7.1.1 (2018-09-26)
- Rename slave to follower
- Use CircleCI for testing
- Simplyfy extension resource
## v7.1.0 (22-06-2018)
## v7.1.0 (2018-06-22)
- Update the `initdb` script to use initdb rather than a service. #542
- Refactor database commands to use the common connect method. #535
- Increase the unit test coverage.
## v7.0.0 (25-05-2018)
## v7.0.0 (2018-05-25)
_Breaking Change_ Please see UPGRADING.md and the README.md for information how to use.
@ -57,7 +75,7 @@ _Breaking Change_ Please see UPGRADING.md and the README.md for information how
## v6.1.2 (2018-04-16)
**this will be the last release of the 6.0 series before all recipes are removed from the cookbook**
this will be the last release of the 6.0 series before all recipes are removed from the cookbook
- Deprecate all recipes

View File

@ -2,10 +2,16 @@
[![Cookbook Version](https://img.shields.io/cookbook/v/postgresql.svg)](https://supermarket.chef.io/cookbooks/postgresql)
[![Build Status](https://img.shields.io/circleci/project/github/sous-chefs/postgresql/master.svg)](https://circleci.com/gh/sous-chefs/postgresql)
[![pullreminders](https://pullreminders.com/badge.svg)](https://pullreminders.com?ref=badge)
[![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors)
[![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0)
Installs and configures PostgreSQL as a client or a server.
## Maintainers
This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If youd like to know more please visit [sous-chefs.org](https://sous-chefs.org/) or come chat with us on the Chef Community Slack in [#sous-chefs](https://chefcommunity.slack.com/messages/C2V7B88SF).
## Upgrading
If you are wondering where all the recipes went in v7.0+, or how on earth I use this new cookbook please see upgrading.md for a full description.
@ -18,7 +24,6 @@ If you are wondering where all the recipes went in v7.0+, or how on earth I use
- Debian 7+
- Ubuntu 14.04+
- Red Hat/CentOS/Scientific 6+
- Fedora
### PostgreSQL version
@ -51,7 +56,7 @@ Name | Types | Description
`hba_file` | String | | `#{conf_dir}/main/pg_hba.conf` | no
`ident_file` | String | | `#{conf_dir}/main/pg_ident.conf` | no
`external_pid_file` | String | | `/var/run/postgresql/#{version}-main.pid` | no
`password` | String, nil | Pass in a password, or have the cookbook generate one for you | <random string> | no
`password` | String, nil | Pass in a password, or have the cookbook generate one for you | random string | no
#### Examples
@ -211,14 +216,14 @@ end
This generates the following line in the `pg_hba.conf`:
```
```config
# Local postgres superuser access
local all postgres ident
```
**Note**: The template by default generates a local access for Unix domain sockets only to support running the SQL execute resources. In Postgres version 9.1 and higher, the method is 'peer' instead of 'ident' which is identical. It looks like this:
```
```config
# "local" is for Unix domain socket connections only
local all all peer
```
@ -257,7 +262,7 @@ end
This generates the following line in the `pg_ident.conf`:
```
```config
# MAPNAME SYSTEM-USERNAME PG-USERNAME
# John Mapping
@ -279,7 +284,7 @@ end
This generates the following line in the `pg_hba.conf`:
```
```config
# Local postgres superuser access
host all foo 127.0.0.1/32 ident
```
@ -400,34 +405,27 @@ postgresql_server_conf 'PostgreSQL Config' do
end
```
## Contributing
## Contributors
Please refer to each project's style guidelines and guidelines for submitting patches and additions. In general, we follow the "fork-and-pull" Git workflow.
This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false)
1. **Fork** the repo on GitHub
2. **Clone** the project to your own machine
3. **Commit** changes to your own branch
4. **Push** your work back up to your fork
5. Submit a **Pull request** so that we can review your changes
### Backers
NOTE: Be sure to merge the latest from "upstream" before making a pull request!
Thank you to all our backers!
[Contribution informations for this project](CONTRIBUTING.md)
![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40)
## License
### Sponsors
Copyright 2010-2017, Chef Software, Inc.
Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
```text
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100)
![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100)

View File

@ -22,7 +22,7 @@ module PostgresqlCookbook
require 'securerandom'
def psql_command_string(new_resource, query, grep_for: nil, value_only: false)
cmd = "/usr/bin/psql -c \"#{query}\""
cmd = %(/usr/bin/psql -c "#{query}")
cmd << " -d #{new_resource.database}" if new_resource.database
cmd << " -U #{new_resource.user}" if new_resource.user
cmd << " --host #{new_resource.host}" if new_resource.host
@ -35,12 +35,12 @@ module PostgresqlCookbook
def execute_sql(new_resource, query)
# If we don't pass in a user to the resource
# default to the postgres user
user = new_resource.user ? new_resource.user : 'postgres'
user = new_resource.user || 'postgres'
# Query could be a String or an Array of Strings
statement = query.is_a?(String) ? query : query.join("\n")
cmd = shell_out(statement, user: user)
cmd = shell_out(statement, user: user, environment: psql_environment)
# Pass back cmd so we can decide what to do with it in the calling method.
cmd
@ -81,7 +81,7 @@ module PostgresqlCookbook
end
def create_extension_sql(new_resource)
sql = "CREATE EXTENSION IF NOT EXISTS #{new_resource.extension}"
sql = %(CREATE EXTENSION IF NOT EXISTS #{new_resource.extension})
sql << " FROM \"#{new_resource.old_version}\"" if new_resource.old_version
psql_command_string(new_resource, sql)
@ -213,6 +213,7 @@ module PostgresqlCookbook
"/usr/pgsql-#{new_resource.version}/bin/initdb"
end
cmd << " --locale '#{new_resource.initdb_locale}'" if new_resource.initdb_locale
cmd << " -E '#{new_resource.initdb_encoding}'" if new_resource.initdb_encoding
cmd << " -D '#{data_dir(new_resource.version)}'"
end
@ -239,6 +240,12 @@ module PostgresqlCookbook
platform?('amazon') ? '6' : '$releasever'
end
# Fedora doesn't seem to know the right symbols for psql
def psql_environment
return {} unless platform?('fedora')
{ LD_LIBRARY_PATH: '/usr/lib64' }
end
# Generate a password if the value is set to generate.
def postgres_password(new_resource)
new_resource.password == 'generate' ? secure_random : new_resource.password

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,7 @@ maintainer 'Sous Chefs'
maintainer_email 'help@sous-chefs.org'
license 'Apache-2.0'
description 'Installs and configures postgresql for clients or servers'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '7.1.4'
version '7.1.8'
source_url 'https://github.com/sous-chefs/postgresql'
issues_url 'https://github.com/sous-chefs/postgresql/issues'
chef_version '>= 13.8'

View File

@ -16,12 +16,12 @@
# limitations under the License.
#
property :access_type, String, required: true, default: 'local'
property :access_db, String, required: true, default: 'all'
property :access_user, String, required: true, default: 'postgres'
property :access_method, String, required: true, default: 'ident'
property :cookbook, String, default: 'postgresql'
property :source, String, default: 'pg_hba.conf.erb'
property :access_type, String, default: 'local'
property :access_db, String, default: 'all'
property :access_user, String, default: 'postgres'
property :access_method, String, default: 'ident'
property :cookbook, String, default: 'postgresql'
property :source, String, default: 'pg_hba.conf.erb'
property :access_addr, String
property :comment, String

View File

@ -23,7 +23,7 @@ property :owner, String
# Connection prefernces
property :user, String, default: 'postgres'
property :database, String, name_property: true
property :host, [String, nil], default: nil
property :host, String
property :port, Integer, default: 5432
action :create do

View File

@ -30,6 +30,7 @@ action :create do
code create_extension_sql(new_resource)
user 'postgres'
action :run
environment(psql_environment)
not_if { follower? || extension_installed?(new_resource) }
end
end
@ -39,6 +40,7 @@ action :drop do
code psql_command_string(new_resource, "DROP EXTENSION IF EXISTS \"#{new_resource.extension}\"")
user 'postgres'
action :run
environment(psql_environment)
not_if { follower? }
only_if { extension_installed?(new_resource) }
end

View File

@ -21,11 +21,11 @@ property :source, String, default: 'pg_ident.conf.erb'
property :cookbook, String, default: 'postgresql'
property :system_user, String, required: true
property :pg_user, String, required: true
property :comment, [String, nil], default: nil
property :comment, String
action :create do
ident_resource = new_resource
with_run_context :root do # ~FC037
with_run_context :root do
edit_resource(:template, "#{conf_dir}/pg_ident.conf") do |new_resource|
source new_resource.source
cookbook new_resource.cookbook

View File

@ -1,4 +1,3 @@
# frozen_string_literal: true
#
# Cookbook:: postgresql
# Resource:: server_install
@ -26,6 +25,7 @@ property :external_pid_file, String, default: lazy { "/var/run/postgresql/#{vers
property :password, [String, nil], default: 'generate' # Set to nil if we do not want to set a password
property :port, Integer, default: 5432
property :initdb_locale, String
property :initdb_encoding, String
# Connection preferences
property :user, String, default: 'postgres'
@ -41,6 +41,23 @@ action :install do
setup_repo new_resource.setup_repo
end
# First install the postgresql-common package
if platform_family?('debian')
package 'postgresql-common'
initdb_options = ''
initdb_options << "--locale #{new_resource.initdb_locale}" if new_resource.initdb_locale
initdb_options << " -E #{new_resource.initdb_encoding}" if new_resource.initdb_encoding
template '/etc/postgresql-common/createcluster.conf' do
source 'createcluster.conf.erb'
cookbook 'postgresql'
variables(
initdb_options: initdb_options
)
end
end
package server_pkg_name
end

View File

@ -40,6 +40,7 @@ action :create do
user 'postgres'
command create_user_sql(new_resource)
sensitive new_resource.sensitive
environment(psql_environment)
not_if { follower? || user_exists?(new_resource) }
end
end
@ -49,6 +50,7 @@ action :update do
execute "update postgresql user #{new_resource.create_user}" do
user 'postgres'
command update_user_sql(new_resource)
environment(psql_environment)
sensitive true
not_if { follower? }
only_if { user_exists?(new_resource) }
@ -64,6 +66,7 @@ action :update do
execute "Update postgresql user #{new_resource.create_user} to set #{attr}" do
user 'postgres'
command update_user_with_attributes_sql(new_resource, v)
environment(psql_environment)
sensitive true
not_if { follower? }
only_if { user_exists?(new_resource) }
@ -76,6 +79,7 @@ action :drop do
execute "drop postgresql user #{new_resource.create_user}" do
user 'postgres'
command drop_user_sql(new_resource)
environment(psql_environment)
sensitive true
not_if { follower? }
only_if { user_exists?(new_resource) }

View File

@ -0,0 +1,41 @@
# Default values for pg_createcluster(8)
# Occurrences of '%v' are replaced by the major version number,
# and '%c' by the cluster name. Use '%%' for a literal '%'.
# Create a "main" cluster when a new postgresql-x.y server package is installed
#create_main_cluster = true
# Default start.conf value, must be one of "auto", "manual", and "disabled".
# See pg_createcluster(8) for more documentation.
#start_conf = 'auto'
# Default data directory.
#data_directory = '/var/lib/postgresql/%v/%c'
# Default directory for transaction logs
# Unset by default, i.e. transaction logs remain in the data directory.
#waldir = '/var/lib/postgresql/wal/%v/%c/pg_wal'
# Options to pass to initdb.
initdb_options = '<%= @initdb_options %>'
# The following options are copied into the new cluster's postgresql.conf:
# Enable SSL by default (using the "snakeoil" certificates installed by the
# ssl-cert package, unless configured otherwise here)
ssl = on
# Show cluster name in process title
cluster_name = '%v/%c'
# Put stats_temp_directory on tmpfs
stats_temp_directory = '/var/run/postgresql/%v-%c.pg_stat_tmp'
# Add prefix to log lines
log_line_prefix = '%%m [%%p] %%q%%u@%%d '
# Add "include_dir" in postgresql.conf
add_include_dir = 'conf.d'
# Directory for additional createcluster config
include_dir '/etc/postgresql-common/createcluster.d'

View File

@ -1,23 +1,51 @@
{
"id": "postgresql",
"ejabberd_user_password": {
"encrypted_data": "s31aNIv9ZTlU8cVXMDUB79Iv+EozZS1NSZVU5ey9xpBf2WYohpSqni/5Wg==\n",
"iv": "a3LWKNYmUZfSMc1Y\n",
"auth_tag": "3P+WFcDw/R1d983g7YoFUw==\n",
"encrypted_data": "hz0xHS2wl66X6xxqLE5/6apQb8SvIR7r8hCd9ZzEcHf7VaWoFMNLmrmwqw==\n",
"iv": "PfEp9Jhqfp0o7Cje\n",
"auth_tag": "ckEADxPfymTvSVLLXUxTWA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"server_password": {
"encrypted_data": "w7zghEF+DjUhS59cze+qviqDcy8mQpIgW6olHabas1IH4t0z+IQ7\n",
"iv": "ppqOzJGczWtwGRnX\n",
"auth_tag": "2Lhqw7Rhm35HcltsDtaJIw==\n",
"encrypted_data": "9aV4IykJB3lISayq/crmowTjrQjwSWSrh7+O9LMq0IgZaWZ6Bk6R\n",
"iv": "XFeNPuZAh4nCX9NU\n",
"auth_tag": "LoAIWrqSAmcuA+r3nyHu2Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"mastodon_user_password": {
"encrypted_data": "84UPPmtNh/5MH6u4svMPhRHBGK1GFnP4G2tk/a+wQLNxSB8FlDsTuqSC2A==\n",
"iv": "UBl2ILWCc2WKcN6d\n",
"auth_tag": "NF/xcK0tmvbBo1dDFhOf7w==\n",
"encrypted_data": "LGU8N2C9Ax17QvFCWNV9m1rbRpBT9YH1qVn/Cmz0/p+1aUcOUN8rzxb57Q==\n",
"iv": "FiYQKLmfJ/CYO50H\n",
"auth_tag": "t3NwAMqoGCJ/c/5H2KjQ+Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"replication_password": {
"encrypted_data": "6UildEd3UactuYufRp+UjHFlK3zLZ8Vmggfc8URBRNVfWHs=\n",
"iv": "e4SpyAt32vXuX4un\n",
"auth_tag": "AkCEvuEnb+E5jTC84tC8NA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ssl_cert": {
"encrypted_data": "loF7NMyOJXr8PfxsuN6zvp86hIqWYoGFiGq+ldirctWnmkeDmaROgzDW1oQp\nAubnEHZNx7IFRn/FGpGhhbX/DGjbL6EK0bSE6x6uzOEhpaFDAqmzzEfMXCMj\nDIsrM5WSmP1WBFd6g+/zk3EAXHeekOlLBEj13zzSJVj4piLFERKZRTgix0eP\nOmH+lGBoxy4hXKfa9ru7c5h4vLVQHSlHjrrsyeKdumbmXWSb3IJWtEsNQRqu\nKu6DZ+IRC8fH+DBs8/32dTbJ6uR29kbKfZrWTrpOKXWJLnT1snuiTMeRbTcO\nVbS1ZSeGcpGMFFayAui4KgPaDK8vT/mXcd2P3+c85GZtmmvIKfloIRmtb4in\nleUx3z70BxPFRg5wYfSiP/xJMpjJrh5/6P+96iMkgmU+wuXT+95yf4Agz7G5\n0gObs/sJCAV9qOoWIXSU3jyNvaYsZMPj8FHXlpnCXojHJ2WnqLCAPeVWYHbd\nvNSEOvmCN07xK1PkGZT9NGfPzRcZxqop5gJ3qP9Km33Z06SNF+28i2d4lpy+\n1oWqg5ow2CBhRrb0Bx8FplQug4EXCV7Sni4mc0jSX90rBv+e65Em+33x0A27\nPrp7lfcv+7ridU5AZXifFZSuIJF6LMXz+ji2zC2JMjS4xQ8/KXBd8E5/fRJH\nI18X+t/xx8gakmaDrz/3+4i8TVt1I8pIpN/SaAXTZqgme1QoISymf6LQzFxW\ns1kQGOwbtgx60+2BG7kF9XRRZJay8P1uxmVgjHWbqyL0KbYTlU2zTLuRs3ez\n+rPEsxB/hNfUeB9guALFLtvlkAob1Fh/Za6aukaFlaVJHbHoXehH/aXBPAVK\n0ld+3fql5Ib/OAD7prWaUCZ/tP357RWwCxz+ECjtJhFdREx8fT1aZGvmJ0yx\nESNhSjrn+b+rVc+HiD4hAytW+QP2yNqfKO9YzxXYfN5BBTxh/fvO2qVtQmSf\n+u9iatEaico44E7MX1ZOYAclTA289dwyu6R9PRa1p0zral5b+vJAOx1iH1uq\nzHUKTiRCRAcWrcciL8PH8MRXdcHSxmfyBSBbcz+dh/MURyQMx/LOQ31gYuYq\nzlgbJNsVl6V9rl9x2SargwJrD1WM863oyQumZc/M42GX0z9PilIhLQbF26MN\n2tUf5IDK7d42Z5A6ATxR+0qKh2/WvDXDbNHy+cuAjRJRX9vTgNqpR5qCOyT5\nIxA55rLvHYxbnqic124I1EdXGtoEXqsxt1YAq3ho9QCQz1t5Z/AP63oUEuLr\np4WIeo44fqZzjprRFEE3KbCGlUDx56xLg4a84JF1rMU0ce11BUtEEtRF2p4X\noecU8Z5vvhvsqXxYko6aFNcAvxO2FdZmC76lilNsHgH9VS02ctjOT7Mvi2XP\n3QEVOg==\n",
"iv": "v+wkuXO+2VZHRkOu\n",
"auth_tag": "C56+Qe/UNzR8k9HizIFyMA==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ssl_key": {
"encrypted_data": "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\n",
"iv": "sPYjnXdqpABH9wrl\n",
"auth_tag": "F5ajYZMx+6r333stbQ0E1Q==\n",
"version": 3,
"cipher": "aes-256-gcm"
},
"ssl_root_cert": {
"encrypted_data": "hwwHOg/kuJxMEOLpDC2zCrIRoWkbcNzui849HEtootXsL8YPFMIo0wKzC4JS\nc5R5A7MOqgoijjrhymMKkWZ4nqdx0ZVjlLQoBpFd2D6OYmomID/e4Qi2fR4Q\nZ9eS1xoPi0cAcKKML83yHJ3bRkZhqcZLIauqm3N+pAwEdYjHo9HrNPs9stqL\noSyLIG5IwNvwh8DJMb9XU5tBlMOpI0eUDRptBHjecAdmSv59jxse7dSHVove\ndsooWNdsz48318QMG3e2ALRIWZHFb0t2C/01wYqk9PrazIX9upC1BHZ7f4XZ\nAOkukFD/uVa3wLrzQnGhh8bLxZmsRaKaGlY79vg6HgYqUoqmEuB6FHVRX7xb\nh4zt3CcWQMwU0r+Po1a2Qo5HT9xP40QgrHwtJwlpLgIP/9yxhTjpb2qdJzY3\n88MI/wZLvyezTZwMmZikE9+IlwfUBBmsSJVHOtKlPQ27YAHXmALczQUPrYG9\nqWLnWoqmyYFMpPF4u7QQUXNjde+z5sZb2gELRy1nBtHGPEZQY/Ji9P4AT0jW\n3tTidly4yYa0sXLGFH/ZbePRwrUX1qd7RalOLWUYkPwEUVcO5FzzWvCr58S0\n570VoHhyTrYWwaRfiEhEsOV/aSrVERa7T89NvDGpaKQmzpWCF1uGbnmRUI+a\nyYhSzgXaFiKiE8JFvev83slqRpsxF2z2bdHEBvSIce69pzC5VjWKVuHG/Lf8\nVseTapbVXNptMTgm+ToZHcbtBFdWlh3rpyaAKj5uKkKenY0n/R7s4M0GFviY\nj+zLQhHGYXNCybKTfguDfcKe6XiktguwXTCaXo8HpaZr49i2HsAYmSEHw4oE\nYKoYUfm9v1n6O6uxWXV92OIpRS0bkb4hUMWY9K6oG/hbUCupX/RWnBZW4wAS\nvh561oz1Ef1NVI85l2DDG++oCgXgiqzulIQxyNFOyofX5KLmJ8/nLSUc2R3E\nITPaqEG/5NUSyeQMPbIVRN4bsXcogWB/779QiXP6nDEuucNH6kpesiDbEmxC\n5J9i3xKI97zDL8HEmT7Tgp5Tu9FOyOA36qS14cMo8Ue4MWDGV1NrnbWf7LvE\nnx65h8tk1LzimnTE/NqhrYgodylUnNf6c76CaHUhqBDi3JUMF9O/IwRuYH7w\nTvOGphtyix7Lph3wCJJf/VVgK4jy2erq9+mr82dKBBCynEbUJVhpVlAkdKqX\n44LC+KIvJBb4UPerutEYmOOy2Ha1elQyFebSgUR6bxxG9JvZEOYY+UCdeRnz\nQTCQYEvUO7nHSI1uKDW2/BC0f6vzQxYWBT1XgWt5D+wlqz3ysW2AKCK2j4xL\nEFZEQF4ibX0Acm/dp/BVztq8ymhTtqW7pMPHbub0/Q4kgFiPq66FHxJdQU4Q\nuS9w2ciiPGbCbgdww3RfEU3c0kTieyHRcL/pU3aaO6RTA3SeGRX6DqXX3Si3\npkLiyuXBBIskbn0RiBn1SXYMJ17Vaye4BvFlDc2PywhEsXkRGn6Ad1gLOkyZ\nycLnXizhLX0kePSgyn/0N9RI067dlv2lzdaVuheQQEX7efrFCC2zMzvdgP8=\n",
"iv": "TrPuASVYx7D2onkS\n",
"auth_tag": "Gzn4kJCs87LK3ZKJxCHAnw==\n",
"version": 3,
"cipher": "aes-256-gcm"
}

View File

@ -24,6 +24,7 @@
"ipaddress": "46.4.18.160",
"roles": [
"base",
"postgresql_primary",
"mastodon",
"ejabberd"
],
@ -73,7 +74,6 @@
"nginx::commons_dir",
"nginx::commons_script",
"nginx::commons_conf",
"build-essential::default",
"ark::default",
"composer::default",
"composer::install",
@ -107,7 +107,8 @@
"tor-full::default",
"kosmos-base::letsencrypt",
"git::default",
"git::package"
"git::package",
"build-essential::default"
],
"platform": "ubuntu",
"platform_version": "18.04",
@ -128,7 +129,7 @@
"recipe[kosmos-base::andromeda_firewall]",
"recipe[kosmos-ipfs]",
"recipe[kosmos-ipfs::public_gateway]",
"recipe[kosmos-postgresql]",
"role[postgresql_primary]",
"recipe[kosmos-mediawiki]",
"recipe[kosmos-btcpayserver::proxy]",
"role[mastodon]",

View File

@ -0,0 +1,5 @@
name "postgresql_primary"
run_list %w(
kosmos-postgresql::default
)

View File

@ -0,0 +1,5 @@
name "postgresql_replica"
run_list %w(
kosmos-postgresql::replica
)

View File

@ -1,4 +1,57 @@
# kosmos-postgresql
TODO: Enter the cookbook description here.
## Usage
### On the primary:
Set the `postgresql_primary` role on the node
### On the replica:
Add the `postgresql_replica` role to the node's run list. Run Chef on the node
a first time.
After the initial Chef run on the replica, run Chef on the primary to add the
firewall rules and PostgreSQL access rules, then run Chef again on the replica
to set up replication.
## Caveat
[`firewall_rules`](https://github.com/chef-cookbooks/firewall/issues/134) and
[`postgresql_access`](https://github.com/sous-chefs/postgresql/issues/648) are
declared in recipes, not resources because of the way custom resources
work currently in Chef. See the `default.rb` and `replica.rb` recipes.
The primary gives access to the `replication` db to the `replication` user
connecting from a replica, and replicas to the primary. For more information
about PostgreSQL client authentication, see the
[official docs](https://www.postgresql.org/docs/12/auth-pg-hba-conf.html)
The primary opens up the PostgreSQL port (5432 TCP) to replicas, and replicas
to the primary.
## TLS self-signed certificate
A wildcard (`*.kosmos.org` certificate) was generated with the following
commands:
```
openssl req -new -nodes -text -out root.csr -keyout root.key \
-subj "/CN=root.kosmos.org"
chmod og-rwx root.key
openssl x509 -req -in root.csr -text -days 3650 \
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
-signkey root.key -out root.crt
openssl req -new -nodes -text -out server.csr \
-keyout server.key -subj "/CN=*.kosmos.org"
chmod og-rwx server.key
openssl x509 -req -in server.csr -text -days 1825 \
-CA root.crt -CAkey root.key -CAcreateserial \
-out server.crt
```
It is valid until May 12 2025.
The content of `server.crt`, `server.key` and `root.crt` an stored in the
`postgresql` encrypted data bag. The root key is stored in LastPass
("Self-signed TLS root certificate"). `server.crt` & `server.key` are used by
the PostgreSQL server.

View File

@ -0,0 +1,3 @@
# This is set to false by default, and set to true in the server resource
# for replicas.
node.default['kosmos-postgresql']['ready_to_set_up_replica'] = false

View File

@ -0,0 +1,33 @@
class Chef
class Recipe
def postgresql_primary
postgresql_primary = search(:node, "role:postgresql_primary AND chef_environment:#{node.chef_environment}").first
unless postgresql_primary.nil?
primary_ip = ip_for(postgresql_primary)
{ hostname: postgresql_primary[:hostname], ipaddress: primary_ip }
end
end
def postgresql_replicas
postgresql_replicas = []
search(:node, "role:postgresql_replica AND chef_environment:#{node.chef_environment}").each do |replica|
replica_ip = ip_for(replica)
postgresql_replicas << { hostname: replica[:hostname], ipaddress: replica_ip }
end
postgresql_replicas
end
def ip_for(server_node)
if node.chef_environment == "development"
server_node['network']['interfaces']['eth1']['routes'].first['src']
else
server_node['ipaddress']
end
end
end
end

View File

@ -24,28 +24,49 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
return if platform?('ubuntu') && node[:platform_version].to_f < 18.04
postgresql_version = "12"
postgresql_service = "postgresql@#{postgresql_version}-main"
node.override['build-essential']['compile_time'] = true
include_recipe 'build-essential::default'
package("libpq-dev") { action :nothing }.run_action(:install)
chef_gem 'pg' do
compile_time true
postgresql_custom_server postgresql_version do
role "primary"
end
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
postgresql_server_install "main" do
version "10"
setup_repo false
password postgresql_data_bag_item['server_password']
action :install
service postgresql_service do
supports restart: true, status: true, reload: true
action [:enable]
end
postgresql_client_install "main" do
version "10"
setup_repo false
action :install
# This will only be run once, if the /var/lib/postgresql/10/main directory
# exists. The old data directory is then moved.
execute "upgrade postgresql to 12" do
command <<-EOF
systemctl stop postgresql@12-main
systemctl stop postgresql@10-main
su - postgres -c "/usr/lib/postgresql/12/bin/pg_upgrade --old-bindir=/usr/lib/postgresql/10/bin/ --new-bindir=/usr/lib/postgresql/12/bin/ --old-datadir=/etc/postgresql/10/main/ --new-datadir=/etc/postgresql/12/main/"
mv /var/lib/postgresql/10/main /var/lib/postgresql/10/main.old
systemctl start postgresql@12-main
EOF
only_if { ::File.exist? "/var/lib/postgresql/10/main" }
end
postgresql_replicas.each do |replica|
postgresql_access "#{replica[:hostname]} replication" do
access_type "host"
access_db "replication"
access_user "replication"
access_addr "#{replica[:ipaddress]}/32"
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
unless node.chef_environment == "development"
include_recipe "firewall"
firewall_rule "postgresql" do
port 5432
protocol :tcp
command :allow
destination replica[:ipaddress]
end
end
end

View File

@ -0,0 +1,82 @@
#
# Cookbook:: kosmos-postgresql
# Recipe:: replica
#
# The MIT License (MIT)
#
# Copyright:: 2019, Kosmos Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
postgresql_version = "12"
postgresql_service = "postgresql@#{postgresql_version}-main"
postgresql_custom_server postgresql_version do
role "replica"
end
service postgresql_service do
supports restart: true, status: true, reload: true
action [:enable]
end
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
primary = postgresql_primary
unless primary.nil?
postgresql_data_dir = "/var/lib/postgresql/#{postgresql_version}/main"
if node['kosmos-postgresql']['ready_to_set_up_replica']
execute "set up replication" do
command <<-EOF
systemctl stop #{postgresql_service}
mv #{postgresql_data_dir} #{postgresql_data_dir}.old
PGPASSWORD=#{postgresql_data_bag_item['replication_password']} pg_basebackup -h #{primary[:ipaddress]} -U replication -D #{postgresql_data_dir} -R
chown -R postgres:postgres #{postgresql_data_dir}
systemctl start #{postgresql_service}
EOF
sensitive true
not_if { ::File.exist? "#{postgresql_data_dir}/standby.signal" }
end
end
postgresql_access "replication" do
access_type "host"
access_db "replication"
access_user "replication"
access_addr "#{primary[:ipaddress]}/32"
access_method "md5"
notifies :reload, "service[#{postgresql_service}]", :immediately
end
# On the next Chef run the replica will be set up
node.normal['kosmos-postgresql']['ready_to_set_up_replica'] = true
unless node.chef_environment == "development"
include_recipe "firewall"
firewall_rule "postgresql" do
port 5432
protocol :tcp
command :allow
destination primary[:ipaddress]
end
end
end

View File

@ -0,0 +1,102 @@
resource_name :postgresql_custom_server
property :postgresql_version, String, required: true, name_property: true
property :role, String, required: true # Can be primary or replica
action :create do
postgresql_version = new_resource.postgresql_version
postgresql_data_dir = data_dir(postgresql_version)
postgresql_service = "postgresql@#{postgresql_version}-main"
node.override['build-essential']['compile_time'] = true
include_recipe 'build-essential::default'
package("libpq-dev") { action :nothing }.run_action(:install)
chef_gem 'pg' do
compile_time true
end
postgresql_data_bag_item = data_bag_item('credentials', 'postgresql')
postgresql_server_install "main" do
version postgresql_version
setup_repo true
password postgresql_data_bag_item['server_password']
action :install
end
service postgresql_service do
supports restart: true, status: true, reload: true
# action [:enable, :start]
end
postgresql_client_install "main" do
version postgresql_version
setup_repo true
action :install
end
postgresql_user "replication" do
action :create
replication true
password postgresql_data_bag_item['replication_password']
end
shared_buffers = if node['memory']['total'].to_i / 1024 < 1024 # > 1GB RAM
"128MB"
else # >= 1GB RAM, use 25% of total RAM
"#{node['memory']['total'].to_i / 1024 / 4}MB"
end
additional_config = {
max_connections: 100, # default
shared_buffers: shared_buffers,
unix_socket_directories: "/var/run/postgresql",
dynamic_shared_memory_type: "posix",
timezone: "UTC", # default is GMT
listen_addresses: "0.0.0.0",
}
if new_resource.role == "replica"
additional_config[:promote_trigger_file] = "#{postgresql_data_dir}/failover.trigger"
end
ssl_cert = postgresql_data_bag_item['ssl_cert']
ssl_cert_path = "#{postgresql_data_dir}/server.crt"
ssl_key = postgresql_data_bag_item['ssl_key']
ssl_key_path = "#{postgresql_data_dir}/server.key"
file ssl_cert_path do
content ssl_cert
owner "postgres"
group "postgres"
mode "0640"
sensitive true
end
file ssl_key_path do
content ssl_key
owner "postgres"
group "postgres"
mode "0600"
sensitive true
end
additional_config[:ssl] = "on"
additional_config[:ssl_cert_file] = ssl_cert_path
additional_config[:ssl_key_file] = ssl_key_path
# ejabberd does not support 1.3 yet
additional_config[:ssl_min_protocol_version] = "TLSv1.2"
postgresql_server_conf "main" do
version postgresql_version
additional_config additional_config
notifies :reload, "service[#{postgresql_service}]"
end
end
action_class do
# to use the data_dir helper
include PostgresqlCookbook::Helpers
end