From 1bbc4908ff7a2be19483811b3b6fee6ebc916235 Mon Sep 17 00:00:00 2001
From: Daniel Watkins <oddbloke@ubuntu.com>
Date: Tue, 31 Mar 2020 17:04:17 -0400
Subject: [PATCH] distros: drop leading/trailing hyphens from mirror URL labels
 (#296)

* distros/tests/test_init: drop needless brackets/indentation

* distros: drop leading/trailing hyphens from mirror URL labels
---
 cloudinit/distros/__init__.py        |  5 +++++
 cloudinit/distros/tests/test_init.py | 14 ++++++++------
 2 files changed, 13 insertions(+), 6 deletions(-)

--- a/cloudinit/distros/__init__.py
+++ b/cloudinit/distros/__init__.py
@@ -816,6 +816,11 @@ def _sanitize_mirror_url(url: str):
         lambda hostname: ''.join(
             c if c in acceptable_chars else "-" for c in hostname
         ),
+
+        # Drop leading/trailing hyphens from each part of the hostname
+        lambda hostname: '.'.join(
+            part.strip('-') for part in hostname.split('.')
+        ),
     ]
 
     return _apply_hostname_transformations_to_url(url, transformations)
--- a/cloudinit/distros/tests/test_init.py
+++ b/cloudinit/distros/tests/test_init.py
@@ -109,15 +109,17 @@ class TestGetPackageMirrorInfo:
          ['http://%(region)s.in.hostname/should/be/filtered',
           'http://but.not.in.the.path/%(region)s'],
          ['http://but.not.in.the.path/inv[lid']),
-    ) + (
+        (None, '-some-region-',
+         ['http://-lead-ing.%(region)s.trail-ing-.example.com/ubuntu'],
+         ['http://lead-ing.some-region.trail-ing.example.com/ubuntu']),
+    ) + tuple(
         # Dynamically generate a test case for each non-LDH
         # (Letters/Digits/Hyphen) ASCII character, testing that it is
         # substituted with a hyphen
-        tuple(
-            (None, 'fk{0}fake{0}1'.format(invalid_char),
-             ['http://%(region)s/ubuntu'], ['http://fk-fake-1/ubuntu'])
-            for invalid_char in INVALID_URL_CHARS))
-    )
+        (None, 'fk{0}fake{0}1'.format(invalid_char),
+         ['http://%(region)s/ubuntu'], ['http://fk-fake-1/ubuntu'])
+        for invalid_char in INVALID_URL_CHARS
+    ))
     def test_substitution(self, availability_zone, region, patterns, expected):
         """Test substitution works as expected."""
         m_data_source = mock.Mock(
