Repository: aws-ia/taskcat
Issue: Taskcat not able to do the Nested Join

**Describe the bug**

When "TemplateURL" in the CloudFormation template is writen in the form of Nested join then taskcat is not able to fetch the template. 

**For Example: 
This is how the TemplateURL is given in CloudFormation Template:** 
```yaml
    TemplateURL: !Join 
        - ''
        - - 'https://'
          - !Join ["-", [!FindInMap ["SourceCode", "General", "S3Bucket"], "reference"]]
          - '.s3.amazonaws.com/'
          - !Join ["/", [!FindInMap ["SourceCode", "General", "KeyPrefix"], "cloudformation.template"]]
```

**Taskcat Error:** 
```
version 0.9.8
[ERROR  ] : TypeError expected str, bytes or os.PathLike object, not dict_node
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/taskcat/_cli.py", line 70, in main
    cli.run()
  File "/usr/local/lib/python3.7/site-packages/taskcat/_cli_core.py", line 228, in run
    return getattr(command(), subcommand)(**args)
  File "/usr/local/lib/python3.7/site-packages/taskcat/_cli_modules/test.py", line 60, in run
    templates = config.get_templates(project_root_path)
  File "/usr/local/lib/python3.7/site-packages/taskcat/_config.py", line 312, in get_templates
    s3_key_prefix=f"{self.config.project.name}/",
  File "/usr/local/lib/python3.7/site-packages/taskcat/_cfn/template.py", line 30, in __init__
    self._find_children()
  File "/usr/local/lib/python3.7/site-packages/taskcat/_cfn/template.py", line 111, in _find_children
    resource["Properties"]["TemplateURL"]
  File "/usr/local/lib/python3.7/site-packages/taskcat/_cfn/template.py", line 72, in _template_url_to_path
    template_path = self.project_root / template_path
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py", line 908, in __truediv__
    return self._make_child((key,))
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py", line 695, in _make_child
    drv, root, parts = self._parse_args(args)
  File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/pathlib.py", line 649, in _parse_args
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not dict_node
```

Changes: 
When I change the "/usr/local/lib/python3.7/site-packages/taskcat/_cfn/template.py" file and add one more "template_path = template_url["Fn::Join"][1][-1]" it worked but then it will not work if there will be single join. 
```python
    def _template_url_to_path(self, template_url):
        # TODO: this code assumes a specific url schema, should rather attempt to
        #  resolve values from params/defaults
        if isinstance(template_url, dict):
            if "Fn::Sub" in template_url.keys():
                if isinstance(template_url["Fn::Sub"], str):
                    template_path = template_url["Fn::Sub"].split("}")[-1]
                else:
                    template_path = template_url["Fn::Sub"][0].split("}")[-1]
            elif "Fn::Join" in list(template_url.keys())[0]:
                template_path = template_url["Fn::Join"][1][-1]
        elif isinstance(template_url, str):
            template_path = "/".join(template_url.split("/")[-2:])
        template_path = self.project_root / template_path
        if template_path.is_file():
            return template_path
        LOG.warning(
            "Failed to discover path for %s, path %s does not exist",
            template_url,
            template_path,
        )
        return ""
```

**To Reproduce**
Steps to reproduce the behavior:
1. Are you testing a *QuickStart* or *Custom template*? - Custom Template
2. Attach or link a copy of the template if possible (**remove any sensitive info**)  - cannot share template
3. Provide the parameters that you passed. (**remove any sensitive info**) - Provided above
4. How did you install taskcat? (docker or pip3) - pip3
5. Are you using a *profile*, *an instance role* or  *access keys* to run taskcat? - access keys
6. Is your AWS environment configured via `aws configure`? - yes 

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Version (Please make sure you are running the latest version of taskcat)
 - Taskcat Version: 0.9.8

 Note: Python Version (python3 required)

To find versions:
*Via taskcat*: `taskcat -V`
*Via pip3*: `pip3 show taskcat`

Note: both version should match

To update taskcat run:
 *for docker* : `docker pull taskcat/taskcat`
 *for pip3*: `pip3 install --upgrade taskcat`

**Additional context**
Add any other context about the problem here.


Changed files:
taskcat/_cfn/template.py

diff --git a/taskcat/_cfn/template.py b/taskcat/_cfn/template.py
index 646b881..9c4e05d 100644
--- a/taskcat/_cfn/template.py
+++ b/taskcat/_cfn/template.py
@@ -59,6 +59,7 @@ class Template:
     def _template_url_to_path(self, template_url):
         # TODO: this code assumes a specific url schema, should rather attempt to
         #  resolve values from params/defaults
+        template_path = None
         if isinstance(template_url, dict):
             if "Fn::Sub" in template_url.keys():
                 if isinstance(template_url["Fn::Sub"], str):
@@ -69,9 +70,10 @@ class Template:
                 template_path = template_url["Fn::Join"][1][-1]
         elif isinstance(template_url, str):
             template_path = "/".join(template_url.split("/")[-2:])
-        template_path = self.project_root / template_path
-        if template_path.is_file():
-            return template_path
+        if isinstance(template_path, str):
+            template_path = self.project_root / template_path
+            if template_path.is_file():
+                return template_path
         LOG.warning(
             "Failed to discover path for %s, path %s does not exist",
             template_url,
@@ -80,13 +82,8 @@ class Template:
         return ""
 
     def _get_relative_url(self, path: str) -> str:
-        if not self.url:
-            return ""
-        suffix = str(self.template_path).replace(str(self.project_root), "")
-        suffix_length = len(suffix.lstrip("/").split("/"))
-        url_prefix = "/".join(self.url.split("/")[0:-suffix_length])
         suffix = str(path).replace(str(self.project_root), "")
-        url = url_prefix + suffix
+        url = self.url_prefix() + suffix
         return url
 
     def url_prefix(self) -> str: