Example #1
0
def postgresql_conf_defaults():
    """Return the postgresql.conf defaults, which we parse from config.yaml"""
    # We load defaults from the extra_pg_conf default in config.yaml,
    # which ensures that they never get out of sync.
    raw = helpers.config_yaml()["options"]["extra_pg_conf"]["default"]
    defaults = postgresql.parse_config(raw)

    # And recalculate some defaults, which could get out of sync.
    # Settings with mandatory minimums like wal_senders are handled
    # later, in ensure_viable_postgresql_conf().
    ram = int(host.get_total_ram() / (1024 * 1024))  # Working in megabytes.

    # Default shared_buffers to 25% of ram, minimum 16MB, maximum 8GB,
    # per current best practice rules of thumb. Rest is cache.
    shared_buffers = max(min(math.ceil(ram * 0.25), 8192), 16)
    effective_cache_size = max(1, ram - shared_buffers)
    defaults["shared_buffers"] = "{} MB".format(shared_buffers)
    defaults["effective_cache_size"] = "{} MB".format(effective_cache_size)

    # PostgreSQL 10 introduces multiple password encryption methods.
    if postgresql.has_version("10"):
        # Change this to scram-sha-256 next LTS release, when we can
        # start assuming clients have libpq 10. The setting can of
        # course still be overridden in the config.
        defaults["password_encryption"] = "md5"
    else:
        defaults["password_encryption"] = True

    return defaults
Example #2
0
def postgresql_conf_defaults():
    '''Return the postgresql.conf defaults, which we parse from config.yaml'''
    # We load defaults from the extra_pg_conf default in config.yaml,
    # which ensures that they never get out of sync.
    raw = helpers.config_yaml()['options']['extra_pg_conf']['default']
    defaults = postgresql.parse_config(raw)

    # And recalculate some defaults, which could get out of sync.
    # Settings with mandatory minimums like wal_senders are handled
    # later, in ensure_viable_postgresql_conf().
    ram = int(host.get_total_ram() / (1024 * 1024))  # Working in megabytes.

    # Default shared_buffers to 25% of ram, minimum 16MB, maximum 8GB,
    # per current best practice rules of thumb. Rest is cache.
    shared_buffers = max(min(math.ceil(ram * 0.25), 8192), 16)
    effective_cache_size = max(1, ram - shared_buffers)
    defaults['shared_buffers'] = '{} MB'.format(shared_buffers)
    defaults['effective_cache_size'] = '{} MB'.format(effective_cache_size)

    return defaults
Example #3
0
def postgresql_conf_overrides():
    """User postgresql.conf overrides, from service configuration."""
    config = hookenv.config()
    return postgresql.parse_config(config["extra_pg_conf"])
    def test_parse_config(self):
        valid = [
            (r"# A comment", dict()),
            (r"key_1 = value", dict(key_1="value")),
            (r"key_2 ='quoted valu3'", dict(key_2="quoted valu3")),
            (r"""key_3= 'foo "bar"'""", dict(key_3='foo "bar"')),
            (r"""key_4='''bar\''""", dict(key_4="'bar'")),
            (r"key_5=''", dict(key_5="")),
            (r"", dict()),
            (r"  # Another comment ", dict()),
            (r"key_6='#'", dict(key_6="#")),
            (r"key_7=42", dict(key_7="42")),
            (r"key_8=3.142", dict(key_8="3.142")),
            (r"key_9=-1", dict(key_9="-1")),
        ]

        # The above examples all parse correctly.
        for raw, expected in valid:
            with self.subTest(raw=raw):
                self.assertDictEqual(postgresql.parse_config(raw), expected)

        # Concatenating them parses correctly to.
        combined_raw = []
        combined_expected = {}
        for raw, expected in valid:
            combined_raw.append(raw)
            combined_expected.update(expected)
        self.assertDictEqual(postgresql.parse_config("\n".join(combined_raw)), combined_expected)

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("=")
        self.assertEqual(str(x.exception), "Missing key (line 1)")
        self.assertEqual(x.exception.lineno, 1)
        self.assertEqual(x.exception.text, "=")

        # We could be lazy here, since we are dealing with trusted input,
        # but meaningful error messages are helpful.
        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("# comment\nkey=")
        self.assertEqual(str(x.exception), "Missing value (line 2)")

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("key='unterminated")
        self.assertEqual(str(x.exception), "Badly quoted value (line 1)")

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("key='unterminated 2 # comment")
        self.assertEqual(str(x.exception), "Badly quoted value (line 1)")

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("key='unte''''")
        self.assertEqual(str(x.exception), "Badly quoted value (line 1)")

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config(r"key='\'")
        self.assertEqual(str(x.exception), "Badly quoted value (line 1)")
Example #5
0
    def test_parse_config(self):
        valid = [(r'# A comment', dict()),
                 (r'key_1 = value', dict(key_1='value')),
                 (r"key_2 ='quoted valu3'", dict(key_2='quoted valu3')),
                 (r"""key_3= 'foo "bar"'""", dict(key_3='foo "bar"')),
                 (r"""key_4='''bar\''""", dict(key_4="'bar'")),
                 (r"key_5=''", dict(key_5='')), (r"", dict()),
                 (r'  # Another comment ', dict()),
                 (r"key_6='#'", dict(key_6='#')),
                 (r"key_7=42", dict(key_7='42')),
                 (r"key_8=3.142", dict(key_8='3.142')),
                 (r'key_9=-1', dict(key_9='-1'))]

        # The above examples all parse correctly.
        for raw, expected in valid:
            with self.subTest(raw=raw):
                self.assertDictEqual(postgresql.parse_config(raw), expected)

        # Concatenating them parses correctly to.
        combined_raw = []
        combined_expected = {}
        for raw, expected in valid:
            combined_raw.append(raw)
            combined_expected.update(expected)
        self.assertDictEqual(postgresql.parse_config('\n'.join(combined_raw)),
                             combined_expected)

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("=")
        self.assertEqual(str(x.exception), "Missing key '=' (line 1)")
        self.assertEqual(x.exception.lineno, 1)
        self.assertEqual(x.exception.text, "=")

        # We could be lazy here, since we are dealing with trusted input,
        # but meaningful error messages are helpful.
        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config('# comment\nkey=')
        self.assertEqual(str(x.exception), 'Missing value (line 2)')

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("key='unterminated")
        self.assertEqual(str(x.exception),
                         r'''Badly quoted value "'unterminated" (line 1)''')

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("key='unterminated 2 # comment")
        self.assertEqual(str(x.exception),
                         r'''Badly quoted value "'unterminated 2" (line 1)''')

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config("key='unte''''")
        self.assertEqual(str(x.exception),
                         r"""Badly quoted value "'unte''''" (line 1)""")

        with self.assertRaises(SyntaxError) as x:
            postgresql.parse_config(r"key='\'")
        self.assertEqual(str(x.exception),
                         r'''Badly quoted value "'\\'" (line 1)''')
Example #6
0
def postgresql_conf_overrides():
    '''User postgresql.conf overrides, from service configuration.'''
    config = hookenv.config()
    return postgresql.parse_config(config['extra_pg_conf'])