Improve validation on baymodel api calls

- Don't allow empty strings and validate strings are not longer than 255
  chars were appropriate.
- Min/Max value for api port
- Docker volume size min size of 1
- DNS server address must be an IPv4

Change-Id: I2c26b758b908f03e60293c68dedf43eb90c3cad2
Partial-Bug: 1412181
This commit is contained in:
Tom Cammann 2015-05-05 14:45:30 +01:00
parent 1c3027fc52
commit ccb410f223
2 changed files with 54 additions and 30 deletions

View File

@ -62,37 +62,37 @@ class BayModel(base.APIBase):
coe = wsme.wsproperty(wtypes.text, _get_coe, _set_coe, mandatory=True)
"""The Container Orchestration Engine for this bay model"""
image_id = wtypes.text
image_id = wtypes.StringType(min_length=1, max_length=255)
"""The image name or UUID to use as a base image for this baymodel"""
flavor_id = wtypes.text
flavor_id = wtypes.StringType(min_length=1, max_length=255)
"""The flavor of this bay model"""
master_flavor_id = wtypes.text
master_flavor_id = wtypes.StringType(min_length=1, max_length=255)
"""The flavor of the master node for this bay model"""
dns_nameserver = wtypes.text
dns_nameserver = wtypes.IPv4AddressType()
"""The DNS nameserver address"""
keypair_id = wtypes.text
keypair_id = wtypes.StringType(min_length=1, max_length=255)
"""The name or id of the nova ssh keypair"""
external_network_id = wtypes.text
external_network_id = wtypes.StringType(min_length=1, max_length=255)
"""The external network to attach the Bay"""
fixed_network = wtypes.text
fixed_network = wtypes.StringType(min_length=1, max_length=255)
"""The fixed network name to attach the Bay"""
apiserver_port = wtypes.IntegerType()
apiserver_port = wtypes.IntegerType(minimum=1024, maximum=65535)
"""The API server port for k8s"""
docker_volume_size = wtypes.IntegerType()
docker_volume_size = wtypes.IntegerType(minimum=1)
"""The size in GB of the docker volume"""
ssh_authorized_key = wtypes.text
ssh_authorized_key = wtypes.StringType(min_length=1)
"""The SSH Authorized Key"""
cluster_distro = wtypes.text
cluster_distro = wtypes.StringType(min_length=1, max_length=255)
"""The Cluster distro for the bay, ex - coreos, fedora-atomic."""
links = wsme.wsattr([link.Link], readonly=True)

View File

@ -12,6 +12,7 @@
import datetime
import contextlib
import mock
from oslo_config import cfg
from oslo_utils import timeutils
@ -370,31 +371,54 @@ class TestPost(api_base.FunctionalTest):
# Check that 'id' is not in first arg of positional args
self.assertNotIn('id', cc_mock.call_args[0][0])
def test_create_baymodel_with_invalid_empty_str_name(self):
with mock.patch.object(self.dbapi, 'create_baymodel',
wraps=self.dbapi.create_baymodel) as cc_mock:
cdict = apiutils.baymodel_post_data(name='')
self.assertRaises(AppError, self.post_json, '/baymodels', cdict)
self.assertFalse(cc_mock.called)
def _create_baymodel_raises_app_error(self, **kwargs):
# Create mock for db and image data
with contextlib.nested(
mock.patch.object(self.dbapi, 'create_baymodel',
wraps=self.dbapi.create_baymodel),
mock.patch.object(api_baymodel.BayModelsController,
'_get_image_data')) as (cc_mock,
mock_image_data):
def test_create_baymodel_with_invalid_long_name(self):
with mock.patch.object(self.dbapi, 'create_baymodel',
wraps=self.dbapi.create_baymodel) as cc_mock:
cdict = apiutils.baymodel_post_data(name='i' * 256)
self.assertRaises(AppError, self.post_json, '/baymodels', cdict)
self.assertFalse(cc_mock.called)
@mock.patch.object(api_baymodel.BayModelsController, '_get_image_data')
def test_create_baymodel_with_invalid_docker_volume_size(self,
mock_image_data):
with mock.patch.object(self.dbapi, 'create_baymodel',
wraps=self.dbapi.create_baymodel) as cc_mock:
mock_image_data.return_value = {'name': 'mock_name',
'os_distro': 'fedora-atomic'}
cdict = apiutils.baymodel_post_data(docker_volume_size='docker')
cdict = apiutils.baymodel_post_data(**kwargs)
self.assertRaises(AppError, self.post_json, '/baymodels', cdict)
self.assertFalse(cc_mock.called)
def test_create_baymodel_with_invalid_long_string(self):
fields = ["uuid", "name", "image_id", "flavor_id", "master_flavor_id",
"dns_nameserver", "keypair_id", "external_network_id",
"cluster_distro", "fixed_network", "apiserver_port",
"docker_volume_size"]
for field in fields:
self._create_baymodel_raises_app_error(**{field: 'i' * 256})
def test_create_baymodel_with_invalid_empty_string(self):
fields = ["uuid", "name", "image_id", "flavor_id", "master_flavor_id",
"dns_nameserver", "keypair_id", "external_network_id",
"cluster_distro", "fixed_network", "apiserver_port",
"docker_volume_size", "ssh_authorized_key"]
for field in fields:
self._create_baymodel_raises_app_error(**{field: ''})
def test_create_baymodel_with_invalid_docker_volume_size(self):
self._create_baymodel_raises_app_error(docker_volume_size=0)
self._create_baymodel_raises_app_error(docker_volume_size=-1)
self._create_baymodel_raises_app_error(docker_volume_size='notanint')
def test_create_baymodel_with_invalid_dns_nameserver(self):
self._create_baymodel_raises_app_error(dns_nameserver='1.1.2')
self._create_baymodel_raises_app_error(dns_nameserver='1.1..1')
self._create_baymodel_raises_app_error(dns_nameserver='openstack.org')
def test_create_baymodel_with_invalid_apiserver_port(self):
self._create_baymodel_raises_app_error(apiserver_port=-12)
self._create_baymodel_raises_app_error(apiserver_port=65536)
self._create_baymodel_raises_app_error(apiserver_port=0)
self._create_baymodel_raises_app_error(apiserver_port=1023)
self._create_baymodel_raises_app_error(apiserver_port='not an int')
@mock.patch.object(api_baymodel.BayModelsController, '_get_image_data')
def test_create_baymodel_with_docker_volume_size(self,
mock_image_data):