func recursiveUpdate()

in types/hcl.go [157:258]


func recursiveUpdate(old *hclwrite.Block, new *hclwrite.Block, before interface{}, after interface{}) {
	// user can't use patch resource to add item to some array, so we don't need to deal with before or after is an array
	beforeMap, ok1 := before.(map[string]interface{})
	afterMap, ok2 := after.(map[string]interface{})
	if !ok1 || !ok2 {
		return
	}
	attrs := make(map[string]bool)
	for attrName := range new.Body().Attributes() {
		attrs[attrName] = true
	}
	for attrName := range old.Body().Attributes() {
		attrs[attrName] = true
	}

	for attrName := range attrs {
		if !reflect.DeepEqual(beforeMap[attrName], afterMap[attrName]) {
			// add
			if beforeMap[attrName] != nil && afterMap[attrName] == nil {
				old.Body().SetAttributeRaw(attrName, new.Body().GetAttribute(attrName).Expr().BuildTokens(nil))
				continue
			}
			// delete
			if beforeMap[attrName] == nil && afterMap[attrName] != nil {
				old.Body().RemoveAttribute(attrName)
				continue
			}

			// update
			if new.Body().GetAttribute(attrName) == nil {
				continue
			}
			old.Body().SetAttributeRaw(attrName, new.Body().GetAttribute(attrName).Expr().BuildTokens(nil))
		}
	}

	blocks := make(map[string]bool)
	for _, block := range new.Body().Blocks() {
		blocks[block.Type()] = true
	}
	for _, block := range old.Body().Blocks() {
		blocks[block.Type()] = true
	}
	for blockName := range blocks {
		if !reflect.DeepEqual(beforeMap[blockName], afterMap[blockName]) {
			oldBlocks := make([]*hclwrite.Block, 0)
			for _, block := range old.Body().Blocks() {
				if block.Type() == blockName {
					oldBlocks = append(oldBlocks, block)
				}
			}
			newBlocks := make([]*hclwrite.Block, 0)
			for _, block := range new.Body().Blocks() {
				if block.Type() == blockName {
					newBlocks = append(newBlocks, block)
				}
			}

			// add
			if len(newBlocks) != 0 && len(oldBlocks) == 0 {
				for _, block := range newBlocks {
					old.Body().AppendBlock(block)
				}
				continue
			}
			// delete
			if len(newBlocks) == 0 && len(oldBlocks) != 0 {
				for _, block := range oldBlocks {
					old.Body().RemoveBlock(block)
				}
				continue
			}

			// update
			if len(newBlocks) == len(oldBlocks) {
				beforeArr := make([]interface{}, 0)
				afterArr := make([]interface{}, 0)
				if beforeMap[blockName] != nil {
					temp, _ := beforeMap[blockName].([]interface{})
					beforeArr = temp
				}
				if afterMap[blockName] != nil {
					temp, _ := afterMap[blockName].([]interface{})
					afterArr = temp
				}
				if len(beforeArr) != len(afterArr) && len(beforeArr) != len(oldBlocks) {
					log.Fatal()
				}
				for index := range newBlocks {
					recursiveUpdate(oldBlocks[index], newBlocks[index], beforeArr[index], afterArr[index])
				}
			} else {
				for _, block := range oldBlocks {
					old.Body().RemoveBlock(block)
				}
				for _, block := range newBlocks {
					old.Body().AppendBlock(block)
				}
			}
		}
	}
}