Repository: hyperledger/aries-cloudagent-python

Issue:
🐛[Bug] - When running in read-only mode, a write ledger is still required in the ledgers.yaml configuration
When running ACA-Py in read-only mode (i.e.: we do this for verifiers such as VC-AuthN) with a multi-ledger configuration, the `ledgers.yaml` configuration file still requires a ledger to be set to `is_write: true`.

```log
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/__main__.py", line 69, in script_main
aca-py-1         |     main(sys.argv)
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/__main__.py", line 75, in main
aca-py-1         |     run(args)
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/__main__.py", line 64, in run
aca-py-1         |     run_command(command, args)
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/commands/__init__.py", line 38, in run_command
aca-py-1         |     module.execute(argv)
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/commands/start.py", line 49, in execute
aca-py-1         |     settings = get_settings(args)
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/config/argparse.py", line 93, in get_settings
aca-py-1         |     raise e
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/config/argparse.py", line 90, in get_settings
aca-py-1         |     settings.update(group.get_settings(args))
aca-py-1         |   File "/home/aries/.local/lib/python3.9/site-packages/aries_cloudagent/config/argparse.py", line 944, in get_settings
aca-py-1         |     raise ArgsParseError(
aca-py-1         | aries_cloudagent.config.error.ArgsParseError: No write ledger genesis provided in multi-ledger config
```

This is misleading, and may/will lead to issues when configuring the service, as well as potentially when consuming the configuration file in the code - when running in read-only mode there should be no need to specify a `is_write` ledger.


Discussion:

Resolving patch:
diff --git a/aries_cloudagent/config/argparse.py b/aries_cloudagent/config/argparse.py
--- a/aries_cloudagent/config/argparse.py
+++ b/aries_cloudagent/config/argparse.py
@@ -618,12 +618,6 @@ def add_arguments(self, parser: ArgumentParser):
             env_var="ACAPY_PROFILE_ENDPOINT",
             help="Specifies the profile endpoint for the (public) DID.",
         )
-        parser.add_argument(
-            "--read-only-ledger",
-            action="store_true",
-            env_var="ACAPY_READ_ONLY_LEDGER",
-            help="Sets ledger to read-only to prevent updates. Default: false.",
-        )
         parser.add_argument(
             "--universal-resolver",
             type=str,
@@ -691,9 +685,6 @@ def get_settings(self, args: Namespace) -> dict:
         if args.profile_endpoint:
             settings["profile_endpoint"] = args.profile_endpoint
 
-        if args.read_only_ledger:
-            settings["read_only_ledger"] = True
-
         if args.universal_resolver_regex and not args.universal_resolver:
             raise ArgsParseError(
                 "--universal-resolver-regex cannot be used without --universal-resolver"
@@ -855,6 +846,12 @@ def add_arguments(self, parser: ArgumentParser):
                 "specified ledger or genesis configurations.  Default: false."
             ),
         )
+        parser.add_argument(
+            "--read-only-ledger",
+            action="store_true",
+            env_var="ACAPY_READ_ONLY_LEDGER",
+            help="Sets ledger to read-only to prevent updates. Default: false.",
+        )
         parser.add_argument(
             "--ledger-keepalive",
             default=5,
@@ -912,6 +909,9 @@ def get_settings(self, args: Namespace) -> dict:
             multi_configured = False
             update_pool_name = False
             write_ledger_specified = False
+
+            if args.read_only_ledger:
+                settings["read_only_ledger"] = True
             if args.genesis_url:
                 settings["ledger.genesis_url"] = args.genesis_url
                 single_configured = True
@@ -940,7 +940,7 @@ def get_settings(self, args: Namespace) -> dict:
                             txn_config["pool_name"] = txn_config["id"]
                         update_pool_name = True
                         ledger_config_list.append(txn_config)
-                    if not write_ledger_specified:
+                    if not write_ledger_specified and not args.read_only_ledger:
                         raise ArgsParseError(
                             "No write ledger genesis provided in multi-ledger config"
                         )
diff --git a/aries_cloudagent/config/ledger.py b/aries_cloudagent/config/ledger.py
--- a/aries_cloudagent/config/ledger.py
+++ b/aries_cloudagent/config/ledger.py
@@ -110,10 +110,14 @@ async def load_multiple_genesis_transactions_from_config(settings: Settings):
         if "endorser_did" in config:
             config_item["endorser_did"] = config.get("endorser_did")
         ledger_txns_list.append(config_item)
-    if not write_ledger_set and not (
-        settings.get("ledger.genesis_transactions")
-        or settings.get("ledger.genesis_file")
-        or settings.get("ledger.genesis_url")
+    if (
+        not write_ledger_set
+        and not settings.get("ledger.read_only")
+        and not (
+            settings.get("ledger.genesis_transactions")
+            or settings.get("ledger.genesis_file")
+            or settings.get("ledger.genesis_url")
+        )
     ):
         raise ConfigError(
             "No is_write ledger set and no genesis_url,"
diff --git a/aries_cloudagent/utils/multi_ledger.py b/aries_cloudagent/utils/multi_ledger.py
--- a/aries_cloudagent/utils/multi_ledger.py
+++ b/aries_cloudagent/utils/multi_ledger.py
@@ -12,11 +12,15 @@ def get_write_ledger_config_for_profile(settings: BaseSettings) -> dict:
     prod_write_ledger_pool = OrderedDict()
     non_prod_write_ledger_pool = OrderedDict()
     for ledger_config in settings.get("ledger.ledger_config_list"):
-        if ledger_config.get("is_production") and ledger_config.get("is_write"):
+        if ledger_config.get("is_production") and (
+            ledger_config.get("is_write") or settings.get("ledger.read_only")
+        ):
             prod_write_ledger_pool[
                 ledger_config.get("id") or ledger_config.get("pool_name")
             ] = ledger_config
-        elif not ledger_config.get("is_production") and ledger_config.get("is_write"):
+        elif not ledger_config.get("is_production") and (
+            ledger_config.get("is_write") or settings.get("ledger.read_only")
+        ):
             non_prod_write_ledger_pool[
                 ledger_config.get("id") or ledger_config.get("pool_name")
             ] = ledger_config


Test patch: