Repository: cloud-custodian/cloud-custodian

Issue:
Error running c7n-org version 0.3.1
```
Traceback (most recent call last):
  File "/usr/local/bin/c7n-org", line 9, in <module>
    load_entry_point('c7n-org==0.3.1', 'console_scripts', 'c7n-org')()
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/c7n_org/cli.py", line 459, in run
    for p, count in f.result().items():
  File "/usr/local/lib/python2.7/dist-packages/concurrent/futures/_base.py", line 455, in result
    return self.__get_result()
  File "/usr/local/lib/python2.7/dist-packages/concurrent/futures/_base.py", line 414, in __get_result
    raise exception_type, self._exception, self._traceback
KeyError: 'profile'```


Discussion:
What command did you use?
This is an issue with gracefully handling the role/profile not found scenario. I did some debugging and found that when a role or profile is not found c7n-org is just exiting instead of handling the error.
yeah.. looks like issue from adding profile support, i'll take a look.
thats odd, i've run a few policies through org and i'm looking at the config files, i don't have profile defined.

what actual command are you running?

INFO:export-config-gen:role not found `account-name`
Traceback (most recent call last):
  File "/usr/local/bin/c7n-org", line 9, in <module>
    load_entry_point('c7n-org==0.3.1', 'console_scripts', 'c7n-org')()
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python2.7/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/c7n_org/cli.py", line 448, in run
    debug)] = (a, r)
  File "/usr/local/lib/python2.7/dist-packages/c7n/executor.py", line 63, in submit
    return MainThreadFuture(func(*args, **kw))
  File "/usr/local/lib/python2.7/dist-packages/c7n_org/cli.py", line 374, in run_account
    elif account['profile']:
KeyError: 'profile'

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
@@ -47,7 +47,8 @@
 log = logging.getLogger('c7n_org')
 
 
-WORKER_COUNT = int(os.environ.get('C7N_ORG_PARALLEL', multiprocessing.cpu_count() * 4))
+WORKER_COUNT = int(
+    os.environ.get('C7N_ORG_PARALLEL', multiprocessing.cpu_count() * 4))
 
 
 CONFIG_SCHEMA = {
@@ -64,12 +65,12 @@
                 'name': {'type': 'string'},
                 'email': {'type': 'string'},
                 'account_id': {'type': 'string'},
-                'profile': {'type': 'string'},
+                'profile': {'type': 'string', 'minLength': 3},
                 'tags': {'type': 'array', 'items': {'type': 'string'}},
                 'regions': {'type': 'array', 'items': {'type': 'string'}},
                 'role': {'oneOf': [
                     {'type': 'array', 'items': {'type': 'string'}},
-                    {'type': 'string'}]},
+                    {'type': 'string', 'minLength': 3}]},
                 'external_id': {'type': 'string'},
             }
         }
@@ -175,10 +176,10 @@ def report_account(account, region, policies_config, output_path, debug):
         account_id=account['account_id'], metrics_enabled=False,
         cache=cache_path, log_group=None, profile=None, external_id=None)
 
-    if account['role']:
+    if account.get('role'):
         bag['assume_role'] = account['role']
         bag['external_id'] = account.get('external_id')
-    elif account['profile']:
+    elif account.get('profile'):
         bag['profile'] = account['profile']
 
     policies = PolicyCollection.from_data(policies_config, bag)
@@ -376,10 +377,10 @@ def run_account(account, region, policies_config, output_path,
         account_id=account['account_id'], metrics_enabled=metrics,
         cache=cache_path, log_group=None, profile=None, external_id=None)
 
-    if account['role']:
+    if account.get('role'):
         bag['assume_role'] = account['role']
         bag['external_id'] = account.get('external_id')
-    elif account['profile']:
+    elif account.get('profile'):
         bag['profile'] = account['profile']
 
     policies = PolicyCollection.from_data(policies_config, bag)


Test patch: