Specify database instance access during creation
Change-Id: I75950ae949e7f19e48f5246e4db9f5d5c514dd2b
This commit is contained in:
parent
2db165a81a
commit
c9d6d03a0f
@ -7,3 +7,4 @@ oslo.log>=3.30.0 # Apache-2.0
|
||||
python-swiftclient>=2.2.0
|
||||
python-troveclient>=1.2.0
|
||||
horizon>=17.1.0 # Apache-2.0
|
||||
netaddr>=0.7.18 # BSD
|
||||
|
@ -149,7 +149,7 @@ def instance_create(request, name, volume, flavor=None, databases=None,
|
||||
datastore=None, datastore_version=None,
|
||||
replica_of=None, replica_count=None,
|
||||
volume_type=None, configuration=None, locality=None,
|
||||
availability_zone=None):
|
||||
availability_zone=None, access=None):
|
||||
# TODO(dklyle): adding conditional to support trove without volume
|
||||
# support for now until API supports checking for volume support
|
||||
if volume > 0 and not replica_of:
|
||||
@ -179,7 +179,8 @@ def instance_create(request, name, volume, flavor=None, databases=None,
|
||||
replica_count=replica_count,
|
||||
configuration=configuration,
|
||||
locality=locality,
|
||||
availability_zone=availability_zone)
|
||||
availability_zone=availability_zone,
|
||||
access=access)
|
||||
|
||||
|
||||
def instance_resize_volume(request, instance_id, size):
|
||||
|
@ -214,7 +214,7 @@ class DatabasesBackupsTests(test.TestCase):
|
||||
url = RESTORE_URL + '?backup=%s' % self.database_backups.first().id
|
||||
res = self.client.get(url)
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_check, 4, mock.call((), test.IsHttpRequest()))
|
||||
self.mock_check, 5, mock.call((), test.IsHttpRequest()))
|
||||
self.mock_backup_get.assert_called_once_with(
|
||||
test.IsHttpRequest(), test.IsA(str))
|
||||
self.mock_backup_list.assert_called_once_with(test.IsHttpRequest())
|
||||
|
@ -0,0 +1,4 @@
|
||||
{% load i18n %}
|
||||
|
||||
<p>{% blocktrans trimmed %}Access defines how the database service is exposed.{% endblocktrans %}</p>
|
||||
<p>{% blocktrans trimmed %}CIDRs is a comma-separated list of IPv4, IPv6 or mix of both CIDRs that restrict access to the database service. 0.0.0.0/0 is used by default if this parameter is not provided. E.g.: 0.0.0.0/0,202.78.240.0/24{% endblocktrans %}</p>
|
@ -163,7 +163,7 @@ class DatabaseTests(test.TestCase):
|
||||
|
||||
res = self.client.get(LAUNCH_URL)
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_check, 4, mock.call((), test.IsHttpRequest()))
|
||||
self.mock_check, 5, mock.call((), test.IsHttpRequest()))
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_datastore_flavors, 20,
|
||||
mock.call(test.IsHttpRequest(),
|
||||
@ -269,7 +269,7 @@ class DatabaseTests(test.TestCase):
|
||||
|
||||
res = self.client.post(LAUNCH_URL, post)
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_check, 4, mock.call((), test.IsHttpRequest()))
|
||||
self.mock_check, 5, mock.call((), test.IsHttpRequest()))
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_datastore_flavors, 20,
|
||||
mock.call(test.IsHttpRequest(),
|
||||
@ -306,7 +306,8 @@ class DatabaseTests(test.TestCase):
|
||||
replica_count=None,
|
||||
volume_type=None,
|
||||
locality=None,
|
||||
availability_zone=test.IsA(str))
|
||||
availability_zone=test.IsA(str),
|
||||
access=None)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_mocks({
|
||||
@ -359,7 +360,7 @@ class DatabaseTests(test.TestCase):
|
||||
|
||||
res = self.client.post(LAUNCH_URL, post)
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_check, 4, mock.call((), test.IsHttpRequest()))
|
||||
self.mock_check, 5, mock.call((), test.IsHttpRequest()))
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_datastore_flavors, 20,
|
||||
mock.call(test.IsHttpRequest(),
|
||||
@ -396,7 +397,8 @@ class DatabaseTests(test.TestCase):
|
||||
replica_count=None,
|
||||
volume_type=None,
|
||||
locality=None,
|
||||
availability_zone=test.IsA(str))
|
||||
availability_zone=test.IsA(str),
|
||||
access=None)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_mocks({
|
||||
@ -1093,7 +1095,7 @@ class DatabaseTests(test.TestCase):
|
||||
|
||||
res = self.client.post(LAUNCH_URL, post)
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_check, 4, mock.call((), test.IsHttpRequest()))
|
||||
self.mock_check, 5, mock.call((), test.IsHttpRequest()))
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
self.mock_datastore_flavors, 20,
|
||||
mock.call(test.IsHttpRequest(),
|
||||
@ -1133,7 +1135,8 @@ class DatabaseTests(test.TestCase):
|
||||
replica_count=2,
|
||||
volume_type=None,
|
||||
locality=None,
|
||||
availability_zone=test.IsA(str))
|
||||
availability_zone=test.IsA(str),
|
||||
access=None)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_mocks({
|
||||
|
@ -15,6 +15,7 @@
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import netaddr
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
@ -283,6 +284,44 @@ class SetInstanceDetails(workflows.Step):
|
||||
"locality", "availability_zone")
|
||||
|
||||
|
||||
class AddAccessAction(workflows.Action):
|
||||
"""Initialize the database access. This tab will honor
|
||||
the settings which should be a list of permissions required:
|
||||
|
||||
* TROVE_ADD_USER_PERMS = []
|
||||
* TROVE_ADD_DATABASE_PERMS = []
|
||||
"""
|
||||
is_public = forms.BooleanField(label=_("Is Public"),
|
||||
required=False)
|
||||
allowed_cidrs = forms.CharField(label=_("Allowed CIDRs"),
|
||||
required=False,
|
||||
help_text=_("Comma-separated CIDRs "
|
||||
"to connect through."))
|
||||
|
||||
class Meta(object):
|
||||
name = _("Database Access")
|
||||
permissions = TROVE_ADD_PERMS
|
||||
help_text_template = "project/databases/_launch_access_help.html"
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(AddAccessAction, self).clean()
|
||||
if cleaned_data.get('allowed_cidrs'):
|
||||
cidrs = cleaned_data.get('allowed_cidrs').split(',')
|
||||
for cidr in cidrs:
|
||||
try:
|
||||
netaddr.IPNetwork(cidr)
|
||||
except netaddr.AddrFormatError:
|
||||
msg = _('Invalid Allowed CIDR provided.')
|
||||
self._errors["allowed_cidrs"] = self.error_class([msg])
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class DatabaseAccess(workflows.Step):
|
||||
action_class = AddAccessAction
|
||||
contributes = ["is_public", "allowed_cidrs"]
|
||||
|
||||
|
||||
class AddDatabasesAction(workflows.Action):
|
||||
"""Initialize the database with users/databases. This tab will honor
|
||||
the settings which should be a list of permissions required:
|
||||
@ -513,6 +552,7 @@ class LaunchInstance(workflows.Workflow):
|
||||
success_url = "horizon:project:databases:index"
|
||||
default_steps = (SetInstanceDetails,
|
||||
dash_create_instance.SetNetwork,
|
||||
DatabaseAccess,
|
||||
InitializeDatabase,
|
||||
Advanced)
|
||||
|
||||
@ -577,6 +617,16 @@ class LaunchInstance(workflows.Workflow):
|
||||
locality = context['locality']
|
||||
return locality
|
||||
|
||||
def _get_access(self, context):
|
||||
if not context['allowed_cidrs'] and not context['is_public']:
|
||||
return None
|
||||
access = {}
|
||||
if context['allowed_cidrs'] != '':
|
||||
access['allowed_cidrs'].split(',')
|
||||
if context['is_public']:
|
||||
access['is_public'] = True
|
||||
return access
|
||||
|
||||
def handle(self, request, context):
|
||||
try:
|
||||
datastore, datastore_version = parse_datastore_and_version_text(
|
||||
@ -597,6 +647,7 @@ class LaunchInstance(workflows.Workflow):
|
||||
context.get('master'), context['replica_count'],
|
||||
context.get('config'), self._get_locality(context),
|
||||
avail_zone)
|
||||
|
||||
api.trove.instance_create(request,
|
||||
context['name'],
|
||||
context['volume'],
|
||||
@ -613,7 +664,8 @@ class LaunchInstance(workflows.Workflow):
|
||||
context),
|
||||
configuration=context.get('config'),
|
||||
locality=self._get_locality(context),
|
||||
availability_zone=avail_zone)
|
||||
availability_zone=avail_zone,
|
||||
access=self._get_access(context))
|
||||
return True
|
||||
except Exception:
|
||||
exceptions.handle(request)
|
||||
|
Loading…
Reference in New Issue
Block a user