Repository: cloudtools/troposphere

Issue:
Template Generator is broken.
When attempting to use the template generator on well defined inputs:

```
import json

from troposphere.template_generator import TemplateGenerator
dictionary = json.loads("""{
  "Resources": {
     "title": {
        "Type": "AWS::S3::Bucket",
        "Properties": {
          "BucketName": "Bob"
        }
    }
  }
}""")
TemplateGenerator(dictionary)
```

yields the following error

```
AttributeError                            Traceback (most recent call last)
<ipython-input-7-a7d4c9f1b746> in <module>()
----> 1 template_generator.TemplateGenerator(json.loads(x))

/usr/lib/python2.7/site-packages/troposphere/template_generator.pyc in __init__(self, cf_template)
     57             self.add_condition(k, self._convert_definition(v, k))
     58         for k, v in cf_template.get('Resources', {}).iteritems():
---> 59             self.add_resource(self._convert_definition(v, k))
     60         for k, v in cf_template.get('Outputs', {}).iteritems():
     61             self.add_output(self._create_instance(Output, v, k))

/usr/lib/python2.7/site-packages/troposphere/__init__.pyc in add_resource(self, resource)
    450 
    451     def add_resource(self, resource):
--> 452         return self._update(self.resources, resource)
    453 
    454     def add_version(self, version=None):

/usr/lib/python2.7/site-packages/troposphere/__init__.pyc in _update(self, d, values)
    435                 d[v.title] = v
    436         else:
--> 437             if values.title in d:
    438                 self.handle_duplicate_key(values.title)
    439             d[values.title] = values

AttributeError: 'dict' object has no attribute 'title'
```

The reason for this is as follows:

`template_generator.py` incorrectly invokes `pkgutil.walk_packages` here:

https://github.com/cloudtools/troposphere/blob/master/troposphere/template_generator.py#L313

https://docs.python.org/3/library/pkgutil.html

`walk_packages` expects a `list` rather than a `string`, of file paths. This error is not caught by the tests because if a string is passed in, then the entire string is treated as a list of paths. The only valid path that does anything will be the `'.'` in `'template_generator.py'`, resulting in the current directory being searched for directories named `'troposphere'`. Obviously, in the test environment, it will find such a package and successfully include all the necessary modules needed to pass the tests.



Discussion:

Resolving patch:
diff --git a/troposphere/template_generator.py b/troposphere/template_generator.py
--- a/troposphere/template_generator.py
+++ b/troposphere/template_generator.py
@@ -16,6 +16,7 @@
 import inspect
 import pkgutil
 import importlib
+import os
 
 from collections import Sequence, Mapping
 
@@ -307,12 +308,12 @@ def _get_function_type(self, function_name):
 
     def _import_all_troposphere_modules(self):
         """ Imports all troposphere modules and returns them """
+        dirname = os.path.join(os.path.dirname(__file__))
         module_names = [
             pkg_name
             for importer, pkg_name, is_pkg in
-            pkgutil.walk_packages(__file__)
-            if not is_pkg and pkg_name.startswith("troposphere") and
-            pkg_name not in self.DEPRECATED_MODULES]
+            pkgutil.walk_packages([dirname], prefix="troposphere.")
+            if not is_pkg and pkg_name not in self.DEPRECATED_MODULES]
         module_names.append('troposphere')
 
         modules = []


Test patch: