// resourceAwsSecurityGroupExpandRules works in pair with
// resourceAwsSecurityGroupCollapseRules and is used as a
// workaround for the problem explained in
// https://github.com/terraform-providers/terraform-provider-aws/pull/4726
//
// This function converts every ingress/egress block that
// contains multiple rules to multiple blocks with only one
// rule. Doing a Difference operation on such a normalized
// set helps to avoid unnecessary removal of unchanged
// rules during the Apply step.
//
// For example, in terraform syntax, the following block:
//
// ingress {
//   from_port = 80
//   to_port = 80
//   protocol = "tcp"
//   cidr_blocks = [
//     "192.168.0.1/32",
//     "192.168.0.2/32",
//   ]
// }
//
// will be converted to the two blocks below:
//
// ingress {
//   from_port = 80
//   to_port = 80
//   protocol = "tcp"
//   cidr_blocks = [ "192.168.0.1/32" ]
// }
//
// ingress {
//   from_port = 80
//   to_port = 80
//   protocol = "tcp"
//   cidr_blocks = [ "192.168.0.2/32" ]
// }
//
// Then the Difference operation is executed on the new set
// to find which rules got modified, and the resulting set
// is then passed to resourceAwsSecurityGroupCollapseRules
// to convert the "diff" back to a more compact form for
// execution. Such compact form helps reduce the number of
// API calls.
//


This function converts every ingress/egress block that
contains multiple rules to multiple blocks with only one
rule. Doing a Difference operation on such a normalized
set helps to avoid unnecessary removal of unchanged
rules during the Apply step.

For example, in terraform syntax, the following block.



will be converted to the two blocks below.





Then the Difference operation is executed on the new set
to find which rules got modified, and the resulting set
is then passed to resourceAwsSecurityGroupCollapseRules
to convert the "diff" back to a more compact form for
execution. Such compact form helps reduce the number of
API calls.
// resourceAwsSecurityGroupExpandRules works in pair with // resourceAwsSecurityGroupCollapseRules and is used as a // workaround for the problem explained in // https : // github . com / terraform - providers / terraform - provider - aws / pull / 4726 // // This function converts every ingress / egress block that // contains multiple rules to multiple blocks with only one // rule . Doing a Difference operation on such a normalized // set helps to avoid unnecessary removal of unchanged // rules during the Apply step . // // For example in terraform syntax the following block : // // ingress { // from_port = 80 // to_port = 80 // protocol = " tcp " // cidr_blocks = [ // " 192 . 168 . 0 . 1 / 32 " // " 192 . 168 . 0 . 2 / 32 " // ] // } // // will be converted to the two blocks below : // // ingress { // from_port = 80 // to_port = 80 // protocol = " tcp " // cidr_blocks = [ " 192 . 168 . 0 . 1 / 32 " ] // } // // ingress { // from_port = 80 // to_port = 80 // protocol = " tcp " // cidr_blocks = [ " 192 . 168 . 0 . 2 / 32 " ] // } // // Then the Difference operation is executed on the new set // to find which rules got modified and the resulting set // is then passed to resourceAwsSecurityGroupCollapseRules // to convert the " diff " back to a more compact form for // execution . Such compact form helps reduce the number of // API calls . //
func resourceAwsSecurityGroupExpandRules(rules *schema.Set) *schema.Set {
	var keys_to_expand = []string{"cidr_blocks", "ipv6_cidr_blocks", "prefix_list_ids", "security_groups"}
	normalized := schema.NewSet(resourceAwsSecurityGroupRuleHash, nil)
	for _, rawRule := range rules.List() {
		rule := rawRule.(map[string]interface{})
		if v, ok := rule["self"]; ok && v.(bool) {
			new_rule := resourceAwsSecurityGroupCopyRule(rule, true, "", nil)
			normalized.Add(new_rule)
		}
		for _, key := range keys_to_expand {
			item, exists := rule[key]
			if exists {
				var list []interface{}
				if key == "security_groups" {
					list = item.(*schema.Set).List()
				} else {
					list = item.([]interface{})
				}
				for _, v := range list {
					var new_rule map[string]interface{}
					if key == "security_groups" {
						new_v := schema.NewSet(schema.HashString, nil)
						new_v.Add(v)
						new_rule = resourceAwsSecurityGroupCopyRule(rule, false, key, new_v)
					} else {
						new_v := make([]interface{}, 0)
						new_v = append(new_v, v)
						new_rule = resourceAwsSecurityGroupCopyRule(rule, false, key, new_v)
					}
					normalized.Add(new_rule)
				}
			}
		}
	}
	return normalized
}
func resourceAwsSecurityGroupExpandRules ( rules * schema . Set ) * schema . Set { var keys_to_expand = [ ] string { " " , " " , " " , " " } normalized := schema . NewSet ( resourceAwsSecurityGroupRuleHash , nil ) for _ , rawRule := range rules . List ( ) { rule := rawRule . ( map [ string ] interface { } ) if v , ok := rule [ " " ] ; ok && v . ( bool ) { new_rule := resourceAwsSecurityGroupCopyRule ( rule , true , " " , nil ) normalized . Add ( new_rule ) } for _ , key := range keys_to_expand { item , exists := rule [ key ] if exists { var list [ ] interface { } if key == " " { list = item . ( * schema . Set ) . List ( ) } else { list = item . ( [ ] interface { } ) } for _ , v := range list { var new_rule map [ string ] interface { } if key == " " { new_v := schema . NewSet ( schema . HashString , nil ) new_v . Add ( v ) new_rule = resourceAwsSecurityGroupCopyRule ( rule , false , key , new_v ) } else { new_v := make ( [ ] interface { } , 0 ) new_v = append ( new_v , v ) new_rule = resourceAwsSecurityGroupCopyRule ( rule , false , key , new_v ) } normalized . Add ( new_rule ) } } } } return normalized }