Add proxy v2 protocol support
This patch adds support for the proxy protocol v2 on pools. Depends-On: https://review.opendev.org/747296 Change-Id: Ic112c5e71ee9b6433b307fdf27059f217ba4136e Story: 2005611 Task: 30858
This commit is contained in:
parent
46de66b240
commit
7fe78c5943
@ -1236,7 +1236,7 @@ protocol:
|
||||
protocol-pools:
|
||||
description: |
|
||||
The protocol for the resource. One of ``HTTP``, ``HTTPS``, ``PROXY``,
|
||||
``TCP``, or ``UDP``.
|
||||
``PROXYV2``, ``TCP``, or ``UDP``.
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
|
@ -102,7 +102,8 @@ is ready for further configuration.
|
||||
At a minimum, you must specify these pool attributes:
|
||||
|
||||
- ``protocol`` The protocol for which this pool and its members
|
||||
listen. A valid value is ``HTTP``, ``HTTPS``, ``PROXY``, ``TCP``, or ``UDP``.
|
||||
listen. A valid value is ``HTTP``, ``HTTPS``, ``PROXY``, ``PROXYV2``,
|
||||
``TCP``, or ``UDP``.
|
||||
|
||||
- ``lb_algorithm`` The load-balancer algorithm, such as
|
||||
``ROUND_ROBIN``, ``LEAST_CONNECTIONS``, ``SOURCE_IP`` and ``SOURCE_IP_PORT``,
|
||||
|
@ -114,6 +114,14 @@ cli=openstack loadbalancer pool create --protocol PROXY --listener <listener>
|
||||
driver.amphora=complete
|
||||
driver.ovn=missing
|
||||
|
||||
[operation.protocol.PROXYV2]
|
||||
title=protocol - PROXYV2
|
||||
status=optional
|
||||
notes=PROXY protocol version 2 support for the pool.
|
||||
cli=openstack loadbalancer pool create --protocol PROXYV2 --listener <listener>
|
||||
driver.amphora=complete
|
||||
driver.ovn=missing
|
||||
|
||||
[operation.protocol.TCP]
|
||||
title=protocol - TCP
|
||||
status=optional
|
||||
|
@ -128,6 +128,9 @@ class RootController(object):
|
||||
self._add_a_version(versions, 'v2.20', 'v2', 'SUPPORTED',
|
||||
'2020-08-02T00:00:00Z', host_url)
|
||||
# Amphora delete
|
||||
self._add_a_version(versions, 'v2.21', 'v2', 'CURRENT',
|
||||
self._add_a_version(versions, 'v2.21', 'v2', 'SUPPORTED',
|
||||
'2020-09-03T00:00:00Z', host_url)
|
||||
# Add PROXYV2 pool protocol
|
||||
self._add_a_version(versions, 'v2.22', 'v2', 'CURRENT',
|
||||
'2020-09-04T00:00:00Z', host_url)
|
||||
return {'versions': versions}
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from octavia_lib.common import constants as lib_constants
|
||||
from wsme import types as wtypes
|
||||
|
||||
from octavia.api.common import types
|
||||
@ -146,8 +147,9 @@ class PoolPOST(BasePoolType):
|
||||
admin_state_up = wtypes.wsattr(bool, default=True)
|
||||
listener_id = wtypes.wsattr(wtypes.UuidType())
|
||||
loadbalancer_id = wtypes.wsattr(wtypes.UuidType())
|
||||
protocol = wtypes.wsattr(wtypes.Enum(str, *constants.SUPPORTED_PROTOCOLS),
|
||||
mandatory=True)
|
||||
protocol = wtypes.wsattr(
|
||||
wtypes.Enum(str, *lib_constants.POOL_SUPPORTED_PROTOCOLS),
|
||||
mandatory=True)
|
||||
lb_algorithm = wtypes.wsattr(
|
||||
wtypes.Enum(str, *constants.SUPPORTED_LB_ALGORITHMS),
|
||||
mandatory=True)
|
||||
@ -198,7 +200,8 @@ class PoolSingleCreate(BasePoolType):
|
||||
name = wtypes.wsattr(wtypes.StringType(max_length=255))
|
||||
description = wtypes.wsattr(wtypes.StringType(max_length=255))
|
||||
admin_state_up = wtypes.wsattr(bool, default=True)
|
||||
protocol = wtypes.wsattr(wtypes.Enum(str, *constants.SUPPORTED_PROTOCOLS))
|
||||
protocol = wtypes.wsattr(
|
||||
wtypes.Enum(str, *lib_constants.POOL_SUPPORTED_PROTOCOLS))
|
||||
lb_algorithm = wtypes.wsattr(
|
||||
wtypes.Enum(str, *constants.SUPPORTED_LB_ALGORITHMS))
|
||||
session_persistence = wtypes.wsattr(SessionPersistencePOST)
|
||||
|
@ -207,10 +207,13 @@ UPDATE_HEALTH = 'UPDATE_HEALTH'
|
||||
|
||||
VALID_LISTENER_POOL_PROTOCOL_MAP = {
|
||||
PROTOCOL_TCP: [PROTOCOL_HTTP, PROTOCOL_HTTPS,
|
||||
PROTOCOL_PROXY, PROTOCOL_TCP],
|
||||
PROTOCOL_HTTP: [PROTOCOL_HTTP, PROTOCOL_PROXY],
|
||||
PROTOCOL_HTTPS: [PROTOCOL_HTTPS, PROTOCOL_PROXY, PROTOCOL_TCP],
|
||||
PROTOCOL_TERMINATED_HTTPS: [PROTOCOL_HTTP, PROTOCOL_PROXY],
|
||||
PROTOCOL_PROXY, lib_consts.PROTOCOL_PROXYV2, PROTOCOL_TCP],
|
||||
PROTOCOL_HTTP: [PROTOCOL_HTTP, PROTOCOL_PROXY,
|
||||
lib_consts.PROTOCOL_PROXYV2],
|
||||
PROTOCOL_HTTPS: [PROTOCOL_HTTPS, PROTOCOL_PROXY,
|
||||
lib_consts.PROTOCOL_PROXYV2, PROTOCOL_TCP],
|
||||
PROTOCOL_TERMINATED_HTTPS: [PROTOCOL_HTTP, PROTOCOL_PROXY,
|
||||
lib_consts.PROTOCOL_PROXYV2],
|
||||
PROTOCOL_UDP: [PROTOCOL_UDP]}
|
||||
|
||||
# API Integer Ranges
|
||||
@ -810,6 +813,7 @@ L4_PROTOCOL_MAP = {
|
||||
PROTOCOL_HTTPS: PROTOCOL_TCP,
|
||||
PROTOCOL_TERMINATED_HTTPS: PROTOCOL_TCP,
|
||||
PROTOCOL_PROXY: PROTOCOL_TCP,
|
||||
lib_consts.PROTOCOL_PROXYV2: PROTOCOL_TCP,
|
||||
PROTOCOL_UDP: PROTOCOL_UDP,
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,9 @@ class JinjaTemplater(object):
|
||||
os.path.join(self.base_crt_dir, loadbalancer.id,
|
||||
tls_certs[listener.client_crl_container_id]))
|
||||
|
||||
tls_enabled = False
|
||||
if listener.protocol == constants.PROTOCOL_TERMINATED_HTTPS:
|
||||
tls_enabled = True
|
||||
if listener.tls_ciphers is not None:
|
||||
ret_value['tls_ciphers'] = listener.tls_ciphers
|
||||
if listener.tls_versions is not None:
|
||||
@ -300,7 +302,7 @@ class JinjaTemplater(object):
|
||||
if tls_certs is not None and tls_certs.get(pool.id):
|
||||
kwargs = {'pool_tls_certs': tls_certs.get(pool.id)}
|
||||
pools.append(self._transform_pool(
|
||||
pool, feature_compatibility, **kwargs))
|
||||
pool, feature_compatibility, tls_enabled, **kwargs))
|
||||
ret_value['pools'] = pools
|
||||
policy_gen = (policy for policy in listener.l7policies if
|
||||
policy.provisioning_status != constants.PENDING_DELETE)
|
||||
@ -311,21 +313,27 @@ class JinjaTemplater(object):
|
||||
break
|
||||
|
||||
l7policies = [self._transform_l7policy(
|
||||
x, feature_compatibility, tls_certs)
|
||||
x, feature_compatibility, tls_enabled, tls_certs)
|
||||
for x in policy_gen]
|
||||
ret_value['l7policies'] = l7policies
|
||||
return ret_value
|
||||
|
||||
def _transform_pool(self, pool, feature_compatibility,
|
||||
pool_tls_certs=None):
|
||||
listener_tls_enabled, pool_tls_certs=None):
|
||||
"""Transforms a pool into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
"""
|
||||
proxy_protocol_version = None
|
||||
if pool.protocol == constants.PROTOCOL_PROXY:
|
||||
proxy_protocol_version = 1
|
||||
if pool.protocol == lib_consts.PROTOCOL_PROXYV2:
|
||||
proxy_protocol_version = 2
|
||||
ret_value = {
|
||||
'id': pool.id,
|
||||
'protocol': PROTOCOL_MAP[pool.protocol],
|
||||
'proxy_protocol': pool.protocol == constants.PROTOCOL_PROXY,
|
||||
'proxy_protocol': proxy_protocol_version,
|
||||
'listener_tls_enabled': listener_tls_enabled,
|
||||
'lb_algorithm': BALANCE_MAP.get(pool.lb_algorithm, 'roundrobin'),
|
||||
'members': [],
|
||||
'health_monitor': '',
|
||||
@ -425,7 +433,7 @@ class JinjaTemplater(object):
|
||||
}
|
||||
|
||||
def _transform_l7policy(self, l7policy, feature_compatibility,
|
||||
tls_certs=None):
|
||||
listener_tls_enabled, tls_certs=None):
|
||||
"""Transforms an L7 policy into an object that will
|
||||
|
||||
be processed by the templating system
|
||||
@ -446,7 +454,8 @@ class JinjaTemplater(object):
|
||||
kwargs = {'pool_tls_certs':
|
||||
tls_certs.get(l7policy.redirect_pool.id)}
|
||||
ret_value['redirect_pool'] = self._transform_pool(
|
||||
l7policy.redirect_pool, feature_compatibility, **kwargs)
|
||||
l7policy.redirect_pool, feature_compatibility,
|
||||
listener_tls_enabled, **kwargs)
|
||||
else:
|
||||
ret_value['redirect_pool'] = None
|
||||
if (l7policy.action in [constants.L7POLICY_ACTION_REDIRECT_TO_URL,
|
||||
|
@ -217,8 +217,14 @@ frontend {{ listener.id }}
|
||||
{% else %}
|
||||
{% set persistence_opt = "" %}
|
||||
{% endif %}
|
||||
{% if pool.proxy_protocol %}
|
||||
{% if pool.proxy_protocol == 1 %}
|
||||
{% set proxy_protocol_opt = " send-proxy" %}
|
||||
{% elif pool.proxy_protocol == 2 %}
|
||||
{% if pool.listener_tls_enabled %}
|
||||
{% set proxy_protocol_opt = " send-proxy-v2-ssl-cn" %}
|
||||
{% else %}
|
||||
{% set proxy_protocol_opt = " send-proxy-v2" %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set proxy_protocol_opt = "" %}
|
||||
{% endif %}
|
||||
@ -288,7 +294,7 @@ frontend {{ listener.id }}
|
||||
|
||||
{% macro backend_macro(constants, lib_consts, listener, pool, loadbalancer) %}
|
||||
backend {{ pool.id }}:{{ listener.id }}
|
||||
{% if pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() %}
|
||||
{% if pool.proxy_protocol is not none %}
|
||||
mode {{ listener.protocol_mode }}
|
||||
{% else %}
|
||||
mode {{ pool.protocol }}
|
||||
|
@ -0,0 +1,43 @@
|
||||
# Copyright 2020 Red Hat, Inc. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
"""Add PROXY v2 pool protocol
|
||||
|
||||
Revision ID: e6ee84f0abf3
|
||||
Revises: 2ab994dd3ec2
|
||||
Create Date: 2020-08-24 11:12:46.745185
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import sql
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'e6ee84f0abf3'
|
||||
down_revision = '2ab994dd3ec2'
|
||||
|
||||
|
||||
def upgrade():
|
||||
insert_table = sql.table(
|
||||
u'protocol',
|
||||
sql.column(u'name', sa.String),
|
||||
sql.column(u'description', sa.String)
|
||||
)
|
||||
|
||||
op.bulk_insert(
|
||||
insert_table,
|
||||
[
|
||||
{'name': 'PROXYV2'}
|
||||
]
|
||||
)
|
@ -11,6 +11,7 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from octavia_lib.common import constants as lib_constants
|
||||
|
||||
from octavia.common import constants
|
||||
|
||||
@ -280,4 +281,5 @@ INVALID_LISTENER_POOL_PROTOCOL_MAP = {
|
||||
constants.PROTOCOL_HTTP,
|
||||
constants.PROTOCOL_HTTPS,
|
||||
constants.PROTOCOL_TERMINATED_HTTPS,
|
||||
constants.PROTOCOL_PROXY]}
|
||||
constants.PROTOCOL_PROXY,
|
||||
lib_constants.PROTOCOL_PROXYV2]}
|
||||
|
@ -45,7 +45,7 @@ class TestRootController(base_db_test.OctaviaDBTestBase):
|
||||
def test_api_versions(self):
|
||||
versions = self._get_versions_with_config()
|
||||
version_ids = tuple(v.get('id') for v in versions)
|
||||
self.assertEqual(22, len(version_ids))
|
||||
self.assertEqual(23, len(version_ids))
|
||||
self.assertIn('v2.0', version_ids)
|
||||
self.assertIn('v2.1', version_ids)
|
||||
self.assertIn('v2.2', version_ids)
|
||||
@ -68,6 +68,7 @@ class TestRootController(base_db_test.OctaviaDBTestBase):
|
||||
self.assertIn('v2.19', version_ids)
|
||||
self.assertIn('v2.20', version_ids)
|
||||
self.assertIn('v2.21', version_ids)
|
||||
self.assertIn('v2.22', version_ids)
|
||||
|
||||
# Each version should have a 'self' 'href' to the API version URL
|
||||
# [{u'rel': u'self', u'href': u'http://localhost/v2'}]
|
||||
|
@ -1303,21 +1303,27 @@ class TestL7Policy(base.BaseAPITest):
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
port = port + 1
|
||||
for pool_proto in invalid_map[listener_proto]:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
if pool_proto == constants.PROTOCOL_TERMINATED_HTTPS:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN, status=400)
|
||||
self.assertIn("Invalid input", pool['faultstring'])
|
||||
else:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
|
||||
l7policy['listener_id'] = listener.get('id')
|
||||
l7policy['redirect_pool_id'] = pool.get('id')
|
||||
expect_error_msg = ("Validation failure: The pool protocol "
|
||||
"'%s' is invalid while the listener "
|
||||
"protocol is '%s'.") % (pool_proto,
|
||||
listener_proto)
|
||||
res = self.post(self.L7POLICIES_PATH,
|
||||
self._build_body(l7policy), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
l7policy['listener_id'] = listener.get('id')
|
||||
l7policy['redirect_pool_id'] = pool.get('id')
|
||||
expect_error_msg = (
|
||||
"Validation failure: The pool protocol '%s' is "
|
||||
"invalid while the listener protocol is '%s'.") % (
|
||||
pool_proto, listener_proto)
|
||||
res = self.post(self.L7POLICIES_PATH,
|
||||
self._build_body(l7policy), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
|
||||
@mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data')
|
||||
def test_listener_pool_protocol_map_put(self, mock_cert_data):
|
||||
@ -1361,21 +1367,27 @@ class TestL7Policy(base.BaseAPITest):
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
port = port + 1
|
||||
for pool_proto in invalid_map[listener_proto]:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
l7policy = self.create_l7policy(
|
||||
listener.get('id'),
|
||||
constants.L7POLICY_ACTION_REJECT).get(self.root_tag)
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
new_l7policy['redirect_pool_id'] = pool.get('id')
|
||||
expect_error_msg = ("Validation failure: The pool protocol "
|
||||
"'%s' is invalid while the listener "
|
||||
"protocol is '%s'.") % (pool_proto,
|
||||
listener_proto)
|
||||
res = self.put(self.L7POLICY_PATH.format(
|
||||
l7policy_id=l7policy.get('id')),
|
||||
self._build_body(new_l7policy), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
if pool_proto == constants.PROTOCOL_TERMINATED_HTTPS:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN, status=400)
|
||||
self.assertIn("Invalid input", pool['faultstring'])
|
||||
else:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
l7policy = self.create_l7policy(
|
||||
listener.get('id'),
|
||||
constants.L7POLICY_ACTION_REJECT).get(self.root_tag)
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
new_l7policy['redirect_pool_id'] = pool.get('id')
|
||||
expect_error_msg = (
|
||||
"Validation failure: The pool protocol '%s' is "
|
||||
"invalid while the listener protocol is '%s'.") % (
|
||||
pool_proto, listener_proto)
|
||||
res = self.put(self.L7POLICY_PATH.format(
|
||||
l7policy_id=l7policy.get('id')),
|
||||
self._build_body(new_l7policy), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
|
@ -2849,23 +2849,29 @@ class TestListener(base.BaseAPITest):
|
||||
for listener_proto in invalid_map:
|
||||
for pool_proto in invalid_map[listener_proto]:
|
||||
port = port + 1
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
expect_error_msg = ("Validation failure: The pool protocol "
|
||||
"'%s' is invalid while the listener "
|
||||
"protocol is '%s'.") % (pool_proto,
|
||||
listener_proto)
|
||||
listener = {'protocol': listener_proto,
|
||||
'protocol_port': port,
|
||||
'loadbalancer_id': self.lb_id,
|
||||
'default_pool_id': pool.get('id')}
|
||||
body = self._build_body(listener)
|
||||
res = self.post(self.LISTENERS_PATH, body,
|
||||
status=400, expect_errors=True)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
if pool_proto == constants.PROTOCOL_TERMINATED_HTTPS:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN, status=400)
|
||||
self.assertIn("Invalid input", pool['faultstring'])
|
||||
else:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
expect_error_msg = (
|
||||
"Validation failure: The pool protocol '%s' is "
|
||||
"invalid while the listener protocol is '%s'.") % (
|
||||
pool_proto, listener_proto)
|
||||
listener = {'protocol': listener_proto,
|
||||
'protocol_port': port,
|
||||
'loadbalancer_id': self.lb_id,
|
||||
'default_pool_id': pool.get('id')}
|
||||
body = self._build_body(listener)
|
||||
res = self.post(self.LISTENERS_PATH, body,
|
||||
status=400, expect_errors=True)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
|
||||
@mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data')
|
||||
def test_listener_pool_protocol_map_put(self, mock_cert_data):
|
||||
@ -2907,13 +2913,20 @@ class TestListener(base.BaseAPITest):
|
||||
"'%s' is invalid while the listener "
|
||||
"protocol is '%s'.") % (pool_proto,
|
||||
listener_proto)
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
new_listener = {'default_pool_id': pool.get('id')}
|
||||
res = self.put(
|
||||
self.LISTENER_PATH.format(listener_id=listener.get('id')),
|
||||
self._build_body(new_listener), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
if pool_proto == constants.PROTOCOL_TERMINATED_HTTPS:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN, status=400)
|
||||
self.assertIn("Invalid input", pool['faultstring'])
|
||||
else:
|
||||
pool = self.create_pool(
|
||||
self.lb_id, pool_proto,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN).get('pool')
|
||||
self.set_object_status(self.lb_repo, self.lb_id)
|
||||
new_listener = {'default_pool_id': pool.get('id')}
|
||||
res = self.put(
|
||||
self.LISTENER_PATH.format(
|
||||
listener_id=listener.get('id')),
|
||||
self._build_body(new_listener), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from octavia_lib.common import constants as lib_constants
|
||||
from oslo_config import cfg
|
||||
from oslo_config import fixture as oslo_fixture
|
||||
from oslo_utils import uuidutils
|
||||
@ -765,6 +766,30 @@ class TestPool(base.BaseAPITest):
|
||||
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||
pool_id=api_pool.get('id'))
|
||||
|
||||
def test_create_with_proxy_v2_protocol(self):
|
||||
api_pool = self.create_pool(
|
||||
self.lb_id,
|
||||
lib_constants.PROTOCOL_PROXYV2,
|
||||
constants.LB_ALGORITHM_ROUND_ROBIN,
|
||||
listener_id=self.listener_id).get(self.root_tag)
|
||||
self.assert_correct_status(
|
||||
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||
pool_id=api_pool.get('id'),
|
||||
lb_prov_status=constants.PENDING_UPDATE,
|
||||
listener_prov_status=constants.PENDING_UPDATE,
|
||||
pool_prov_status=constants.PENDING_CREATE,
|
||||
pool_op_status=constants.OFFLINE)
|
||||
self.set_lb_status(self.lb_id)
|
||||
self.assertEqual(lib_constants.PROTOCOL_PROXYV2,
|
||||
api_pool.get('protocol'))
|
||||
self.assertEqual(constants.LB_ALGORITHM_ROUND_ROBIN,
|
||||
api_pool.get('lb_algorithm'))
|
||||
self.assertIsNotNone(api_pool.get('created_at'))
|
||||
self.assertIsNone(api_pool.get('updated_at'))
|
||||
self.assert_correct_status(
|
||||
lb_id=self.lb_id, listener_id=self.listener_id,
|
||||
pool_id=api_pool.get('id'))
|
||||
|
||||
def test_create_sans_listener(self):
|
||||
api_pool = self.create_pool(
|
||||
self.lb_id,
|
||||
@ -2382,5 +2407,10 @@ class TestPool(base.BaseAPITest):
|
||||
lb_pool['listener_id'] = listener.get('id')
|
||||
res = self.post(self.POOLS_PATH, self._build_body(lb_pool),
|
||||
status=400, expect_errors=True)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
if pool_proto == constants.PROTOCOL_TERMINATED_HTTPS:
|
||||
self.assertIn('Invalid input',
|
||||
res.json['faultstring'])
|
||||
else:
|
||||
self.assertEqual(expect_error_msg,
|
||||
res.json['faultstring'])
|
||||
self.assert_correct_status(lb_id=self.lb_id)
|
||||
|
@ -1288,18 +1288,18 @@ class TestHaproxyCfg(base.TestCase):
|
||||
|
||||
def test_transform_pool(self):
|
||||
in_pool = sample_configs_combined.sample_pool_tuple()
|
||||
ret = self.jinja_cfg._transform_pool(in_pool, {})
|
||||
ret = self.jinja_cfg._transform_pool(in_pool, {}, False)
|
||||
self.assertEqual(sample_configs_combined.RET_POOL_1, ret)
|
||||
|
||||
def test_transform_pool_2(self):
|
||||
in_pool = sample_configs_combined.sample_pool_tuple(sample_pool=2)
|
||||
ret = self.jinja_cfg._transform_pool(in_pool, {})
|
||||
ret = self.jinja_cfg._transform_pool(in_pool, {}, False)
|
||||
self.assertEqual(sample_configs_combined.RET_POOL_2, ret)
|
||||
|
||||
def test_transform_pool_http_reuse(self):
|
||||
in_pool = sample_configs_combined.sample_pool_tuple(sample_pool=2)
|
||||
ret = self.jinja_cfg._transform_pool(
|
||||
in_pool, {constants.HTTP_REUSE: True})
|
||||
in_pool, {constants.HTTP_REUSE: True}, False)
|
||||
expected_config = copy.copy(sample_configs_combined.RET_POOL_2)
|
||||
expected_config[constants.HTTP_REUSE] = True
|
||||
self.assertEqual(expected_config, ret)
|
||||
@ -1309,7 +1309,7 @@ class TestHaproxyCfg(base.TestCase):
|
||||
cert_path = os.path.join(self.jinja_cfg.base_crt_dir,
|
||||
'test_listener_id', 'pool_cert.pem')
|
||||
ret = self.jinja_cfg._transform_pool(
|
||||
in_pool, {}, pool_tls_certs={'client_cert': cert_path})
|
||||
in_pool, {}, False, pool_tls_certs={'client_cert': cert_path})
|
||||
expected_config = copy.copy(sample_configs_combined.RET_POOL_1)
|
||||
expected_config['client_cert'] = cert_path
|
||||
self.assertEqual(expected_config, ret)
|
||||
@ -1383,25 +1383,25 @@ class TestHaproxyCfg(base.TestCase):
|
||||
def test_transform_l7policy(self):
|
||||
in_l7policy = sample_configs_combined.sample_l7policy_tuple(
|
||||
'sample_l7policy_id_1')
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {})
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}, False)
|
||||
self.assertEqual(sample_configs_combined.RET_L7POLICY_1, ret)
|
||||
|
||||
def test_transform_l7policy_2_8(self):
|
||||
in_l7policy = sample_configs_combined.sample_l7policy_tuple(
|
||||
'sample_l7policy_id_2', sample_policy=2)
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {})
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}, False)
|
||||
self.assertEqual(sample_configs_combined.RET_L7POLICY_2, ret)
|
||||
|
||||
# test invalid action without redirect_http_code
|
||||
in_l7policy = sample_configs_combined.sample_l7policy_tuple(
|
||||
'sample_l7policy_id_8', sample_policy=2, redirect_http_code=None)
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {})
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}, False)
|
||||
self.assertEqual(sample_configs_combined.RET_L7POLICY_8, ret)
|
||||
|
||||
def test_transform_l7policy_disabled_rule(self):
|
||||
in_l7policy = sample_configs_combined.sample_l7policy_tuple(
|
||||
'sample_l7policy_id_6', sample_policy=6)
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {})
|
||||
ret = self.jinja_cfg._transform_l7policy(in_l7policy, {}, False)
|
||||
self.assertEqual(sample_configs_combined.RET_L7POLICY_6, ret)
|
||||
|
||||
def test_escape_haproxy_config_string(self):
|
||||
|
@ -117,8 +117,9 @@ RET_MEMBER_3 = {
|
||||
RET_POOL_1 = {
|
||||
'id': 'sample_pool_id_1',
|
||||
'protocol': 'http',
|
||||
'proxy_protocol': False,
|
||||
'proxy_protocol': None,
|
||||
'lb_algorithm': 'roundrobin',
|
||||
'listener_tls_enabled': False,
|
||||
'members': [RET_MEMBER_1, RET_MEMBER_2],
|
||||
'health_monitor': RET_MONITOR_1,
|
||||
'session_persistence': RET_PERSISTENCE,
|
||||
@ -134,8 +135,9 @@ RET_POOL_1 = {
|
||||
RET_POOL_2 = {
|
||||
'id': 'sample_pool_id_2',
|
||||
'protocol': 'http',
|
||||
'proxy_protocol': False,
|
||||
'proxy_protocol': None,
|
||||
'lb_algorithm': 'roundrobin',
|
||||
'listener_tls_enabled': False,
|
||||
'members': [RET_MEMBER_3],
|
||||
'health_monitor': RET_MONITOR_2,
|
||||
'session_persistence': RET_PERSISTENCE,
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for proxy protocol version 2.
|
Loading…
Reference in New Issue
Block a user