Node naming validations

- Update the hostname validator account for the FQDN

Change-Id: If59eb5d5d351e2251cf881492b46e109111c91ec
This commit is contained in:
Scott Hussey 2018-08-03 12:20:02 -05:00
parent 89ce941202
commit e044575e05
4 changed files with 59 additions and 30 deletions

View File

@ -203,9 +203,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
self.networks.append(new_network)
def get_network(self, network_key):
for n in self.networks:
if n.get_id() == network_key:
return n
if self.networks:
for n in self.networks:
if n.get_id() == network_key:
return n
raise errors.DesignError(
"Network %s not found in design state" % network_key)
@ -220,9 +221,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
self.network_links.append(new_network_link)
def get_network_link(self, link_key):
for l in self.network_links:
if l.get_id() == link_key:
return l
if self.network_links:
for l in self.network_links:
if l.get_id() == link_key:
return l
raise errors.DesignError(
"NetworkLink %s not found in design state" % link_key)
@ -237,9 +239,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
self.racks.append(new_rack)
def get_rack(self, rack_key):
for r in self.racks:
if r.get_id() == rack_key:
return r
if self.racks:
for r in self.racks:
if r.get_id() == rack_key:
return r
raise errors.DesignError(
"Rack %s not found in design state" % rack_key)
@ -258,9 +261,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
:param ba_key: Value should match the ``get_id()`` value of the BootAction returned
"""
for ba in self.bootactions:
if ba.get_id() == ba_key:
return ba
if self.bootactions:
for ba in self.bootactions:
if ba.get_id() == ba_key:
return ba
raise errors.DesignError(
"BootAction %s not found in design state" % ba_key)
@ -274,9 +278,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
self.host_profiles.append(new_host_profile)
def get_host_profile(self, profile_key):
for p in self.host_profiles:
if p.get_id() == profile_key:
return p
if self.host_profiles:
for p in self.host_profiles:
if p.get_id() == profile_key:
return p
raise errors.DesignError(
"HostProfile %s not found in design state" % profile_key)
@ -291,9 +296,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
self.hardware_profiles.append(new_hardware_profile)
def get_hardware_profile(self, profile_key):
for p in self.hardware_profiles:
if p.get_id() == profile_key:
return p
if self.hardware_profiles:
for p in self.hardware_profiles:
if p.get_id() == profile_key:
return p
raise errors.DesignError(
"HardwareProfile %s not found in design state" % profile_key)
@ -308,9 +314,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
self.baremetal_nodes.append(new_baremetal_node)
def get_baremetal_node(self, node_key):
for n in self.baremetal_nodes:
if n.get_id() == node_key:
return n
if self.baremetal_nodes:
for n in self.baremetal_nodes:
if n.get_id() == node_key:
return n
raise errors.DesignError(
"BaremetalNode %s not found in design state" % node_key)

View File

@ -11,6 +11,8 @@
# 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.
import re
from drydock_provisioner.orchestrator.validations.validators import Validators
@ -19,14 +21,32 @@ class HostnameValidity(Validators):
super().__init__('Hostname Validity', 'DD3003')
def run_validation(self, site_design, orchestrator=None):
"""Validate that node hostnames do not contain '__' """
node_list = site_design.baremetal_nodes or []
# Check FQDN length is <= 255 characters per RFC 1035
invalid_nodes = [n for n in node_list if '__' in n.name]
node_list = site_design.baremetal_nodes or []
invalid_nodes = [
n for n in node_list if len(n.get_fqdn(site_design)) > 255
]
for n in invalid_nodes:
msg = "Hostname %s invalid." % n.name
msg = "FQDN %s is invalid, greater than 255 characters." % n.get_fqdn(
site_design)
self.report_error(
msg, [n.doc_ref],
"Hostnames cannot contain '__' (double underscore)")
return
"RFC 1035 requires full DNS names to be < 256 characters.")
# Check each label in the domain name is <= 63 characters per RFC 1035
# and only contains A-Z,a-z,0-9,-
valid_label = re.compile('[a-z0-9-]{1,63}', flags=re.I)
for n in node_list:
domain_labels = n.get_fqdn(site_design).split('.')
for l in domain_labels:
if not valid_label.fullmatch(l):
msg = "FQDN %s is invalid - label '%s' is invalid." % (
n.get_fqdn(site_design), l)
self.report_error(
msg, [n.doc_ref],
"RFC 1035 requires each label in a DNS name to be <= 63 characters and contain "
"only A-Z, a-z, 0-9, and hyphens.")

View File

@ -54,11 +54,13 @@ class TestHostnameValidity(object):
validator = HostnameValidity()
message_list = validator.execute(site_design, orchestrator=orch)
long_label = "sitenameisverylongsoitshouldbeinvalidperrfcifikeepaddingoctetsafewmore"
for msg in message_list:
msg = msg.to_dict()
LOG.debug(msg)
assert msg.get('error')
assert len(msg.get('documents')) > 0
assert "bad__name" in msg.get('message')
assert "bad__name" in msg.get('message') or long_label in msg.get(
'message')
assert len(message_list) == 1
assert len(message_list) > 1

View File

@ -182,7 +182,7 @@ data:
gateway: 141.16.1.1
metric: 10
dns:
domain: mgmt.sitename.example.com
domain: mgmt.sitenameisverylongsoitshouldbeinvalidperrfcifikeepaddingoctetsafewmore.example.com
servers: 172.16.1.9,172.16.1.10
---
schema: 'drydock/Network/v1'