Browse Source

Merge "Add TLS support in etcd3 and etcd3gw drivers"

tags/2.3.0^0
Zuul 3 months ago
committed by Gerrit Code Review
parent
commit
1880be2c00
7 changed files with 168 additions and 7 deletions
  1. +6
    -0
      releasenotes/notes/etcd3-etcd3gw-tls-support-618ab207706e67af.yaml
  2. +2
    -1
      setup.cfg
  3. +1
    -0
      test-requirements.txt
  4. +12
    -2
      tooz/drivers/etcd3.py
  5. +17
    -4
      tooz/drivers/etcd3gw.py
  6. +63
    -0
      tooz/tests/drivers/test_etcd3.py
  7. +67
    -0
      tooz/tests/drivers/test_etcd3gw.py

+ 6
- 0
releasenotes/notes/etcd3-etcd3gw-tls-support-618ab207706e67af.yaml View File

@@ -0,0 +1,6 @@
---
features:
- |
The etcd3 and etcd3gw drivers now support TLS, by adding the ability to
specify ca_cert, cert_key and cert_cert files. For the etcd3gw driver,
this is controlled by specifying "etcd3+https" in the coordination URL.

+ 2
- 1
setup.cfg View File

@@ -30,6 +30,7 @@ tooz.backends =
etcd = tooz.drivers.etcd:EtcdDriver
etcd3 = tooz.drivers.etcd3:Etcd3Driver
etcd3+http = tooz.drivers.etcd3gw:Etcd3Driver
etcd3+https = tooz.drivers.etcd3gw:Etcd3Driver
kazoo = tooz.drivers.zookeeper:KazooDriver
zake = tooz.drivers.zake:ZakeDriver
memcached = tooz.drivers.memcached:MemcachedDriver
@@ -47,7 +48,7 @@ consul =
etcd =
requests>=2.10.0 # Apache-2.0
etcd3 =
etcd3>=0.6.2 # Apache-2.0
etcd3>=0.12.0 # Apache-2.0
grpcio>=1.18.0
etcd3gw =
etcd3gw>=0.1.0 # Apache-2.0


+ 1
- 0
test-requirements.txt View File

@@ -9,3 +9,4 @@ coverage>=3.6 # Apache-2.0
fixtures>=3.0.0 # Apache-2.0/BSD
pifpaf>=0.10.0 # Apache-2.0
stestr>=2.0.0
ddt>=1.2.1 # MIT

+ 12
- 2
tooz/drivers/etcd3.py View File

