diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst index 73734242b1..d63ee5d1c0 100644 --- a/doc/source/user/index.rst +++ b/doc/source/user/index.rst @@ -347,6 +347,8 @@ the table are linked to more details elsewhere in the user guide. +---------------------------------------+--------------------+---------------+ | `ingress_controller_role`_ | see below | "ingress" | +---------------------------------------+--------------------+---------------+ +| `octavia_ingress_controller_tag`_ | see below | see below | ++---------------------------------------+--------------------+---------------+ | `kubelet_options`_ | extra kubelet args | "" | +---------------------------------------+--------------------+---------------+ | `kubeapi_options`_ | extra kubeapi args | "" | @@ -1235,8 +1237,11 @@ Magnum allows selecting one of multiple controller options via the your own Ingress resources. _`ingress_controller` - This label sets the Ingress Controller to be used. Currently only traefik - is supported. The default is '', meaning no Ingress Controller configured. + This label sets the Ingress Controller to be used. Currently 'traefik' and + 'octavia' are supported. The default is '', meaning no Ingress Controller + configured. For more details about octavia-ingress-controller please refer + to `cloud-provider-openstack document + `_ _`ingress_controller_role` This label defines the role nodes should have to run an instance of the @@ -1247,6 +1252,11 @@ _`ingress_controller_role` kubectl label node role=ingress + This lable is not used for octavia-ingress-controller. + +_`octavia_ingress_controller_tag` + The image tag for octavia-ingress-controller. Stain-default: 1.13.2-alpha + DNS --- diff --git a/magnum/common/neutron.py b/magnum/common/neutron.py index 06b3472def..7036f44d4e 100644 --- a/magnum/common/neutron.py +++ b/magnum/common/neutron.py @@ -53,3 +53,25 @@ def delete_floatingip(context, fix_port_id, cluster): except Exception as e: raise exception.PreDeletionFailed(cluster_uuid=cluster.uuid, msg=str(e)) + + +def get_network_id(context, network_name): + nets = [] + n_client = clients.OpenStackClients(context).neutron() + ext_filter = {'router:external': True} + + networks = n_client.list_networks(**ext_filter) + for net in networks.get('networks'): + if net.get('name') == network_name: + nets.append(net) + + if len(nets) == 0: + raise exception.ExternalNetworkNotFound(network=network_name) + + if len(nets) > 1: + raise exception.Conflict( + "Multiple networks exist with same name '%s'. Please use the " + "network ID instead." % network_name + ) + + return nets[0]["id"] diff --git a/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-controller.sh b/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-controller.sh index 75518c52cd..a76c7d6116 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-controller.sh +++ b/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-controller.sh @@ -3,9 +3,6 @@ step="enable-ingress-controller" printf "Starting to run ${step}\n" -# Enables the specified ingress controller. -# -# Currently there is only support for traefik. . /etc/sysconfig/heat-params function writeFile { @@ -21,8 +18,20 @@ EOF } } -if [ "$(echo $INGRESS_CONTROLLER | tr '[:upper:]' '[:lower:]')" = "traefik" ]; then +ingress_controller=$(echo $INGRESS_CONTROLLER | tr '[:upper:]' '[:lower:]') +case "$ingress_controller" in +"") + echo "No ingress controller configured." + ;; +"traefik") $enable-ingress-traefik -fi + ;; +"octavia") + $enable-ingress-octavia + ;; +*) + echo "Ingress controller $ingress_controller not supported." + ;; +esac printf "Finished running ${step}\n" diff --git a/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-octavia.sh b/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-octavia.sh new file mode 100644 index 0000000000..622a6e24c3 --- /dev/null +++ b/magnum/drivers/common/templates/kubernetes/fragments/enable-ingress-octavia.sh @@ -0,0 +1,122 @@ +# octavia-ingress-controller RBAC +OCTAVIA_INGRESS_CONTROLLER_RBAC=/srv/magnum/kubernetes/manifests/octavia-ingress-controller-rbac.yaml +OCTAVIA_INGRESS_CONTROLLER_RBAC_CONTENT=$(cat < @@ -754,6 +758,7 @@ resources: pods_network_cidr: {get_param: pods_network_cidr} ingress_controller: {get_param: ingress_controller} ingress_controller_role: {get_param: ingress_controller_role} + octavia_ingress_controller_tag: {get_param: octavia_ingress_controller_tag} kubelet_options: {get_param: kubelet_options} kubeapi_options: {get_param: kubeapi_options} kubeproxy_options: {get_param: kubeproxy_options} @@ -791,6 +796,7 @@ resources: - str_replace: params: $enable-ingress-traefik: {get_file: ../../common/templates/kubernetes/fragments/enable-ingress-traefik.sh} + $enable-ingress-octavia: {get_file: ../../common/templates/kubernetes/fragments/enable-ingress-octavia.sh} template: {get_file: ../../common/templates/kubernetes/fragments/enable-ingress-controller.sh} - get_file: ../../common/templates/kubernetes/fragments/kube-dashboard-service.sh - get_file: ../../common/templates/kubernetes/fragments/enable-keystone-auth.sh diff --git a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml index 355cb32391..d9173aa3d9 100644 --- a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml +++ b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml @@ -25,7 +25,7 @@ parameters: external_network: type: string - description: uuid/name of a network to use for floating ip addresses + description: uuid of a network to use for floating ip addresses portal_network_cidr: type: string @@ -341,6 +341,10 @@ parameters: description: > node role where the ingress controller should run + octavia_ingress_controller_tag: + type: string + description: Octavia ingress controller docker image tag. + kubelet_options: type: string description: > @@ -504,6 +508,7 @@ resources: "$CALICO_IPV4POOL": {get_param: calico_ipv4pool} "$INGRESS_CONTROLLER": {get_param: ingress_controller} "$INGRESS_CONTROLLER_ROLE": {get_param: ingress_controller_role} + "$OCTAVIA_INGRESS_CONTROLLER_TAG": {get_param: octavia_ingress_controller_tag} "$KUBELET_OPTIONS": {get_param: kubelet_options} "$KUBEAPI_OPTIONS": {get_param: kubeapi_options} "$KUBECONTROLLER_OPTIONS": {get_param: kubecontroller_options} @@ -518,6 +523,7 @@ resources: "$KEYSTONE_AUTH_ENABLED": {get_param: keystone_auth_enabled} "$K8S_KEYSTONE_AUTH_TAG": {get_param: k8s_keystone_auth_tag} "$PROJECT_ID": {get_param: project_id} + "$EXTERNAL_NETWORK_ID": {get_param: external_network} install_openstack_ca: type: OS::Heat::SoftwareConfig diff --git a/magnum/tests/unit/common/test_neutron.py b/magnum/tests/unit/common/test_neutron.py index 87438759d7..b8448fed00 100644 --- a/magnum/tests/unit/common/test_neutron.py +++ b/magnum/tests/unit/common/test_neutron.py @@ -136,3 +136,84 @@ class NeutronTest(base.TestCase): fake_port_id, self.cluster ) + + @mock.patch('magnum.common.clients.OpenStackClients') + def test_get_network_id(self, mock_clients): + fake_name = "fake_network" + fake_id = "24fe5da0-1ac0-11e9-84cd-00224d6b7bc1" + mock_nclient = mock.MagicMock() + mock_nclient.list_networks.return_value = { + 'networks': [ + { + 'id': fake_id, + 'name': fake_name, + 'router:external': True + } + ] + } + + osc = mock.MagicMock() + mock_clients.return_value = osc + osc.neutron.return_value = mock_nclient + + network_id = neutron.get_network_id(self.context, fake_name) + + self.assertEqual(fake_id, network_id) + + @mock.patch('magnum.common.clients.OpenStackClients') + def test_get_network_id_notfound(self, mock_clients): + fake_name = "fake_network" + fake_id = "24fe5da0-1ac0-11e9-84cd-00224d6b7bc1" + mock_nclient = mock.MagicMock() + mock_nclient.list_networks.return_value = { + 'networks': [ + { + 'id': fake_id, + 'name': fake_name, + 'router:external': True + } + ] + } + + osc = mock.MagicMock() + mock_clients.return_value = osc + osc.neutron.return_value = mock_nclient + + self.assertRaises( + exception.ExternalNetworkNotFound, + neutron.get_network_id, + self.context, + "another_network" + ) + + @mock.patch('magnum.common.clients.OpenStackClients') + def test_get_network_id_conflict(self, mock_clients): + fake_name = "fake_network" + fake_id_1 = "24fe5da0-1ac0-11e9-84cd-00224d6b7bc1" + fake_id_2 = "93781f82-1ac0-11e9-84cd-00224d6b7bc1" + mock_nclient = mock.MagicMock() + mock_nclient.list_networks.return_value = { + 'networks': [ + { + 'id': fake_id_1, + 'name': fake_name, + 'router:external': True + }, + { + 'id': fake_id_2, + 'name': fake_name, + 'router:external': True + } + ] + } + + osc = mock.MagicMock() + mock_clients.return_value = osc + osc.neutron.return_value = mock_nclient + + self.assertRaises( + exception.Conflict, + neutron.get_network_id, + self.context, + fake_name + ) diff --git a/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py b/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py index 8cba6782a6..9d86dd845d 100644 --- a/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py @@ -33,7 +33,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'master_flavor_id': 'master_flavor_id', 'keypair_id': 'keypair_id', 'dns_nameserver': 'dns_nameserver', - 'external_network_id': 'external_network_id', + 'external_network_id': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'fixed_network': 'fixed_network', 'fixed_subnet': 'fixed_subnet', 'network_driver': 'network_driver', @@ -232,7 +232,7 @@ class TestClusterConductorWithK8s(base.TestCase): } expected = { 'ssh_key_name': 'keypair_id', - 'external_network': 'external_network_id', + 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'fixed_network': 'fixed_network', 'fixed_subnet': 'fixed_subnet', 'network_driver': 'network_driver', @@ -282,6 +282,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'cert_manager_api': 'False', 'ingress_controller': 'i-controller', 'ingress_controller_role': 'i-controller-role', + 'octavia_ingress_controller_tag': None, 'kubelet_options': '--kubelet', 'kubeapi_options': '--kubeapi', 'kubecontroller_options': '--kubecontroller', @@ -358,7 +359,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'docker_volume_size': 20, 'docker_volume_type': 'lvmdriver-1', 'etcd_volume_size': None, - 'external_network': 'external_network_id', + 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'fixed_network': 'fixed_network', 'fixed_subnet': 'fixed_subnet', 'flannel_backend': 'vxlan', @@ -403,6 +404,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'cert_manager_api': 'False', 'ingress_controller': 'i-controller', 'ingress_controller_role': 'i-controller-role', + 'octavia_ingress_controller_tag': None, 'kubelet_options': '--kubelet', 'kubeapi_options': '--kubeapi', 'kubecontroller_options': '--kubecontroller', @@ -476,7 +478,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'docker_volume_size': 20, 'master_flavor': 'master_flavor_id', 'minion_flavor': 'flavor_id', - 'external_network': 'external_network_id', + 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'flannel_backend': 'vxlan', 'flannel_network_cidr': '10.101.0.0/16', 'flannel_network_subnetlen': '26', @@ -511,6 +513,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'cert_manager_api': 'False', 'ingress_controller': 'i-controller', 'ingress_controller_role': 'i-controller-role', + 'octavia_ingress_controller_tag': None, 'kubelet_options': '--kubelet', 'kubeapi_options': '--kubeapi', 'kubecontroller_options': '--kubecontroller', @@ -561,7 +564,7 @@ class TestClusterConductorWithK8s(base.TestCase): expected = { 'ssh_key_name': 'keypair_id', - 'external_network': 'external_network_id', + 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'fixed_network': 'fixed_network', 'fixed_subnet': 'fixed_subnet', 'availability_zone': 'az_1', @@ -612,6 +615,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'cert_manager_api': 'False', 'ingress_controller': 'i-controller', 'ingress_controller_role': 'i-controller-role', + 'octavia_ingress_controller_tag': None, 'kubelet_options': '--kubelet', 'kubeapi_options': '--kubeapi', 'kubecontroller_options': '--kubecontroller', @@ -657,7 +661,7 @@ class TestClusterConductorWithK8s(base.TestCase): expected = { 'ssh_key_name': 'keypair_id', 'availability_zone': 'az_1', - 'external_network': 'external_network_id', + 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'fixed_network': 'fixed_network', 'fixed_subnet': 'fixed_subnet', 'dns_nameserver': 'dns_nameserver', @@ -707,6 +711,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'cert_manager_api': 'False', 'ingress_controller': 'i-controller', 'ingress_controller_role': 'i-controller-role', + 'octavia_ingress_controller_tag': None, 'kubelet_options': '--kubelet', 'kubeapi_options': '--kubeapi', 'kubecontroller_options': '--kubecontroller', @@ -896,7 +901,7 @@ class TestClusterConductorWithK8s(base.TestCase): expected = { 'ssh_key_name': 'keypair_id', - 'external_network': 'external_network_id', + 'external_network': 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e', 'fixed_network': 'fixed_network', 'fixed_subnet': 'fixed_subnet', 'dns_nameserver': 'dns_nameserver', @@ -946,6 +951,7 @@ class TestClusterConductorWithK8s(base.TestCase): 'cert_manager_api': 'False', 'ingress_controller': 'i-controller', 'ingress_controller_role': 'i-controller-role', + 'octavia_ingress_controller_tag': None, 'kubelet_options': '--kubelet', 'kubeapi_options': '--kubeapi', 'kubecontroller_options': '--kubecontroller', diff --git a/magnum/tests/unit/drivers/test_template_definition.py b/magnum/tests/unit/drivers/test_template_definition.py index fb1794d7e0..96f5f1f62a 100644 --- a/magnum/tests/unit/drivers/test_template_definition.py +++ b/magnum/tests/unit/drivers/test_template_definition.py @@ -326,6 +326,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): mock_cluster_template.tls_disabled = False mock_cluster_template.registry_enabled = False mock_cluster_template.network_driver = 'flannel' + external_network_id = '17e4e301-b7f3-4996-b3dd-97b3a700174b' + mock_cluster_template.external_network_id = external_network_id mock_cluster = mock.MagicMock() mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52' del mock_cluster.stack_id @@ -384,9 +386,11 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): cgroup_driver = mock_cluster.labels.get( 'cgroup_driver') ingress_controller = mock_cluster.labels.get( - 'ingress_controller') + 'ingress_controller').lower() ingress_controller_role = mock_cluster.labels.get( 'ingress_controller_role') + octavia_ingress_controller_tag = mock_cluster.labels.get( + 'octavia_ingress_controller_tag') kubelet_options = mock_cluster.labels.get( 'kubelet_options') kubeapi_options = mock_cluster.labels.get( @@ -459,6 +463,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): 'pods_network_cidr': pods_network_cidr, 'ingress_controller': ingress_controller, 'ingress_controller_role': ingress_controller_role, + 'octavia_ingress_controller_tag': octavia_ingress_controller_tag, 'octavia_enabled': False, 'kube_service_account_key': 'public_key', 'kube_service_account_private_key': 'private_key', @@ -469,6 +474,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): 'keystone_auth_enabled': keystone_auth_enabled, 'k8s_keystone_auth_tag': k8s_keystone_auth_tag, 'project_id': project_id, + 'external_network': external_network_id }} mock_get_params.assert_called_once_with(mock_context, mock_cluster_template, @@ -486,6 +492,170 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): mock_cluster, ) + @mock.patch('magnum.common.neutron.get_network_id') + @mock.patch('magnum.common.keystone.is_octavia_enabled') + @mock.patch('magnum.common.clients.OpenStackClients') + @mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def' + '.AtomicK8sTemplateDefinition.get_discovery_url') + @mock.patch('magnum.drivers.heat.template_def.BaseTemplateDefinition' + '.get_params') + @mock.patch('magnum.drivers.heat.template_def.TemplateDefinition' + '.get_output') + @mock.patch('magnum.common.x509.operations.generate_csr_and_key') + def test_k8s_get_params_external_network_id(self, + mock_generate_csr_and_key, + mock_get_output, + mock_get_params, + mock_get_discovery_url, + mock_osc_class, + mock_enable_octavia, + mock_network_id): + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'private_key': 'private_key', + 'public_key': 'public_key'} + mock_enable_octavia.return_value = False + mock_get_discovery_url.return_value = 'fake_discovery_url' + external_network_id = 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e' + mock_network_id.return_value = external_network_id + + mock_context = mock.MagicMock() + mock_context.auth_token = 'AUTH_TOKEN' + mock_context.auth_url = 'http://192.168.10.10:5000/v3' + mock_context.user_name = 'fake_user' + + mock_cluster_template = mock.MagicMock() + mock_cluster_template.tls_disabled = False + mock_cluster_template.registry_enabled = False + mock_cluster_template.network_driver = 'calico' + mock_cluster_template.external_network_id = "public" + + mock_cluster = mock.MagicMock() + mock_cluster.labels = {} + mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52' + + mock_osc = mock.MagicMock() + mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1' + mock_osc.cinder_region_name.return_value = 'RegionOne' + mock_osc_class.return_value = mock_osc + + k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition() + k8s_def.get_params(mock_context, mock_cluster_template, mock_cluster) + + actual_params = mock_get_params.call_args[1]["extra_params"] + self.assertEqual( + external_network_id, + actual_params.get("external_network") + ) + mock_network_id.assert_called_once_with( + mock_context, + mock_cluster_template.external_network_id + ) + + @mock.patch('magnum.common.keystone.is_octavia_enabled') + @mock.patch('magnum.common.clients.OpenStackClients') + @mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def' + '.AtomicK8sTemplateDefinition.get_discovery_url') + @mock.patch('magnum.drivers.heat.template_def.BaseTemplateDefinition' + '.get_params') + @mock.patch('magnum.drivers.heat.template_def.TemplateDefinition' + '.get_output') + @mock.patch('magnum.common.x509.operations.generate_csr_and_key') + def test_k8s_get_params_octavia_disabled(self, + mock_generate_csr_and_key, + mock_get_output, + mock_get_params, + mock_get_discovery_url, + mock_osc_class, + mock_enable_octavia): + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'private_key': 'private_key', + 'public_key': 'public_key'} + mock_enable_octavia.return_value = False + mock_get_discovery_url.return_value = 'fake_discovery_url' + + mock_context = mock.MagicMock() + mock_context.auth_token = 'AUTH_TOKEN' + mock_context.auth_url = 'http://192.168.10.10:5000/v3' + mock_context.user_name = 'fake_user' + + mock_cluster_template = mock.MagicMock() + mock_cluster_template.tls_disabled = False + mock_cluster_template.registry_enabled = False + mock_cluster_template.network_driver = 'calico' + external_network_id = 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e' + mock_cluster_template.external_network_id = external_network_id + + mock_cluster = mock.MagicMock() + mock_cluster.labels = {"ingress_controller": "octavia"} + mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52' + + mock_osc = mock.MagicMock() + mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1' + mock_osc.cinder_region_name.return_value = 'RegionOne' + mock_osc_class.return_value = mock_osc + + k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition() + + self.assertRaises( + exception.InvalidParameterValue, + k8s_def.get_params, + mock_context, + mock_cluster_template, + mock_cluster, + ) + + @mock.patch('magnum.common.keystone.is_octavia_enabled') + @mock.patch('magnum.common.clients.OpenStackClients') + @mock.patch('magnum.drivers.k8s_fedora_atomic_v1.template_def' + '.AtomicK8sTemplateDefinition.get_discovery_url') + @mock.patch('magnum.drivers.heat.template_def.BaseTemplateDefinition' + '.get_params') + @mock.patch('magnum.drivers.heat.template_def.TemplateDefinition' + '.get_output') + @mock.patch('magnum.common.x509.operations.generate_csr_and_key') + def test_k8s_get_params_octavia_enabled(self, + mock_generate_csr_and_key, + mock_get_output, + mock_get_params, + mock_get_discovery_url, + mock_osc_class, + mock_enable_octavia): + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'private_key': 'private_key', + 'public_key': 'public_key'} + mock_enable_octavia.return_value = True + mock_get_discovery_url.return_value = 'fake_discovery_url' + + mock_context = mock.MagicMock() + mock_context.auth_token = 'AUTH_TOKEN' + mock_context.auth_url = 'http://192.168.10.10:5000/v3' + mock_context.user_name = 'fake_user' + + mock_cluster_template = mock.MagicMock() + mock_cluster_template.tls_disabled = False + mock_cluster_template.registry_enabled = False + mock_cluster_template.network_driver = 'calico' + external_network_id = 'e2a6c8b0-a3c2-42a3-b3f4-01400a30896e' + mock_cluster_template.external_network_id = external_network_id + + mock_cluster = mock.MagicMock() + mock_cluster.labels = {"ingress_controller": "octavia"} + mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52' + + mock_osc = mock.MagicMock() + mock_osc.magnum_url.return_value = 'http://127.0.0.1:9511/v1' + mock_osc.cinder_region_name.return_value = 'RegionOne' + mock_osc_class.return_value = mock_osc + + k8s_def = k8sa_tdef.AtomicK8sTemplateDefinition() + k8s_def.get_params(mock_context, mock_cluster_template, mock_cluster) + + actual_params = mock_get_params.call_args[1]["extra_params"] + self.assertEqual( + "octavia", + actual_params.get("ingress_controller") + ) + @mock.patch('magnum.common.keystone.is_octavia_enabled') @mock.patch('magnum.common.clients.OpenStackClients') @mock.patch('magnum.drivers.heat.template_def' @@ -513,6 +683,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): mock_cluster_template.tls_disabled = True mock_cluster_template.registry_enabled = False mock_cluster_template.network_driver = 'calico' + external_network_id = '17e4e301-b7f3-4996-b3dd-97b3a700174b' + mock_cluster_template.external_network_id = external_network_id mock_cluster = mock.MagicMock() mock_cluster.uuid = '5d12f6fd-a196-4bf0-ae4c-1f639a523a52' del mock_cluster.stack_id @@ -571,9 +743,11 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): cgroup_driver = mock_cluster.labels.get( 'cgroup_driver') ingress_controller = mock_cluster.labels.get( - 'ingress_controller') + 'ingress_controller').lower() ingress_controller_role = mock_cluster.labels.get( 'ingress_controller_role') + octavia_ingress_controller_tag = mock_cluster.labels.get( + 'octavia_ingress_controller_tag') kubelet_options = mock_cluster.labels.get( 'kubelet_options') kubeapi_options = mock_cluster.labels.get( @@ -648,6 +822,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): 'pods_network_cidr': pods_network_cidr, 'ingress_controller': ingress_controller, 'ingress_controller_role': ingress_controller_role, + 'octavia_ingress_controller_tag': octavia_ingress_controller_tag, 'octavia_enabled': False, 'kube_service_account_key': 'public_key', 'kube_service_account_private_key': 'private_key', @@ -658,6 +833,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase): 'keystone_auth_enabled': keystone_auth_enabled, 'k8s_keystone_auth_tag': k8s_keystone_auth_tag, 'project_id': project_id, + 'external_network': external_network_id }} mock_get_params.assert_called_once_with(mock_context, mock_cluster_template, diff --git a/releasenotes/notes/k8s-octavia-ingress-controller-32c0b97031fd0dd4.yaml b/releasenotes/notes/k8s-octavia-ingress-controller-32c0b97031fd0dd4.yaml new file mode 100644 index 0000000000..15fdb32f92 --- /dev/null +++ b/releasenotes/notes/k8s-octavia-ingress-controller-32c0b97031fd0dd4.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Add a new option 'octavia' for the label 'ingress_controller' and a new + label 'octavia_ingress_controller_tag' to enable the deployment of + `octavia-ingress-controller `_ + in the kubernetes cluster. The 'ingress_controller_role' label is not used + for this option.