mirror of
https://github.com/certbot/certbot.git
synced 2026-06-03 13:59:02 -04:00
Merge pull request #3084 from certbot/sysd_os
Fix merge conflicts in #2818 (Sysd os)
This commit is contained in:
commit
6a97f9edd1
7 changed files with 166 additions and 28 deletions
|
|
@ -78,6 +78,8 @@ CLI_DEFAULTS = {
|
|||
"centos linux": CLI_DEFAULTS_CENTOS,
|
||||
"fedora": CLI_DEFAULTS_CENTOS,
|
||||
"red hat enterprise linux server": CLI_DEFAULTS_CENTOS,
|
||||
"rhel": CLI_DEFAULTS_CENTOS,
|
||||
"amazon": CLI_DEFAULTS_CENTOS,
|
||||
"gentoo base system": CLI_DEFAULTS_GENTOO,
|
||||
"darwin": CLI_DEFAULTS_DARWIN,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ def _determine_user_agent(config):
|
|||
|
||||
if config.user_agent is None:
|
||||
ua = "CertbotACMEClient/{0} ({1}) Authenticator/{2} Installer/{3}"
|
||||
ua = ua.format(certbot.__version__, " ".join(util.get_os_info()),
|
||||
ua = ua.format(certbot.__version__, util.get_os_info_ua(),
|
||||
config.authenticator, config.installer)
|
||||
else:
|
||||
ua = config.user_agent
|
||||
|
|
|
|||
|
|
@ -171,13 +171,13 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods
|
|||
|
||||
with mock.patch('certbot.main.client.acme_client.ClientNetwork') as acme_net:
|
||||
self._call_no_clientmock(args)
|
||||
os_ver = " ".join(util.get_os_info())
|
||||
os_ver = util.get_os_info_ua()
|
||||
ua = acme_net.call_args[1]["user_agent"]
|
||||
self.assertTrue(os_ver in ua)
|
||||
import platform
|
||||
plat = platform.platform()
|
||||
if "linux" in plat.lower():
|
||||
self.assertTrue(platform.linux_distribution()[0] in ua)
|
||||
self.assertTrue(util.get_os_info_ua() in ua)
|
||||
|
||||
with mock.patch('certbot.main.client.acme_client.ClientNetwork') as acme_net:
|
||||
ua = "bandersnatch"
|
||||
|
|
|
|||
7
certbot/tests/testdata/os-release
vendored
Normal file
7
certbot/tests/testdata/os-release
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
NAME="SystemdOS"
|
||||
VERSION="42.42.42 LTS, Unreal"
|
||||
ID=systemdos
|
||||
ID_LIKE=debian
|
||||
VERSION_ID="42"
|
||||
HOME_URL="http://www.example.com/"
|
||||
SUPPORT_URL="http://help.example.com/"
|
||||
|
|
@ -10,8 +10,8 @@ import unittest
|
|||
import mock
|
||||
import six
|
||||
|
||||
import certbot
|
||||
from certbot import errors
|
||||
from certbot.tests import test_util
|
||||
|
||||
|
||||
class RunScriptTest(unittest.TestCase):
|
||||
|
|
@ -340,31 +340,66 @@ class EnforceDomainSanityTest(unittest.TestCase):
|
|||
u"eichh\u00f6rnchen.example.com")
|
||||
|
||||
|
||||
class GetStrictVersionTest(unittest.TestCase):
|
||||
"""Tests for certbot.util.get_strict_version."""
|
||||
class OsInfoTest(unittest.TestCase):
|
||||
"""Test OS / distribution detection"""
|
||||
|
||||
@classmethod
|
||||
def _call(cls, *args, **kwargs):
|
||||
from certbot.util import get_strict_version
|
||||
return get_strict_version(*args, **kwargs)
|
||||
def test_systemd_os_release(self):
|
||||
from certbot.util import (get_os_info, get_systemd_os_info,
|
||||
get_os_info_ua)
|
||||
|
||||
def test_two_dev_versions(self):
|
||||
self.assertTrue(
|
||||
self._call("0.0.0.dev20151006") < self._call("0.0.0.dev20151008"))
|
||||
with mock.patch('os.path.isfile', return_value=True):
|
||||
self.assertEqual(get_os_info(
|
||||
test_util.vector_path("os-release"))[0], 'systemdos')
|
||||
self.assertEqual(get_os_info(
|
||||
test_util.vector_path("os-release"))[1], '42')
|
||||
self.assertEqual(get_systemd_os_info("/dev/null"), ("", ""))
|
||||
self.assertEqual(get_os_info_ua(
|
||||
test_util.vector_path("os-release")),
|
||||
"SystemdOS")
|
||||
with mock.patch('os.path.isfile', return_value=False):
|
||||
self.assertEqual(get_systemd_os_info(), ("", ""))
|
||||
|
||||
def test_one_dev_one_release_version(self):
|
||||
self.assertTrue(self._call("1.0.0.dev0") < self._call("1.0.0"))
|
||||
self.assertTrue(self._call("1.0.0") < self._call("1.0.1.dev0"))
|
||||
@mock.patch("certbot.util.subprocess.Popen")
|
||||
def test_non_systemd_os_info(self, popen_mock):
|
||||
from certbot.util import (get_os_info, get_python_os_info,
|
||||
get_os_info_ua)
|
||||
with mock.patch('os.path.isfile', return_value=False):
|
||||
with mock.patch('platform.system_alias',
|
||||
return_value=('NonSystemD', '42', '42')):
|
||||
self.assertEqual(get_os_info()[0], 'nonsystemd')
|
||||
self.assertEqual(get_os_info_ua(),
|
||||
" ".join(get_python_os_info()))
|
||||
|
||||
def test_two_release_versions(self):
|
||||
self.assertTrue(self._call("0.0.0") < self._call("0.0.1"))
|
||||
self.assertTrue(self._call("0.0.0") < self._call("0.1.0"))
|
||||
self.assertTrue(self._call("0.0.0") < self._call("1.0.0"))
|
||||
with mock.patch('platform.system_alias',
|
||||
return_value=('darwin', '', '')):
|
||||
comm_mock = mock.Mock()
|
||||
comm_attrs = {'communicate.return_value':
|
||||
('42.42.42', 'error')}
|
||||
comm_mock.configure_mock(**comm_attrs) # pylint: disable=star-args
|
||||
popen_mock.return_value = comm_mock
|
||||
self.assertEqual(get_os_info()[0], 'darwin')
|
||||
self.assertEqual(get_os_info()[1], '42.42.42')
|
||||
|
||||
def test_current_version(self):
|
||||
current_version = self._call(certbot.__version__)
|
||||
self.assertTrue(self._call("0.6.0") < current_version)
|
||||
self.assertTrue(current_version < self._call("99.99.99"))
|
||||
with mock.patch('platform.system_alias',
|
||||
return_value=('linux', '', '')):
|
||||
with mock.patch('platform.linux_distribution',
|
||||
return_value=('', '', '')):
|
||||
self.assertEqual(get_python_os_info(), ("linux", ""))
|
||||
|
||||
with mock.patch('platform.linux_distribution',
|
||||
return_value=('testdist', '42', '')):
|
||||
self.assertEqual(get_python_os_info(), ("testdist", "42"))
|
||||
|
||||
with mock.patch('platform.system_alias',
|
||||
return_value=('freebsd', '9.3-RC3-p1', '')):
|
||||
self.assertEqual(get_python_os_info(), ("freebsd", "9"))
|
||||
|
||||
with mock.patch('platform.system_alias',
|
||||
return_value=('windows', '', '')):
|
||||
with mock.patch('platform.win32_ver',
|
||||
return_value=('4242', '95', '2', '')):
|
||||
self.assertEqual(get_python_os_info(),
|
||||
("windows", "95"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -213,9 +213,95 @@ def safely_remove(path):
|
|||
raise
|
||||
|
||||
|
||||
def get_os_info():
|
||||
def get_os_info(filepath="/etc/os-release"):
|
||||
"""
|
||||
Get OS name and version
|
||||
|
||||
:param str filepath: File path of os-release file
|
||||
:returns: (os_name, os_version)
|
||||
:rtype: `tuple` of `str`
|
||||
"""
|
||||
|
||||
if os.path.isfile(filepath):
|
||||
# Systemd os-release parsing might be viable
|
||||
os_name, os_version = get_systemd_os_info(filepath=filepath)
|
||||
if os_name:
|
||||
return (os_name, os_version)
|
||||
|
||||
# Fallback to platform module
|
||||
return get_python_os_info()
|
||||
|
||||
|
||||
def get_os_info_ua(filepath="/etc/os-release"):
|
||||
"""
|
||||
Get OS name and version string for User Agent
|
||||
|
||||
:param str filepath: File path of os-release file
|
||||
:returns: os_ua
|
||||
:rtype: `str`
|
||||
"""
|
||||
|
||||
if os.path.isfile(filepath):
|
||||
os_ua = _get_systemd_os_release_var("PRETTY_NAME", filepath=filepath)
|
||||
if not os_ua:
|
||||
os_ua = _get_systemd_os_release_var("NAME", filepath=filepath)
|
||||
if os_ua:
|
||||
return os_ua
|
||||
|
||||
# Fallback
|
||||
return " ".join(get_python_os_info())
|
||||
|
||||
|
||||
def get_systemd_os_info(filepath="/etc/os-release"):
|
||||
"""
|
||||
Parse systemd /etc/os-release for distribution information
|
||||
|
||||
:param str filepath: File path of os-release file
|
||||
:returns: (os_name, os_version)
|
||||
:rtype: `tuple` of `str`
|
||||
"""
|
||||
|
||||
os_name = _get_systemd_os_release_var("ID", filepath=filepath)
|
||||
os_version = _get_systemd_os_release_var("VERSION_ID", filepath=filepath)
|
||||
|
||||
return (os_name, os_version)
|
||||
|
||||
|
||||
def _get_systemd_os_release_var(varname, filepath="/etc/os-release"):
|
||||
"""
|
||||
Get single value from systemd /etc/os-release
|
||||
|
||||
:param str varname: Name of variable to fetch
|
||||
:param str filepath: File path of os-release file
|
||||
:returns: requested value
|
||||
:rtype: `str`
|
||||
"""
|
||||
|
||||
var_string = varname+"="
|
||||
if not os.path.isfile(filepath):
|
||||
return ""
|
||||
with open(filepath, 'r') as fh:
|
||||
contents = fh.readlines()
|
||||
|
||||
for line in contents:
|
||||
if line.strip().startswith(var_string):
|
||||
# Return the value of var, normalized
|
||||
return _normalize_string(line.strip()[len(var_string):])
|
||||
return ""
|
||||
|
||||
|
||||
def _normalize_string(orig):
|
||||
"""
|
||||
Helper function for _get_systemd_os_release_var() to remove quotes
|
||||
and whitespaces
|
||||
"""
|
||||
return orig.replace('"', '').replace("'", "").strip()
|
||||
|
||||
|
||||
def get_python_os_info():
|
||||
"""
|
||||
Get Operating System type/distribution and major version
|
||||
using python platform module
|
||||
|
||||
:returns: (os_name, os_version)
|
||||
:rtype: `tuple` of `str`
|
||||
|
|
@ -240,7 +326,6 @@ def get_os_info():
|
|||
["sw_vers", "-productVersion"],
|
||||
stdout=subprocess.PIPE
|
||||
).communicate()[0]
|
||||
os_ver = os_ver.partition(".")[0]
|
||||
elif os_type.startswith('freebsd'):
|
||||
# eg "9.3-RC3-p1"
|
||||
os_ver = os_ver.partition("-")[0]
|
||||
|
|
@ -317,7 +402,7 @@ def enforce_domain_sanity(domain):
|
|||
domain = domain.encode('ascii').lower()
|
||||
except UnicodeError:
|
||||
error_fmt = (u"Internationalized domain names "
|
||||
"are not presently supported: {0}")
|
||||
"are not presently supported: {0}")
|
||||
if isinstance(domain, six.text_type):
|
||||
raise errors.ConfigurationError(error_fmt.format(domain))
|
||||
else:
|
||||
|
|
@ -344,7 +429,8 @@ def enforce_domain_sanity(domain):
|
|||
# first and last char is not "-"
|
||||
fqdn = re.compile("^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,63}$")
|
||||
if not fqdn.match(domain):
|
||||
raise errors.ConfigurationError("Requested domain {0} is not a FQDN".format(domain))
|
||||
raise errors.ConfigurationError("Requested domain {0} is not a FQDN"
|
||||
.format(domain))
|
||||
return domain
|
||||
|
||||
|
||||
|
|
|
|||
8
letsencrypt/tests/testdata/os-release
vendored
Normal file
8
letsencrypt/tests/testdata/os-release
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
NAME="SystemdOS"
|
||||
VERSION="42.42.42 LTS, Unreal"
|
||||
ID=systemdos
|
||||
ID_LIKE=debian
|
||||
PRETTY_NAME="SystemdOS 42.42.42 Unreal"
|
||||
VERSION_ID="42"
|
||||
HOME_URL="http://www.example.com/"
|
||||
SUPPORT_URL="http://help.example.com/"
|
||||
Loading…
Reference in a new issue