diff --git a/calico/felix/devices.py b/calico/felix/devices.py index 736c481f28e..761ca4aa207 100644 --- a/calico/felix/devices.py +++ b/calico/felix/devices.py @@ -91,7 +91,12 @@ def interface_exists(interface): futils.check_call(["ip", "link", "list", interface]) return True except futils.FailedSystemCall as fsc: - if fsc.stderr.count("does not exist") != 0: + # If the interface doesn't exist, the error message varies by + # flavor of Linux: + # * Ubuntu/RHEL: "Device 'XYZ' does not exist" + # * Alpine: "ip: can't find device 'XYZ'" + if ("does not exist" in fsc.stderr) or \ + ("can't find device" in fsc.stderr): return False else: # An error other than does not exist; just pass on up diff --git a/calico/felix/test/test_devices.py b/calico/felix/test/test_devices.py index d2147a8198c..61650a46b9a 100644 --- a/calico/felix/test/test_devices.py +++ b/calico/felix/test/test_devices.py @@ -79,12 +79,20 @@ def test_interface_exists(self): args = [] retcode = 1 stdout = "" - stderr = "Device \"%s\" does not exist." % tap - err = futils.FailedSystemCall("From test", args, retcode, stdout, stderr) - with mock.patch('calico.felix.futils.check_call', side_effect=err): - self.assertFalse(devices.interface_exists(tap)) - futils.check_call.assert_called_with(["ip", "link", "list", tap]) + # Check we correctly handle error messages for a missing interface, + # and do so for all supported flavors of Linux. + error_messages = [ + "Device \"%s\" does not exist." % tap, # Ubuntu/RHEL + "ip: can't find device '%s'" % tap, # Alpine + ] + + for stderr in error_messages: + err = futils.FailedSystemCall("From test", args, retcode, stdout, stderr) + + with mock.patch('calico.felix.futils.check_call', side_effect=err): + self.assertFalse(devices.interface_exists(tap)) + futils.check_call.assert_called_with(["ip", "link", "list", tap]) with mock.patch('calico.felix.futils.check_call'): self.assertTrue(devices.interface_exists(tap))