From 36c00afb1ad34185c795227816ceb9eaa252645d Mon Sep 17 00:00:00 2001 From: Nora Shapiro Date: Fri, 16 Aug 2024 16:49:13 -0700 Subject: [PATCH] add license logging back to startup (#331) --- shared/license/__init__.py | 30 +++++++++++++++++ tests/unit/test_license.py | 68 ++++++++++++++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/shared/license/__init__.py b/shared/license/__init__.py index 3076a80d..5624a1c1 100644 --- a/shared/license/__init__.py +++ b/shared/license/__init__.py @@ -71,3 +71,33 @@ def parse_license(raw_license): is_trial=license_dict.get("trial"), is_pr_billing=is_pr_billing, ) + + +def startup_license_logging(): + """ + Makes troubleshooting license issues easier - called by startup process in worker and api + """ + if get_config("setup", "enterprise_license"): + statements_to_print = [ + "", # padding + "==> Checking License", + ] + + current_license = get_current_license() + is_valid = current_license.is_valid + statements_to_print.append( + f" License is {"valid" if is_valid else "INVALID"}" + ) + + if current_license.message: + statements_to_print.append(f" Warning: {current_license.message}") + + exp_date = current_license.expires + statements_to_print.append( + f" License expires {datetime.strftime(exp_date, "%Y-%m-%d %H:%M:%S") if exp_date else "NOT FOUND"} <==" + ) + statements_to_print.append("") # padding + + # printing the message in a single statement so the lines won't get split up + # among all the other messages during startup + print(*statements_to_print, sep="\n") diff --git a/tests/unit/test_license.py b/tests/unit/test_license.py index 37bc4d6b..02f48dc3 100644 --- a/tests/unit/test_license.py +++ b/tests/unit/test_license.py @@ -1,13 +1,26 @@ import json from base64 import b64encode from datetime import datetime +from unittest.mock import patch from shared.encryption.standard import EncryptorWithAlreadyGeneratedKey -from shared.license import LicenseInformation, get_current_license, parse_license +from shared.license import ( + LICENSE_ERRORS_MESSAGES, + LicenseInformation, + get_current_license, + parse_license, + startup_license_logging, +) +from tests.base import BaseTestCase + +valid_trial_license_encrypted = "8rz8TfoZ1HDR5P2kpXSOaSvihqbHnJ4DANvDTB/J94tMjovTUUmuIX07W9FwB0UiiAp4j9McdH4JH5cloihjKqwluwC03t22/UA+4SHwxHbi6IhBbYXCEggYcrwtyjcdA4y3yARixGEsNEwDqAzxXLOe95nMetpb1u1Jr8E6CWp/2QSqvIUww8qTkegESk+3CiH3bPrA71pW8w9KYDX65g==" +invalid_license_encrypted = ( + "8rz8TfodsdsSOaSvih09nvnasu4DANvdsdsauIX07W9FwB0UiiAp4j9McdH4JH5cloihjKqadsada" +) def test_sample_license_checking(): - encrypted_license = "8rz8TfoZ1HDR5P2kpXSOaSvihqbHnJ4DANvDTB/J94tMjovTUUmuIX07W9FwB0UiiAp4j9McdH4JH5cloihjKqwluwC03t22/UA+4SHwxHbi6IhBbYXCEggYcrwtyjcdA4y3yARixGEsNEwDqAzxXLOe95nMetpb1u1Jr8E6CWp/2QSqvIUww8qTkegESk+3CiH3bPrA71pW8w9KYDX65g==" + encrypted_license = valid_trial_license_encrypted expected_result = LicenseInformation( is_valid=True, is_trial=True, @@ -56,9 +69,7 @@ def test_sample_license_checking_with_users_and_repos(): def test_invalid_license_checking_nonvalid_64encoded(): - encrypted_license = ( - "8rz8TfodsdsSOaSvih09nvnasu4DANvdsdsauIX07W9FwB0UiiAp4j9McdH4JH5cloihjKqadsada" - ) + encrypted_license = invalid_license_encrypted expected_result = LicenseInformation( is_valid=False, is_trial=False, @@ -111,7 +122,7 @@ def test_invalid_license_checking_wrong_key(): def test_get_current_license(mock_configuration): - encrypted_license = "8rz8TfoZ1HDR5P2kpXSOaSvihqbHnJ4DANvDTB/J94tMjovTUUmuIX07W9FwB0UiiAp4j9McdH4JH5cloihjKqwluwC03t22/UA+4SHwxHbi6IhBbYXCEggYcrwtyjcdA4y3yARixGEsNEwDqAzxXLOe95nMetpb1u1Jr8E6CWp/2QSqvIUww8qTkegESk+3CiH3bPrA71pW8w9KYDX65g==" + encrypted_license = valid_trial_license_encrypted mock_configuration.set_params({"setup": {"enterprise_license": encrypted_license}}) expected_result = LicenseInformation( is_valid=True, @@ -137,3 +148,48 @@ def test_get_current_license_no_license(mock_configuration): expires=None, ) assert get_current_license() == expected_result + + +@patch("builtins.print") +class TestUserGivenSecret(BaseTestCase): + def test_startup_license_logging_valid(self, mock_print, mock_configuration): + encrypted_license = valid_trial_license_encrypted + mock_configuration.set_params( + {"setup": {"enterprise_license": encrypted_license}} + ) + + expected_log = [ + "", + "==> Checking License", + " License is valid", + " License expires 2020-05-09 00:00:00 <==", + "", + ] + + startup_license_logging() + mock_print.assert_called_once_with(*expected_log, sep="\n") + + @patch("shared.license.parse_license") + def test_startup_license_logging_invalid( + self, mock_license_parsing, mock_print, mock_configuration + ): + mock_license_parsing.return_value = LicenseInformation( + is_valid=False, + message=LICENSE_ERRORS_MESSAGES["no-license"], + ) + + mock_configuration.set_params( + {"setup": {"enterprise_license": True}} + ) # value doesn't matter since parse_license is mocked + + expected_log = [ + "", + "==> Checking License", + " License is INVALID", + f" Warning: {LICENSE_ERRORS_MESSAGES["no-license"]}", + " License expires NOT FOUND <==", + "", + ] + + startup_license_logging() + mock_print.assert_called_once_with(*expected_log, sep="\n")