From 2200a4ce8c6122241eae0815c44a5b8952015388 Mon Sep 17 00:00:00 2001 From: Oleksii Kliukin Date: Wed, 21 Oct 2015 15:51:21 +0200 Subject: [PATCH] Add support for per-member tags. Tags are labels assigned to individual members in order to alter its default behavior, i.e. exclude from the leader election or indicate a possibility to create base backups from the member. This commit only adds support for setting tags in the configuration file, exposes the tags to DCS /member subkey and returns the tags in a response of the API request. At the moment the tag names are not validated, nor they are interpreted in any way. Support for setting tags via the API is also in the scope of further work. --- patroni/__init__.py | 1 + patroni/api.py | 5 +++++ patroni/ha.py | 3 ++- postgres0.yml | 5 +++++ postgres1.yml | 5 +++++ tests/test_api.py | 1 + tests/test_ha.py | 1 + 7 files changed, 20 insertions(+), 1 deletion(-) diff --git a/patroni/__init__.py b/patroni/__init__.py index 150334ba..5769a8fc 100644 --- a/patroni/__init__.py +++ b/patroni/__init__.py @@ -18,6 +18,7 @@ class Patroni: def __init__(self, config): self.nap_time = config['loop_wait'] + self.tags = config.get('tags', dict()) self.postgresql = Postgresql(config['postgresql']) self.dcs = self.get_dcs(self.postgresql.name, config) host, port = config['restapi']['listen'].split(':') diff --git a/patroni/api.py b/patroni/api.py index dc83249f..e4071e8e 100644 --- a/patroni/api.py +++ b/patroni/api.py @@ -46,6 +46,7 @@ class RestApiHandler(BaseHTTPRequestHandler): path = '/master' if self.path == '/' else self.path response = self.get_postgresql_status() + response.update(self.get_tags()) patroni = self.server.patroni cluster = patroni.dcs.cluster @@ -75,6 +76,7 @@ class RestApiHandler(BaseHTTPRequestHandler): def do_GET_patroni(self): response = self.get_postgresql_status(True) + response.update(self.get_tags()) self.send_response(200) self.send_header('Content-Type', 'application/json') @@ -174,6 +176,9 @@ class RestApiHandler(BaseHTTPRequestHandler): state = 'unknown' if state == 'running' else state return {'state': state} + def get_tags(self): + return {'tags': self.server.patroni.tags} + class RestApiServer(ThreadingMixIn, HTTPServer, Thread): diff --git a/patroni/ha.py b/patroni/ha.py index 0019253d..d8ff4756 100644 --- a/patroni/ha.py +++ b/patroni/ha.py @@ -50,7 +50,8 @@ class Ha: 'conn_url': self.state_handler.connection_string, 'api_url': self.patroni.api.connection_string, 'state': self.state_handler.state, - 'role': self.state_handler.role + 'role': self.state_handler.role, + 'tags': self.patroni.tags } if data['state'] in ['running', 'restarting', 'starting']: try: diff --git a/postgres0.yml b/postgres0.yml index a155b1cd..0aef6d4e 100644 --- a/postgres0.yml +++ b/postgres0.yml @@ -67,3 +67,8 @@ postgresql: max_replication_slots: 5 hot_standby: "on" wal_log_hints: "on" +tags: + nofailover: False + noloadbalance: False + clonefrom: False + replicatefrom: 127.0.0.1 diff --git a/postgres1.yml b/postgres1.yml index 94e33a42..34e55eae 100644 --- a/postgres1.yml +++ b/postgres1.yml @@ -67,3 +67,8 @@ postgresql: max_replication_slots: 5 hot_standby: "on" wal_log_hints: "on" +tags: + nofailover: False + noloadbalance: False + clonefrom: False + replicatefrom: 127.0.0.1 diff --git a/tests/test_api.py b/tests/test_api.py index e4b8f87e..7fdf9568 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -44,6 +44,7 @@ class MockPatroni: postgresql = MockPostgresql() ha = MockHa() dcs = Mock() + tags = {} class MockRequest: diff --git a/tests/test_ha.py b/tests/test_ha.py index a5a816da..d149746c 100644 --- a/tests/test_ha.py +++ b/tests/test_ha.py @@ -82,6 +82,7 @@ class MockPatroni: self.postgresql = p self.dcs = d self.api = Mock() + self.tags = {} self.api.connection_string = 'http://127.0.0.1:8008'