Improve detection of postgresql conf dir and data dir

Redhat conf_dir detection was regressed in 57d7275 which inadvertently
removed the setting of @conf_dir. Any attempt to use the postgres
resource on RHEL would rain an exception:

    inspec> postgres.data_dir
    TypeError: no implicit conversion of nil into String

Further, the redhat detection code appears to assume that RHEL always
uses versioned data directories. This however, does not appear to be the
case:

    $ cat /etc/redhat-release
    CentOS release 6.7 (Final)
    $ sudo ls /var/lib/pgsql/
    backups  data  pgstartup.log

The code now can handle both versioned and un-versioned directory
formats on RHEL. Further, it provides diagnostic warnings about
uncertainty in the discovered data directories and configuration
directories.

Signed-off-by: Steven Danna <steve@chef.io>
This commit is contained in:
Steven Danna 2016-08-10 12:25:03 +01:00 committed by Christoph Hartmann
parent 9138c7d04e
commit c71f5cdb30

View file

@ -12,29 +12,111 @@ module Inspec::Resources
def initialize
os = inspec.os
if os.debian?
@service = 'postgresql'
@data_dir = '/var/lib/postgresql'
@version = inspec.command('ls /etc/postgresql/').stdout.chomp
@conf_dir = "/etc/postgresql/#{@version}/main"
#
# https://wiki.debian.org/PostgreSql
#
# Debian allows multiple versions of postgresql to be
# installed as well as multiple "clusters" to be configured.
#
version = version_from_dir('/etc/postgresql')
cluster = cluster_from_dir("/etc/postgresql/#{version}")
@conf_dir = "/etc/postgresql/#{version}/#{cluster}"
@data_dir = "/var/lib/postgresql/#{version}/#{cluster}"
elsif os.redhat?
@service = 'postgresql'
@version = inspec.command('ls /var/lib/pgsql/').stdout.chomp
@data_dir = "/var/lib/pgsql/#{@version}/data"
#
# /var/lib/pgsql/data is the default data directory on RHEL6
# and RHEL7. However, PR #824 explicitly added version-based
# directories. Thus, we call #version_from_dir unless it looks
# like we are using unversioned directories.
#
# TODO(ssd): This has the potential to be noisy because of the
# warning in version_from_dir. We should determine which case
# is more common and only warn in the less common case.
#
version = if inspec.directory('/var/lib/pgsql/data').exist?
warn 'Found /var/lib/pgsql/data. Assuming postgresql install uses un-versioned directories.'
nil
else
version_from_dir('/var/lib/pgsql/')
end
@data_dir = File.join('/var/lib/pgsql/', version.to_s, 'data')
elsif os[:name] == 'arch'
@service = 'postgresql'
#
# https://wiki.archlinux.org/index.php/PostgreSQL
#
# The archlinux wiki points to /var/lib/postgresql/data as the
# main data directory.
#
@data_dir = '/var/lib/postgres/data'
@conf_dir = '/var/lib/postgres/data'
else
@service = 'postgresql'
@data_dir = '/var/lib/postgresql'
@conf_dir = '/var/lib/pgsql/data'
#
# According to https://www.postgresql.org/docs/9.5/static/creating-cluster.html
#
# > There is no default, although locations such as
# > /usr/local/pgsql/data or /var/lib/pgsql/data are popular.
#
@data_dir = '/var/lib/pgsql/data'
end
@service = 'postgresql'
@conf_dir ||= @data_dir
verify_dirs
@conf_path = File.join @conf_dir, 'postgresql.conf'
end
def to_s
'PostgreSQL'
end
private
def verify_dirs
if !inspec.directory(@conf_dir).exist?
warn "Default postgresql configuration directory: #{@conf_dir} does not exist. Postgresql may not be installed or we've misidentified the configuration directory."
end
if !inspec.directory(@data_dir).exist?
warn "Default postgresql data directory: #{@data_dir} does not exist. Postgresql may not be installed or we've misidentified the data directory."
end
end
def version_from_dir(dir)
dirs = inspec.command("ls -d #{dir}/*/").stdout
entries = dirs.lines.count
case entries
when 0
warn "Could not determine version of installed postgresql by inspecting #{dir}"
nil
when 1
warn "Using #{dirs}: #{dir_to_version(dirs)}"
dir_to_version(dirs)
else
warn "Multiple versions of postgresql installed or incorrect base dir #{dir}"
first = dir_to_version(dirs.lines.first)
warn "Using the first version found: #{first}"
first
end
end
def dir_to_version(dir)
dir.chomp.split('/').last
end
def cluster_from_dir(dir)
# Main is the default cluster name on debian use it if it
# exists.
if inspec.directory("#{dir}/main").exist?
'main'
else
dirs = inspec.command("ls -d #{dir}/*/").stdout.lines
first = dirs.first.chomp.split('/').last
if dirs.count > 1
warn "Multiple postgresql clusters configured or incorrect base dir #{dir}"
warn "Using the first directory found: #{first}"
end
first
end
end
end
end