@@ -126,7 +126,9 @@ class Etcd3Driver(coordination.CoordinationDriverCachedRunWatchers,
================== =======
Name Default
================== =======
protocol http
ca_cert None
cert_key None
cert_cert None
timeout 30
lock_timeout 30
membership_timeout 30
@@ -147,8 +149,16 @@ class Etcd3Driver(coordination.CoordinationDriverCachedRunWatchers,
host = parsed_url.hostname or self.DEFAULT_HOST
port = parsed_url.port or self.DEFAULT_PORT
options = utils.collapse(options)
ca_cert = options.get('ca_cert')
cert_key = options.get('cert_key')
cert_cert = options.get('cert_cert')
timeout = int(options.get('timeout', self.DEFAULT_TIMEOUT))
self.client = etcd3.client(host=host, port=port, timeout=timeout)
self.client = etcd3.client(host=host,
port=port,
ca_cert=ca_cert,
cert_key=cert_key,
cert_cert=cert_cert,
timeout=timeout)
self.lock_timeout = int(options.get('lock_timeout', timeout))
self.membership_timeout = int(options.get(
'membership_timeout', timeout))


+ 17
- 4
tooz/drivers/etcd3gw.py View File

@@ -169,15 +169,18 @@ class Etcd3Driver(coordination.CoordinationDriverWithExecutor):

The Etcd driver connection URI should look like::

etcd3+http://[HOST[:PORT]][?OPTION1=VALUE1[&OPTION2=VALUE2[&...]]]
etcd3+PROTOCOL://[HOST[:PORT]][?OPTION1=VALUE1[&OPTION2=VALUE2[&...]]]

If not specified, HOST defaults to localhost and PORT defaults to 2379.
The PROTOCOL can be http or https. If not specified, HOST defaults to
localhost and PORT defaults to 2379.
Available options are:

================== =======
Name Default
================== =======
protocol http
ca_cert None
cert_key None
cert_cert None
timeout 30
lock_timeout 30
membership_timeout 30
@@ -197,11 +200,21 @@ class Etcd3Driver(coordination.CoordinationDriverWithExecutor):

def __init__(self, member_id, parsed_url, options):
super(Etcd3Driver, self).__init__(member_id, parsed_url, options)
protocol = 'https' if parsed_url.scheme.endswith('https') else 'http'
host = parsed_url.hostname or self.DEFAULT_HOST
port = parsed_url.port or self.DEFAULT_PORT
options = utils.collapse(options)
ca_cert = options.get('ca_cert')
cert_key = options.get('cert_key')
cert_cert = options.get('cert_cert')
timeout = int(options.get('timeout', self.DEFAULT_TIMEOUT))
self.client = etcd3gw.client(host=host, port=port, timeout=timeout)
self.client = etcd3gw.client(host=host,
port=port,
protocol=protocol,
ca_cert=ca_cert,
cert_key=cert_key,
cert_cert=cert_cert,
timeout=timeout)
self.lock_timeout = int(options.get('lock_timeout', timeout))
self.membership_timeout = int(options.get(
'membership_timeout', timeout))


+ 63
- 0
tooz/tests/drivers/test_etcd3.py View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
#
# Copyright 2020 Red Hat, Inc.
#
# 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.

import ddt
from testtools import testcase
from unittest import mock

import tooz.coordination
import tooz.drivers.etcd3 as etcd3_driver
import tooz.tests


@ddt.ddt
class TestEtcd3(testcase.TestCase):
FAKE_MEMBER_ID = tooz.tests.get_random_uuid()

@ddt.data({'coord_url': 'etcd3://',
'host': etcd3_driver.Etcd3Driver.DEFAULT_HOST,
'port': etcd3_driver.Etcd3Driver.DEFAULT_PORT,
'ca_cert': None,
'cert_key': None,
'cert_cert': None,
'timeout': etcd3_driver.Etcd3Driver.DEFAULT_TIMEOUT},
{'coord_url': ('etcd3://my_host:666?ca_cert=/my/ca_cert&'
'cert_key=/my/cert_key&cert_cert=/my/cert_cert&'
'timeout=42'),
'host': 'my_host',
'port': 666,
'ca_cert': '/my/ca_cert',
'cert_key': '/my/cert_key',
'cert_cert': '/my/cert_cert',
'timeout': 42})
@ddt.unpack
@mock.patch('etcd3.client')
def test_etcd3_client_init(self,
mock_etcd3_client,
coord_url,
host,
port,
ca_cert,
cert_key,
cert_cert,
timeout):
tooz.coordination.get_coordinator(coord_url, self.FAKE_MEMBER_ID)
mock_etcd3_client.assert_called_with(host=host,
port=port,
ca_cert=ca_cert,
cert_key=cert_key,
cert_cert=cert_cert,
timeout=timeout)

+ 67
- 0
tooz/tests/drivers/test_etcd3gw.py View File

@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
#
# Copyright 2020 Red Hat, Inc.
#
# 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.

import ddt
from testtools import testcase
from unittest import mock

import tooz.coordination
import tooz.drivers.etcd3gw as etcd3gw_driver
import tooz.tests


@ddt.ddt
class TestEtcd3Gw(testcase.TestCase):
FAKE_MEMBER_ID = tooz.tests.get_random_uuid()

@ddt.data({'coord_url': 'etcd3+http://',
'protocol': 'http',
'host': etcd3gw_driver.Etcd3Driver.DEFAULT_HOST,
'port': etcd3gw_driver.Etcd3Driver.DEFAULT_PORT,
'ca_cert': None,
'cert_key': None,
'cert_cert': None,
'timeout': etcd3gw_driver.Etcd3Driver.DEFAULT_TIMEOUT},
{'coord_url': ('etcd3+https://my_host:666?ca_cert=/my/ca_cert&'
'cert_key=/my/cert_key&cert_cert=/my/cert_cert&'
'timeout=42'),
'protocol': 'https',
'host': 'my_host',
'port': 666,
'ca_cert': '/my/ca_cert',
'cert_key': '/my/cert_key',
'cert_cert': '/my/cert_cert',
'timeout': 42})
@ddt.unpack
@mock.patch('etcd3gw.client')
def test_etcd3gw_client_init(self,
mock_etcd3gw_client,
coord_url,
protocol,
host,
port,
ca_cert,
cert_key,
cert_cert,
timeout):
tooz.coordination.get_coordinator(coord_url, self.FAKE_MEMBER_ID)
mock_etcd3gw_client.assert_called_with(host=host,
port=port,
protocol=protocol,
ca_cert=ca_cert,
cert_key=cert_key,
cert_cert=cert_cert,
timeout=timeout)

Loading…
Cancel
Save