terraform/plan-test/lib.go (97 lines of code) (raw):
package test
import (
"encoding/json"
"fmt"
tfjson "github.com/hashicorp/terraform-json"
"io/ioutil"
"regexp"
)
func getActionType(actions *tfjson.Actions) string {
switch {
case actions.NoOp():
return string(tfjson.ActionNoop)
case actions.Create():
return string(tfjson.ActionCreate)
case actions.Read():
return string(tfjson.ActionRead)
case actions.Update():
return string(tfjson.ActionUpdate)
case actions.Delete():
return string(tfjson.ActionDelete)
case actions.CreateBeforeDestroy():
return "create-before-destroy"
case actions.DestroyBeforeCreate():
return "destroy-before-create"
case actions.Replace():
return "replace"
default:
panic("detected a non-existent Action")
}
}
func parsePlanJson(planFilePath string) (*tfjson.Plan, error) {
planJson, err := ioutil.ReadFile(planFilePath)
if err != nil {
return nil, fmt.Errorf("fail open %v: %v", planFilePath, err)
}
plan := tfjson.Plan{}
if err := json.Unmarshal(planJson, &plan); err != nil {
return nil, fmt.Errorf("fail parse %v: %v", planFilePath, err)
}
return &plan, nil
}
func getResourceChanges(plan *tfjson.Plan) map[string]*tfjson.ResourceChange {
resourceChanges := map[string]*tfjson.ResourceChange{}
for _, change := range plan.ResourceChanges {
resourceChanges[change.Address] = change
}
return resourceChanges
}
func getActions(resourceChanges map[string]*tfjson.ResourceChange) map[string][]string {
actions := map[string][]string{}
for _, resource := range resourceChanges {
action := getActionType(&resource.Change.Actions)
if _, ok := actions[action]; ok {
actions[action] = append(actions[action], resource.Address)
} else {
actions[action] = []string{resource.Address}
}
}
return actions
}
func searchAction(resourceChanges map[string]*tfjson.ResourceChange, actionType tfjson.Action) []string {
// 特定のActionがあるかどうか
actions := getActions(resourceChanges)
if _, ok := actions[string(actionType)]; ok {
return actions[string(actionType)]
}
return nil
}
func searchResourceType(resourceChanges map[string]*tfjson.ResourceChange, resourceType string) (map[string][]tfjson.ResourceChange, map[string][]tfjson.ResourceChange) {
foundTypes := map[string][]tfjson.ResourceChange{}
withoutTypes := map[string][]tfjson.ResourceChange{}
for _, resource := range resourceChanges {
if resource.Change.Actions.NoOp() {
continue
}
if regexp.MustCompile(resourceType).Match([]byte(resource.Type)) {
foundTypes[resource.Type] = append(foundTypes[resourceType], *resource)
} else {
withoutTypes[resource.Type] = append(withoutTypes[resourceType], *resource)
}
}
return foundTypes, withoutTypes
}
func searchResourceModule(resourceChanges map[string]*tfjson.ResourceChange, resourceModule string) (map[string][]tfjson.ResourceChange, map[string][]tfjson.ResourceChange) {
foundModule := map[string][]tfjson.ResourceChange{}
withoutModule := map[string][]tfjson.ResourceChange{}
for _, resource := range resourceChanges {
if resource.Change.Actions.NoOp() {
continue
}
if regexp.MustCompile(resourceModule).Match([]byte(resource.ModuleAddress)) {
foundModule[resource.Type] = append(foundModule[resourceModule], *resource)
} else {
withoutModule[resource.Type] = append(withoutModule[resourceModule], *resource)
}
}
return foundModule, withoutModule
}