from troposphere.ec2 import SecurityGroupIngress, SecurityGroupEgress
from stacker.blueprints.base import Blueprint

CLASS_MAP = {
    "IngressRules": SecurityGroupIngress,
    "EgressRules": SecurityGroupEgress,
}


class SecurityGroupRules(Blueprint):
    """Used to add Ingress/Egress rules to existing security groups.

    This blueprint uses two variables:
        IngressRules:
            A dict with keys of the virtual titles for each rule, and with the
            value being a dict of the parameters taken directly from:
                http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group-ingress.html
        EgressRules:
            A dict with keys of the virtual titles for each rule, and with the
            value being a dict of the parameters taken directly from:
                http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-security-group-egress.html

    An example:

    name: mySecurityRules
    class_path: stacker_blueprints.security_rules.SecurityGroupRules
    variables:
      IngressRules:
        All80ToWebserverGroup:
          CidrIp: 0.0.0.0/0
          FromPort: 80
          ToPort: 80
          GroupId: ${output WebserverStack::SecurityGroup}
          IpProtocol: tcp
    """

    VARIABLES = {
        "IngressRules": {
            "type": dict,
            "description": "A dict of ingress rules where the key is the "
                           "name of the rule to create, and the value is "
                           "a dictionary of keys/values based on the "
                           "attributes of the "
                           "troposphere.ec2.SecurityGroupIngress class.",
        },
        "EgressRules": {
            "type": dict,
            "description": "A dict of ingress rules where the key is the "
                           "name of the rule to create, and the value is "
                           "a dictionary of keys/values based on the "
                           "attributes of the "
                           "troposphere.ec2.SecurityGroupEgress class.",
        }
    }

    def create_template(self):
        t = self.template
        variables = self.get_variables()
        for rule_type, rule_class in CLASS_MAP.items():
            for rule_title, rule_attrs in variables[rule_type]:
                t.add_resource(rule_class.from_dict(rule_title, rule_attrs))

Add new, low-level security group rule blueprint
Add new, low-level security group rule blueprint

This should make it super simple to have a stack that
maintains security group rules on security groups built in other
stacks. Mostly useful for rules that glue two stacks together
(like adding a rule to allow instances in your webserver stack to
talk to your RDS database on the right port)
