Repository: cloud-custodian/cloud-custodian

Issue:
c7n-org -l option fails when no policies match
### Describe the bug

policies_config['policies'] is empty if no policies match any tags and you get an ERROR:
```
def initialize_provider_output(policies_config, output_dir, regions):
    policy_config = Config.empty(
        account_id='112233445566',
        output_dir=output_dir,
        region=regions and regions[0] or "us-east-1"
    )
    if policies_config['policies']:
        provider_name = get_policy_provider(policies_config['policies'][0])
    else:
        provider_name = 'aws'
    provider = cloud_providers[provider_name]()
    provider.initialize(policy_config)
    return policy_config.output_dir
```

### What did you expect to happen?

I expected no error

### Cloud Provider

Amazon Web Services (AWS)

### Cloud Custodian version and dependency information

```shell
Custodian:   0.9.24
Python:      3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0]
Platform:    posix.uname_result(sysname='Linux', nodename='8d8e532ec080', release='5.15.49-linuxkit', version='#1 SMP Tue Sep 13 07:51:46 UTC 2022', machine='x86_64')
Using venv:  True
Docker: True
Installed:
```


### Policy

```shell
policies is empty in the scenario
```


### Relevant log/traceback output

```shell
Traceback (most recent call last):
 File "/usr/local/bin/c7n-org", line 6, in <module>
  sys.exit(cli())
 File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
  return self.main(*args, **kwargs)
 File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1055, in main
  rv = self.invoke(ctx)
 File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
  return _process_result(sub_ctx.command.invoke(sub_ctx))
 File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
  return ctx.invoke(self.callback, **ctx.params)
 File "/usr/local/lib/python3.10/site-packages/click/core.py", line 760, in invoke
  return __callback(*args, **kwargs)
 File "/src/tools/c7n_org/c7n_org/cli.py", line 727, in run
  output_dir = initialize_provider_output(custodian_config, output_dir, region)
 File "/src/tools/c7n_org/c7n_org/cli.py", line 679, in initialize_provider_output
  print(policies_config['policies'][0])
```


### Extra information or context

Here is the solution:

```
def initialize_provider_output(policies_config, output_dir, regions):
    policy_config = Config.empty(
        account_id='112233445566',
        output_dir=output_dir,
        region=regions and regions[0] or "us-east-1"
    )
    if policies_config['policies']:
        provider_name = get_policy_provider(policies_config['policies'][0])
    else:
        provider_name = 'aws'
    provider = cloud_providers[provider_name]()
    provider.initialize(policy_config)
    return policy_config.output_dir
```


Discussion:

Resolving patch:
diff --git a/tools/c7n_org/c7n_org/cli.py b/tools/c7n_org/c7n_org/cli.py
--- a/tools/c7n_org/c7n_org/cli.py
+++ b/tools/c7n_org/c7n_org/cli.py
@@ -712,6 +712,13 @@ def run(config, use, output_dir, accounts, not_accounts, tags, region,
     accounts_config, custodian_config, executor = init(
         config, use, debug, verbose, accounts, tags, policy, policy_tags=policy_tags,
         not_accounts=not_accounts)
+    if not (accounts_config["accounts"] and custodian_config["policies"]):
+        log.info(
+            "Targeting accounts: %d, policies: %d. Nothing to do." %
+            (len(accounts_config["accounts"]), len(custodian_config["policies"]))
+        )
+        return
+
     policy_counts = Counter()
     success = True
 


Test patch:
diff --git a/tools/c7n_org/tests/test_org.py b/tools/c7n_org/tests/test_org.py
--- a/tools/c7n_org/tests/test_org.py
+++ b/tools/c7n_org/tests/test_org.py
@@ -294,3 +294,47 @@ def test_accounts_iterator(self):
         accounts[0]["vars"]["default_tz"] = "Sydney/Australia"
         # NOTE allow override at account level
         accounts[1]["vars"]["default_tz"] = "UTC"
+
+    def test_cli_nothing_to_do(self):
+        run_dir = self.setup_run_dir()
+        logger = mock.MagicMock()
+        run_account = mock.MagicMock()
+        run_account.return_value = (
+            {'compute': 24, 'serverless': 12}, True)
+        self.patch(org, 'logging', logger)
+        self.patch(org, 'run_account', run_account)
+        self.change_cwd(run_dir)
+        log_output = self.capture_logging('c7n_org')
+        runner = CliRunner()
+
+        cli_args = [
+            'run', '-c', 'accounts.yml', '-u', 'policies.yml',
+            '--debug', '-s', 'output', '--cache-path', 'cache',
+            '--metrics-uri', 'aws://',
+        ]
+
+        # No policies to run
+        result = runner.invoke(
+            org.cli,
+            cli_args + ['--policytags', 'nonsense'],
+            catch_exceptions=False
+        )
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(
+            log_output.getvalue().strip(),
+            "Targeting accounts: 2, policies: 0. Nothing to do.",
+        )
+
+        # No accounts to run against
+        log_output.truncate(0)
+        log_output.seek(0)
+        result = runner.invoke(
+            org.cli,
+            cli_args + ['--tags', 'nonsense'],
+            catch_exceptions=False
+        )
+        self.assertEqual(result.exit_code, 0)
+        self.assertEqual(
+            log_output.getvalue().strip(),
+            "Targeting accounts: 0, policies: 2. Nothing to do.",
+        )