taler-deployment

Deployment scripts and configuration files
Log | Files | Refs | README

test_inventory_wizard.py (5570B)


      1 import importlib.util
      2 import os
      3 import tempfile
      4 import unittest
      5 from pathlib import Path
      6 from unittest import mock
      7 
      8 
      9 MODULE_PATH = Path(__file__).parents[1] / "inventory-wizard.py"
     10 SPEC = importlib.util.spec_from_file_location("inventory_wizard", MODULE_PATH)
     11 assert SPEC and SPEC.loader
     12 inventory_wizard = importlib.util.module_from_spec(SPEC)
     13 SPEC.loader.exec_module(inventory_wizard)
     14 
     15 
     16 class InventoryWriteTests(unittest.TestCase):
     17     def test_targets_are_independent_and_private(self):
     18         with tempfile.TemporaryDirectory() as temporary_directory:
     19             directory = Path(temporary_directory)
     20             first = inventory_wizard.write_target(
     21                 directory,
     22                 "first",
     23                 {"ansible_host": "first.example", "custom_value": "preserved"},
     24             )
     25             second = inventory_wizard.write_target(
     26                 directory, "second", {"ansible_host": "second.example"}
     27             )
     28 
     29             first_values, first_legacy = inventory_wizard.load_target(
     30                 directory, "first"
     31             )
     32             first_values["ansible_host"] = "new-first.example"
     33             inventory_wizard.write_target(directory, "first", first_values)
     34             first_values, _ = inventory_wizard.load_target(directory, "first")
     35             second_values, second_legacy = inventory_wizard.load_target(
     36                 directory, "second"
     37             )
     38 
     39             self.assertEqual(first_values["ansible_host"], "new-first.example")
     40             self.assertEqual(first_values["custom_value"], "preserved")
     41             self.assertEqual(second_values["ansible_host"], "second.example")
     42             self.assertFalse(first_legacy)
     43             self.assertFalse(second_legacy)
     44             self.assertEqual(first.stat().st_mode & 0o777, 0o600)
     45             self.assertEqual(second.stat().st_mode & 0o777, 0o600)
     46 
     47     def test_failed_replace_preserves_existing_inventory(self):
     48         with tempfile.TemporaryDirectory() as temporary_directory:
     49             directory = Path(temporary_directory)
     50             target = inventory_wizard.write_target(
     51                 directory, "target", {"ansible_host": "old.example"}
     52             )
     53             original = target.read_bytes()
     54 
     55             with mock.patch.object(os, "replace", side_effect=OSError("failed")):
     56                 with self.assertRaises(OSError):
     57                     inventory_wizard.write_target(
     58                         directory, "target", {"ansible_host": "new.example"}
     59                     )
     60 
     61             self.assertEqual(target.read_bytes(), original)
     62             self.assertEqual(list(directory.glob(".target.yml.*")), [])
     63 
     64 
     65 class InventoryPromptTests(unittest.TestCase):
     66     def test_conversion_test_mode_keeps_nexus_services_disabled(self):
     67         answers = {
     68             "SSH host name or address": "conversion.example",
     69             "SSH user": "root",
     70             "Base domain for the service hosts and optional landing page": "conversion.example",
     71             "Human-readable bank name": "Test Bank",
     72             "Fiat bank name": "Synthetic Bank",
     73             "Fiat account legal name": "Synthetic Account",
     74         }
     75         matching_answers = {
     76             "Inventory host name to add or update": "conversion-test",
     77             "Regional currency code": "FLODOS",
     78             "Fiat currency code": "CHF",
     79             "Fiat account IBAN": "CH8615624QG38ANY0UVER",
     80             "Fiat account BIC": "TSTRCHZZXXX",
     81         }
     82         boolean_answers = {
     83             "Configure a testing deployment": True,
     84             "Configure a landing page on the base domain": True,
     85             "Obtain TLS certificates using Let's Encrypt": False,
     86             "Configure conversion to a fiat currency": True,
     87             "Use simulated conversion test mode (no EBICS bank connection)": True,
     88             "Configure Telesign SMS authentication": False,
     89             "Configure exchange terms of service": False,
     90             "Configure an exchange privacy policy": False,
     91             "Use the GNU Taler testing APT repository (Debian only)": True,
     92         }
     93 
     94         def ask(message, default=None, **_kwargs):
     95             return answers.get(message, default)
     96 
     97         def ask_matching(message, _pattern, default=None, **_kwargs):
     98             return matching_answers.get(message, default)
     99 
    100         def ask_yes_no(message, _default):
    101             if message.startswith("Enable Nexus services"):
    102                 self.fail("test mode must not offer to enable Nexus services")
    103             return boolean_answers[message]
    104 
    105         with tempfile.TemporaryDirectory() as temporary_directory:
    106             with (
    107                 mock.patch.object(inventory_wizard, "ask", side_effect=ask),
    108                 mock.patch.object(
    109                     inventory_wizard, "ask_matching", side_effect=ask_matching
    110                 ),
    111                 mock.patch.object(
    112                     inventory_wizard, "ask_yes_no", side_effect=ask_yes_no
    113                 ),
    114                 mock.patch.object(
    115                     inventory_wizard, "ask_int", side_effect=lambda _m, d: d
    116                 ),
    117                 mock.patch.object(
    118                     inventory_wizard.getpass, "getpass", return_value="secret"
    119                 ),
    120             ):
    121                 _, _, variables, _, _, _ = inventory_wizard.collect_configuration(
    122                     Path(temporary_directory)
    123                 )
    124 
    125         self.assertTrue(variables["regional_currency_conversion_test_mode"])
    126         self.assertFalse(variables["regional_currency_enable_nexus_services"])
    127 
    128 
    129 if __name__ == "__main__":
    130     unittest.main()