Repository: aws-cloudformation/cfn-lint

Issue:
AWS::Serverless::Application parameters
*Description of issue.*
When creating a `AWS::Serverless::Application` input parameters should match parameters required in the nested template.

  * Supplying parameters to `AWS::Serverless::Application` resources that do not exist in the child template will succeed in creating a Change Set but fail upon deployment.
 * Neglecting to provide parameters `AWS::Serverless::Application` resources that do exist in the child template will fail in creating a Change Set.


Discussion:
@redbaron09 agreed here.  We have tried not to reach out to validate things in an AWS account.   

Is there a way to do this without actually querying the account?

Or maybe we need to start thinking about a way to query live accounts when requested.
Following `Location` on the local file system, reading the parameters section, and comparing against the parameters supplied in the parent stack would be sufficient.
I'm using [`AWS::Serverless::Application`](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-application.html) in place of [`AWS::CloudFormation::Stack`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html)

We are doing this for `AWS::CloudFormation::Stack` with rule [E3043](https://github.com/aws-cloudformation/cfn-lint/blob/3492649d613a61fff3063ce0ffa404e1055c6a3a/src/cfnlint/rules/resources/cloudformation/NestedStackParameters.py).   Need to update the transform logic to leave strings as is.

Resolving patch:
diff --git a/src/cfnlint/transform.py b/src/cfnlint/transform.py
--- a/src/cfnlint/transform.py
+++ b/src/cfnlint/transform.py
@@ -105,8 +105,9 @@ def _replace_local_codeuri(self):
                     Transform._update_to_s3_uri('ContentUri', resource_dict)
             if resource_type == 'AWS::Serverless::Application':
                 if resource_dict.get('Location'):
-                    resource_dict['Location'] = ''
-                    Transform._update_to_s3_uri('Location', resource_dict)
+                    if isinstance(resource_dict.get('Location'), dict):
+                        resource_dict['Location'] = ''
+                        Transform._update_to_s3_uri('Location', resource_dict)
             if resource_type == 'AWS::Serverless::Api':
                 if (
                     'DefinitionBody' not in resource_dict


Test patch:
diff --git a/test/fixtures/templates/good/transform/applications_location.yaml b/test/fixtures/templates/good/transform/applications_location.yaml
new file mode 100644
--- /dev/null
+++ b/test/fixtures/templates/good/transform/applications_location.yaml
@@ -0,0 +1,11 @@
+Transform: AWS::Serverless-2016-10-31
+Resources:
+  App1:
+    Type: AWS::Serverless::Application
+    Properties:
+      Location: ./step_function_local_definition.yaml
+  App2:
+    Type: AWS::Serverless::Application
+    Properties:
+      Location:
+        ApplicationId: '1'
diff --git a/test/unit/module/transform/test_transform.py b/test/unit/module/transform/test_transform.py
--- a/test/unit/module/transform/test_transform.py
+++ b/test/unit/module/transform/test_transform.py
@@ -43,6 +43,37 @@ def test_conversion_of_step_function_definition_uri(self):
                 'Key': 'value'
             })
 
+    def test_conversion_of_application_location(self):
+        """ Tests if serverless application converts location to string when dict """
+        filename = 'test/fixtures/templates/good/transform/applications_location.yaml'
+        region = 'us-east-1'
+        template = cfn_yaml.load(filename)
+        transformed_template = Transform(filename, template, region)
+        transformed_template.transform_template()
+        self.assertEqual(
+            transformed_template._template.get('Resources').get(
+                'App1').get('Properties').get('TemplateURL'),
+            './step_function_local_definition.yaml')
+        self.assertEqual(
+            transformed_template._template.get('Resources').get(
+                'App2').get('Properties').get('TemplateURL'),
+            's3://bucket/value')
+    
+    def test_conversion_of_step_function_definition_uri(self):
+        """ Tests that the a serverless step function can convert a local path to a s3 path """
+        filename = 'test/fixtures/templates/good/transform/step_function_local_definition.yaml'
+        region = 'us-east-1'
+        template = cfn_yaml.load(filename)
+        transformed_template = Transform(filename, template, region)
+        transformed_template.transform_template()
+        self.assertDictEqual(
+            transformed_template._template.get('Resources').get(
+                'StateMachine').get('Properties').get('DefinitionS3Location'),
+            {
+                'Bucket': 'bucket',
+                'Key': 'value'
+            })
+
     def test_parameter_for_autopublish_version_bad(self):
         """Test Parameter is created for autopublish version run"""
         filename = 'test/fixtures/templates/bad/transform/auto_publish_alias.yaml'