Repository: forseti-security/forseti-security
Issue: The GCP deployment is broken in 2.0-dev

Repro steps:

1. Create a project in the cloud console
1. Start cloud shell for the project
1. git clone -b 2.0-dev --single-branch-only https://github.com/GoogleCloudPlatform/forseti-security.git
1. cd forseti-security
1. python scripts/gcp_setup/setup_forseti.py
1. Choose defaults by hiting enter on any prompts

Here's the relevant bits output of `/tmp/deployment.log` on the host machine.


```
Starting services.
Success! The Forseti API server has been started.
Copying gs://redacted-project-name-data-110607/configs/forseti_conf.yaml...
/ [0 files][    0.0 B/  8.2 KiB]                                                ^M/ [1 files][  8.2 KiB/  8.2 KiB]                                                ^M
Operation completed over 1 objects/8.2 KiB.
Copying gs://redacted-project-name-data-110607/rules/bigquery_rules.yaml...
/ [0 files][    0.0 B/  1.6 KiB]                                                ^M/ [1 files][  1.6 KiB/  1.6 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/bucket_rules.yaml...
/ [1 files][  1.6 KiB/  2.7 KiB]                                                ^M/ [2 files][  2.7 KiB/  2.7 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/cloudsql_rules.yaml...
/ [2 files][  2.7 KiB/  3.8 KiB]                                                ^M/ [3 files][  3.8 KiB/  3.8 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/firewall_rules.yaml...
/ [3 files][  3.8 KiB/  5.3 KiB]                                                ^M/ [4 files][  5.3 KiB/  5.3 KiB]                                                ^M
==> NOTE: You are performing a sequence of gsutil operations that may
run significantly faster if you instead use gsutil -m -o ... Please
see the -m section under "gsutil help options" for further information
about when gsutil -m can be advantageous.

Copying gs://redacted-project-name-data-110607/rules/forwarding_rules.yaml...
/ [4 files][  5.3 KiB/  6.9 KiB]                                                ^M/ [5 files][  6.9 KiB/  6.9 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/group_rules.yaml...
/ [5 files][  6.9 KiB/  8.1 KiB]                                                ^M/ [6 files][  8.1 KiB/  8.1 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/iam_rules.yaml...
/ [6 files][  8.1 KiB/  9.7 KiB]                                                ^M-^M- [7 files][  9.7 KiB/  9.7 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/iap_rules.yaml...
- [7 files][  9.7 KiB/ 10.9 KiB]                                                ^M- [8 files][ 10.9 KiB/ 10.9 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/instance_network_interface_rules.yaml...
- [8 files][ 10.9 KiB/ 12.1 KiB]                                                ^M- [9 files][ 12.1 KiB/ 12.1 KiB]                                                ^MCopying gs://redacted-project-name-data-110607/rules/ke_rules.yaml...
- [9 files][ 12.1 KiB/ 15.6 KiB]                                                ^M- [10 files][ 15.6 KiB/ 15.6 KiB]                                               ^M
Operation completed over 10 objects/15.6 KiB.
Run inventory creation
2018-02-01 17:17:56,762 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:17:56,763 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:17:56,764 __main__     WARNING  load IOError - trying to open configuration file located at /home/ubuntu/.forseti
id: "2018-02-01T17:17:56.79991"
last_warning: "\\'\\'"
last_error: "\\'\\'"

id: "2018-02-01T17:17:56.79991"
step: "497558025406"
last_warning: "\\'\\'"
last_error: "\\'\\'"

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 1074, in <module>
    main(sys.argv[1:], ENV_CONFIG)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 1056, in main
    services[config.service](client, config, output, config_env)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 741, in run_inventory
    actions[config.action]()
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 717, in do_create_inventory
    config.import_as):
  File "/usr/local/lib/python2.7/dist-packages/grpc/_channel.py", line 347, in next
    return self._next()
  File "/usr/local/lib/python2.7/dist-packages/grpc/_channel.py", line 338, in _next
    raise self
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.UNKNOWN, Exception iterating responses: unauthorized_client: Client is unauthorized to retrieve access tokens using this method.)>
2018-02-01 17:18:10,278 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:18:10,279 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:18:10,280 __main__     WARNING  load IOError - trying to open configuration file located at /home/ubuntu/.forseti
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 1074, in <module>
    main(sys.argv[1:], ENV_CONFIG)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 1056, in main
    services[config.service](client, config, output, config_env)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 700, in run_model
    actions[config.action]()
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 689, in do_use_model
    raise Warning('use_model failed, the specified model is '
Warning: use_model failed, the specified model is either not existed or not usable.
Created inventory and using model 20180201T171755
2018-02-01 17:18:21,185 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:18:21,186 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:18:21,187 __main__     WARNING  load IOError - trying to open configuration file located at /home/ubuntu/.forseti
Forseti config: {'model': '', 'endpoint': 'localhost:50051', 'format': 'text'}
Run scanner with /home/ubuntu/forseti-security/configs/forseti_conf.yaml
2018-02-01 17:18:22,088 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:18:22,090 __main__     INFO     read_env reading environment variable FORSETI_CLIENT_CONFIG = /home/ubuntu/.forseti
2018-02-01 17:18:22,090 __main__     WARNING  load IOError - trying to open configuration file located at /home/ubuntu/.forseti
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 1074, in <module>
    main(sys.argv[1:], ENV_CONFIG)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 1056, in main
    services[config.service](client, config, output, config_env)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 642, in run_scanner
    actions[config.action]()
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/cli.py", line 636, in do_run
    result = client.run(config.config_file)
  File "/usr/local/lib/python2.7/dist-packages/forseti_security-2.0.0-py2.7.egg/google/cloud/forseti/services/client.py", line 49, in wrapper
    raise Exception("API requires model to be set")
Exception: API requires model to be set
Ran scanner
Added the run_forseti.sh to crontab
Execution of startup script finished
```


Changed files:
google/cloud/forseti/services/inventory/base/resources.py

diff --git a/google/cloud/forseti/services/inventory/base/resources.py b/google/cloud/forseti/services/inventory/base/resources.py
index 5b4d451b..ecd3bd0a 100644
--- a/google/cloud/forseti/services/inventory/base/resources.py
+++ b/google/cloud/forseti/services/inventory/base/resources.py
@@ -146,16 +146,20 @@ class Resource(object):
         visitor.visit(self)
         for yielder_cls in self._contains:
             yielder = yielder_cls(self, visitor.get_client())
-            for resource in yielder.iter():
-                res = resource
-                new_stack = stack + [self]
-
-                # Parallelization for resource subtrees.
-                if res.should_dispatch():
-                    callback = partial(res.try_accept, visitor, new_stack)
-                    visitor.dispatch(callback)
-                else:
-                    res.try_accept(visitor, new_stack)
+            try:
+                for resource in yielder.iter():
+                    res = resource
+                    new_stack = stack + [self]
+
+                    # Parallelization for resource subtrees.
+                    if res.should_dispatch():
+                        callback = partial(res.try_accept, visitor, new_stack)
+                        visitor.dispatch(callback)
+                    else:
+                        res.try_accept(visitor, new_stack)
+            except Exception as e:
+                self.add_warning(e)
+                visitor.on_child_error(e)
 
         if self._warning:
             visitor.update(self)