From cc0df4900bf9d10c16bd06ec04820b897de9f6f6 Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Mon, 2 Dec 2019 10:46:20 +0100 Subject: [PATCH] Set User-Agent for all http requests (#1312) Example: `Patroni/1.6.1 Python/3.6.8 Linux` --- patroni/dcs/consul.py | 10 ++++++---- patroni/dcs/etcd.py | 13 +++++++++---- patroni/dcs/kubernetes.py | 8 +++++--- patroni/request.py | 6 ++++-- patroni/utils.py | 6 +++++- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/patroni/dcs/consul.py b/patroni/dcs/consul.py index cb509ac7..66a8446f 100644 --- a/patroni/dcs/consul.py +++ b/patroni/dcs/consul.py @@ -9,13 +9,14 @@ import time import urllib3 from consul import ConsulException, NotFound, base -from patroni.dcs import AbstractDCS, ClusterConfig, Cluster, Failover, Leader, Member, SyncState, TimelineHistory -from patroni.exceptions import DCSError -from patroni.utils import deep_compare, parse_bool, Retry, RetryFailedError, split_host_port, uri from urllib3.exceptions import HTTPError from six.moves.urllib.parse import urlencode, urlparse, quote from six.moves.http_client import HTTPException +from . import AbstractDCS, Cluster, ClusterConfig, Failover, Leader, Member, SyncState, TimelineHistory +from ..exceptions import DCSError +from ..utils import deep_compare, parse_bool, Retry, RetryFailedError, split_host_port, uri, USER_AGENT + logger = logging.getLogger(__name__) @@ -111,8 +112,9 @@ class HTTPClient(object): else: kwargs['timeout'] = self._read_timeout token = params.pop('token', self.token) if isinstance(params, dict) else self.token + kwargs['headers'] = urllib3.make_headers(user_agent=USER_AGENT) if token: - kwargs['headers'] = {'X-Consul-Token': token} + kwargs['headers']['X-Consul-Token'] = token return callback(self.response(self.http.request(method.upper(), self.uri(path, params), **kwargs))) return wrapper diff --git a/patroni/dcs/etcd.py b/patroni/dcs/etcd.py index 52c95dcb..880b5578 100644 --- a/patroni/dcs/etcd.py +++ b/patroni/dcs/etcd.py @@ -11,16 +11,17 @@ import time from dns.exception import DNSException from dns import resolver -from patroni.dcs import AbstractDCS, ClusterConfig, Cluster, Failover, Leader, Member, SyncState, TimelineHistory -from patroni.exceptions import DCSError -from patroni.utils import Retry, RetryFailedError, split_host_port, uri -from patroni.request import get as requests_get from urllib3.exceptions import HTTPError, ReadTimeoutError, ProtocolError from six.moves.queue import Queue from six.moves.http_client import HTTPException from six.moves.urllib_parse import urlparse from threading import Thread +from . import AbstractDCS, Cluster, ClusterConfig, Failover, Leader, Member, SyncState, TimelineHistory +from ..exceptions import DCSError +from ..request import get as requests_get +from ..utils import Retry, RetryFailedError, split_host_port, uri, USER_AGENT + logger = logging.getLogger(__name__) @@ -125,6 +126,10 @@ class Client(etcd.Client): return etcd_nodes, per_node_timeout, per_node_retries - 1 + def _get_headers(self): + basic_auth = ':'.join((self.username, self.password)) if self.username and self.password else None + return urllib3.make_headers(basic_auth=basic_auth, user_agent=USER_AGENT) + def _build_request_parameters(self, timeout=None): kwargs = {'headers': self._get_headers(), 'redirect': self.allow_redirect} diff --git a/patroni/dcs/kubernetes.py b/patroni/dcs/kubernetes.py index 4257e834..1853105a 100644 --- a/patroni/dcs/kubernetes.py +++ b/patroni/dcs/kubernetes.py @@ -8,14 +8,15 @@ import sys import time from kubernetes import client as k8s_client, config as k8s_config, watch as k8s_watch -from patroni.dcs import AbstractDCS, ClusterConfig, Cluster, Failover, Leader, Member, SyncState, TimelineHistory -from patroni.exceptions import DCSError -from patroni.utils import deep_compare, tzutc, Retry, RetryFailedError from urllib3 import Timeout from urllib3.exceptions import HTTPError from six.moves.http_client import HTTPException from threading import Condition, Lock, Thread +from . import AbstractDCS, Cluster, ClusterConfig, Failover, Leader, Member, SyncState, TimelineHistory +from ..exceptions import DCSError +from ..utils import deep_compare, Retry, RetryFailedError, tzutc, USER_AGENT + logger = logging.getLogger(__name__) @@ -35,6 +36,7 @@ class CoreV1ApiProxy(object): def __init__(self, use_endpoints=False): self._api = k8s_client.CoreV1Api() + self._api.api_client.user_agent = USER_AGENT self._api.api_client.rest_client.pool_manager.connection_pool_kw['maxsize'] = 10 self._request_timeout = None self._use_endpoints = use_endpoints diff --git a/patroni/request.py b/patroni/request.py index f16b7089..0463831c 100644 --- a/patroni/request.py +++ b/patroni/request.py @@ -4,12 +4,14 @@ import six from six.moves.urllib_parse import urlparse, urlunparse +from .utils import USER_AGENT + class PatroniRequest(object): def __init__(self, config, insecure=False): cert_reqs = 'CERT_NONE' if insecure or config.get('ctl', {}).get('insecure', False) else 'CERT_REQUIRED' - self._pool = urllib3.PoolManager(cert_reqs=cert_reqs) + self._pool = urllib3.PoolManager(num_pools=10, maxsize=10, cert_reqs=cert_reqs) self.reload_config(config) @staticmethod @@ -28,7 +30,7 @@ class PatroniRequest(object): return value def reload_config(self, config): - self._pool.headers = urllib3.make_headers(basic_auth=self._get_cfg_value(config, 'auth')) + self._pool.headers = urllib3.make_headers(basic_auth=self._get_cfg_value(config, 'auth'), user_agent=USER_AGENT) if self._apply_ssl_file_param(config, 'cert'): self._apply_ssl_file_param(config, 'key') diff --git a/patroni/utils.py b/patroni/utils.py index 6b0aab25..837243f7 100644 --- a/patroni/utils.py +++ b/patroni/utils.py @@ -1,15 +1,19 @@ import logging +import platform import random import re import time from dateutil import tz -from patroni.exceptions import PatroniException + +from .exceptions import PatroniException +from .version import __version__ tzutc = tz.tzutc() logger = logging.getLogger(__name__) +USER_AGENT = 'Patroni/{0} Python/{1} {2}'.format(__version__, platform.python_version(), platform.system()) OCT_RE = re.compile(r'^[-+]?0[0-7]*') DEC_RE = re.compile(r'^[-+]?(0|[1-9][0-9]*)') HEX_RE = re.compile(r'^[-+]?0x[0-9a-fA-F]+')