Repository: aws-cloudformation/cfn-lint

Issue:
E3001 Missing properties raised as an error when they're not required
*cfn-lint version: 0.4.2*

*Description of issue.*

An error about missing properties is not always useful. There are resources which don't necessarily need properties.

Please provide as much information as possible:
* Template linting issues:
```
    "WaitCondition": {
      "Type": "AWS::CloudFormation::WaitCondition",
      "CreationPolicy": {
        "ResourceSignal": {
          "Timeout": "PT15M",
          "Count": {
            "Ref": "TargetCapacity"
          }
        }
      }
    }
```
Getting `E3001 Properties not defined for resource WaitCondition`

* Feature request:

I'm not sure if there's a list of resources which don't need properties in many situations. S3 buckets and WaitCondition seem like good candidates for not raising this.
[AWS docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html) say:
> Use the optional Parameters section to customize your templates.
so it doesn't sound like it needs to be provided.


Discussion:
@cmmeyer this one may be with you too.  The reason this is showing up is because according to the spec there are required properties.
```
"AWS::CloudFormation::WaitCondition": {
      "Attributes": {
        "Data": {
          "PrimitiveType": "Json"
        }
      },
      "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html",
      "Properties": {
        "Count": {
          "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html#cfn-waitcondition-count",
          "PrimitiveType": "Integer",
          "Required": false,
          "UpdateType": "Mutable"
        },
        "Handle": {
          "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html#cfn-waitcondition-handle",
          "PrimitiveType": "String",
          "Required": true,
          "UpdateType": "Mutable"
        },
        "Timeout": {
          "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html#cfn-waitcondition-timeout",
          "PrimitiveType": "String",
          "Required": true,
          "UpdateType": "Mutable"
        }
      }
    },
```
This matches the documentation that says those properties are required.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waitcondition.html#w2ab2c21c10d213c17

If the spec didn't have required attributes `Properties` wouldn't be required.
```
➜  cat test.yaml
---
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  myBucket:
    Type: AWS::S3::Bucket
➜  cfn-lint test1.yaml
➜  echo $?
0
```
Tested this and looks like a special case related to WaitConditions.   We are probably going to have to come up with an exception process for `E3001` as the Spec Properties are required if there isn't a `CreationPolicy`.

Looks like there is a Warning rule that should be added for making sure people are using `CreationPolicy` when doing ASGs and Instances instead of doing a `Ref` to a `AWS::CloudFormation::WaitCondition`. 


Resolving patch:
diff --git a/src/cfnlint/rules/resources/Configuration.py b/src/cfnlint/rules/resources/Configuration.py
--- a/src/cfnlint/rules/resources/Configuration.py
+++ b/src/cfnlint/rules/resources/Configuration.py
@@ -111,10 +111,13 @@ def match(self, cfn):
                                 if property_spec.get('Required', False):
                                     required += 1
                             if required > 0:
-                                message = 'Properties not defined for resource {0}'
-                                matches.append(RuleMatch(
-                                    ['Resources', resource_name],
-                                    message.format(resource_name)
-                                ))
+                                if resource_type == 'AWS::CloudFormation::WaitCondition' and 'CreationPolicy' in resource_values.keys():
+                                    self.logger.debug('Exception to required properties section as CreationPolicy is defined.')
+                                else:
+                                    message = 'Properties not defined for resource {0}'
+                                    matches.append(RuleMatch(
+                                        ['Resources', resource_name],
+                                        message.format(resource_name)
+                                    ))
 
         return matches


Test patch:
diff --git a/test/fixtures/templates/good/generic.yaml b/test/fixtures/templates/good/generic.yaml
--- a/test/fixtures/templates/good/generic.yaml
+++ b/test/fixtures/templates/good/generic.yaml
@@ -160,6 +160,12 @@ Resources:
       Version: "1.0"
       Properties:
         ServiceToken: anArn
+  WaitCondition:
+    Type: AWS::CloudFormation::WaitCondition
+    CreationPolicy:
+      ResourceSignal:
+        Timeout: PT15M
+        Count: 1
 Outputs:
   ElasticIP:
     Value: !Sub "${ElasticIP}/32"
diff --git a/test/module/test_template.py b/test/module/test_template.py
--- a/test/module/test_template.py
+++ b/test/module/test_template.py
@@ -44,7 +44,7 @@ def setUp(self):
 
     def test_get_resources_success(self):
         """Test Success on Get Resources"""
-        valid_resource_count = 10
+        valid_resource_count = 11
         resources = self.template.get_resources()
         assert len(resources) == valid_resource_count, 'Expected {} resources, got {}'.format(valid_resource_count, len(resources))
 
@@ -80,7 +80,7 @@ def test_get_parameter_names(self):
 
     def test_get_valid_refs(self):
         """ Get Valid REFs"""
-        valid_ref_count = 25
+        valid_ref_count = 26
         refs = self.template.get_valid_refs()
         assert len(refs) == valid_ref_count, 'Expected {} refs, got {}'.format(valid_ref_count, len(refs))