From 24e471eb1701fba5e2ca609a877b6a401ef03f6c Mon Sep 17 00:00:00 2001 From: Benjamin Bertrand <benjamin.bertrand@esss.se> Date: Wed, 23 Oct 2019 18:52:54 +0200 Subject: [PATCH] Increase interface name max length The interface name shall start by the host name. Its length must thus be longer than the host. JIRA INFRA-1324 #action In Progress --- app/models.py | 5 +++-- app/network/forms.py | 5 +++-- app/validators.py | 1 + tests/functional/test_models.py | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/app/models.py b/app/models.py index 0c32a0b..8408cc6 100644 --- a/app/models.py +++ b/app/models.py @@ -31,6 +31,7 @@ from .plugins import FlaskUserPlugin from .validators import ( ICS_ID_RE, HOST_NAME_RE, + INTERFACE_NAME_RE, VLAN_NAME_RE, MAC_ADDRESS_RE, DEVICE_TYPE_RE, @@ -1415,8 +1416,8 @@ class Interface(CreatedMixin, db.Model): return None # Force the string to lowercase lower_string = string.lower() - if HOST_NAME_RE.fullmatch(lower_string) is None: - raise ValidationError(r"Interface name shall match [a-z0-9\-]{2,20}") + if INTERFACE_NAME_RE.fullmatch(lower_string) is None: + raise ValidationError(r"Interface name shall match [a-z0-9\-]{2,25}") if self.host and not lower_string.startswith(self.host.name): raise ValidationError( f"Interface name shall start with the host name '{self.host}'" diff --git a/app/network/forms.py b/app/network/forms.py index 5d0f9c5..30743fe 100644 --- a/app/network/forms.py +++ b/app/network/forms.py @@ -28,6 +28,7 @@ from ..validators import ( RegexpList, IPNetwork, HOST_NAME_RE, + INTERFACE_NAME_RE, VLAN_NAME_RE, MAC_ADDRESS_RE, NoValidateSelectField, @@ -183,10 +184,10 @@ class InterfaceForm(CSEntryForm): ) interface_name = StringField( "Interface name", - description="name must be 2-20 characters long and contain only letters, numbers and dash", + description="name must be 2-25 characters long and contain only letters, numbers and dash", validators=[ validators.InputRequired(), - validators.Regexp(HOST_NAME_RE), + validators.Regexp(INTERFACE_NAME_RE), Unique(models.Interface), starts_with_hostname, UniqueAccrossModels([models.Cname]), diff --git a/app/validators.py b/app/validators.py index 8684941..642da1d 100644 --- a/app/validators.py +++ b/app/validators.py @@ -16,6 +16,7 @@ from wtforms import ValidationError, SelectField ICS_ID_RE = re.compile(r"[A-Z]{3}[0-9]{3}") HOST_NAME_RE = re.compile(r"^[a-z0-9\-]{2,20}$") +INTERFACE_NAME_RE = re.compile(r"^[a-z0-9\-]{2,25}$") VLAN_NAME_RE = re.compile(r"^[A-Za-z0-9\-]{3,25}$") MAC_ADDRESS_RE = re.compile(r"^(?:[0-9a-fA-F]{2}[:-]?){5}[0-9a-fA-F]{2}$") DEVICE_TYPE_RE = re.compile(r"^[A-Za-z0-9]{3,25}$") diff --git a/tests/functional/test_models.py b/tests/functional/test_models.py index 73d445b..c501486 100644 --- a/tests/functional/test_models.py +++ b/tests/functional/test_models.py @@ -767,3 +767,35 @@ def test_task_awx_job_url(db, task_factory): assert task4.awx_job_url is None task5 = task_factory(awx_resource="inventory_source", awx_job_id=12) assert task5.awx_job_url == "https://awx.example.org/#/jobs/inventory/12" + + +@pytest.mark.parametrize("length", (1, 21, 50)) +def test_hostname_invalid_length(db, host_factory, length): + with pytest.raises(ValidationError) as excinfo: + host_factory(name="x" * length) + assert r"Host name shall match [a-z0-9\-]{2,20}" in str(excinfo.value) + + +@pytest.mark.parametrize("name", ("my_host", "host@", "foo:bar", "U02.K02")) +def test_hostname_invalid_characters(db, host_factory, name): + with pytest.raises(ValidationError) as excinfo: + host_factory(name=name) + assert r"Host name shall match [a-z0-9\-]{2,20}" in str(excinfo.value) + + +@pytest.mark.parametrize("length", (1, 26, 50)) +def test_interface_name_invalid_length(db, interface_factory, length): + with pytest.raises(ValidationError) as excinfo: + interface_factory(name="x" * length) + assert r"Interface name shall match [a-z0-9\-]{2,25}" in str(excinfo.value) + + +def test_interface_name_length(db, host_factory, interface_factory): + hostname = "x" * 20 + interface_name = hostname + "-yyyy" + host1 = host_factory(name=hostname) + interface_factory(name=interface_name, host=host1) + assert host1.interfaces[0].name == interface_name + with pytest.raises(ValidationError) as excinfo: + interface_factory(name=interface_name + "y", host=host1) + assert r"Interface name shall match [a-z0-9\-]{2,25}" in str(excinfo.value) -- GitLab