Repository: aws-cloudformation/cfn-lint

Issue:
Don't hardcode all for AvailabilityZones not relevant for AWS::ElasticLoadBalancingV2::TargetGroup
Hello, 

*cfn-lint version: 0.19.1*

*Description of issue.*

The following snippet : 

```
Resources:
  DefaultTargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      VpcId: hello
      Port: 80
      Protocol: HTTP
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: "/"
      HealthCheckPort: "80"
      HealthCheckProtocol: "HTTP"
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 5
      TargetType: ip
      Targets:
        - 
          Id: "10.31.33.28"
          AvailabilityZone: all
      Matcher:
        HttpCode: "200"
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: "20"
```

Triggers this warn message : 

> W3010 Don't hardcode all for AvailabilityZones 

In the case of AWS::ElasticLoadBalancingV2::TargetGroup, there is legitimacy to hardcode all for AvailabilityZones : 
>  If the IP address is outside the VPC, this parameter is required. With an Application Load Balancer, if the target type is ip and the IP address is outside the VPC for the target group, the only supported value is all. 

I'm unsure what to PR here. Should we get rid of this line ? https://github.com/aws-cloudformation/cfn-python-lint/blob/master/src/cfnlint/rules/resources/properties/AvailabilityZone.py#L52 

Thanks for the suggestions. 

[1] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-targetgroup-targetdescription.html#aws-properties-elasticloadbalancingv2-targetgroup-targetdescription-properties



Discussion:

Resolving patch:
diff --git a/src/cfnlint/rules/resources/properties/AvailabilityZone.py b/src/cfnlint/rules/resources/properties/AvailabilityZone.py
--- a/src/cfnlint/rules/resources/properties/AvailabilityZone.py
+++ b/src/cfnlint/rules/resources/properties/AvailabilityZone.py
@@ -63,9 +63,11 @@ def check_az_value(self, value, path):
         """Check ref for VPC"""
         matches = []
 
-        if path[-1] != 'Fn::GetAZs':
-            message = 'Don\'t hardcode {0} for AvailabilityZones'
-            matches.append(RuleMatch(path, message.format(value)))
+        # value of `all` is a valide exception in AWS::ElasticLoadBalancingV2::TargetGroup
+        if value not in ['all']:
+            if path[-1] != ['Fn::GetAZs']:
+                message = 'Don\'t hardcode {0} for AvailabilityZones'
+                matches.append(RuleMatch(path, message.format(value)))
 
         return matches
 


Test patch:
diff --git a/test/fixtures/templates/good/resources/properties/az.yaml b/test/fixtures/templates/good/resources/properties/az.yaml
new file mode 100644
--- /dev/null
+++ b/test/fixtures/templates/good/resources/properties/az.yaml
@@ -0,0 +1,24 @@
+---
+AWSTemplateFormatVersion: "2010-09-09"
+Resources:
+  DefaultTargetGroup:
+    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
+    Properties:
+      VpcId: hello
+      Port: 80
+      Protocol: HTTP
+      HealthCheckIntervalSeconds: 30
+      HealthCheckPath: "/"
+      HealthCheckPort: "80"
+      HealthCheckProtocol: "HTTP"
+      HealthCheckTimeoutSeconds: 5
+      HealthyThresholdCount: 5
+      TargetType: ip
+      Targets:
+        - Id: "10.31.33.28"
+          AvailabilityZone: all
+      Matcher:
+        HttpCode: "200"
+      TargetGroupAttributes:
+        - Key: deregistration_delay.timeout_seconds
+          Value: "20"
diff --git a/test/rules/resources/properties/test_availability_zone.py b/test/rules/resources/properties/test_availability_zone.py
--- a/test/rules/resources/properties/test_availability_zone.py
+++ b/test/rules/resources/properties/test_availability_zone.py
@@ -24,6 +24,9 @@ def setUp(self):
         """Setup"""
         super(TestPropertyAvailabilityZone, self).setUp()
         self.collection.register(AvailabilityZone())
+        self.success_templates = [
+            'test/fixtures/templates/good/resources/properties/az.yaml'
+        ]
 
     def test_file_positive(self):
         """Success test"""