| package structured |
| |
| import ( |
| "github.com/hashicorp/terraform/internal/command/jsonformat/structured/attribute_path" |
| ) |
| |
| // ChangeSlice is a Change that represents a Tuple, Set, or List type, and has |
| // converted the relevant interfaces into slices for easier access. |
| type ChangeSlice struct { |
| // Before contains the value before the proposed change. |
| Before []interface{} |
| |
| // After contains the value after the proposed change. |
| After []interface{} |
| |
| // Unknown contains the unknown status of any elements of this list/set. |
| Unknown []interface{} |
| |
| // BeforeSensitive contains the before sensitive status of any elements of |
| //this list/set. |
| BeforeSensitive []interface{} |
| |
| // AfterSensitive contains the after sensitive status of any elements of |
| //this list/set. |
| AfterSensitive []interface{} |
| |
| // ReplacePaths matches the same attributes in Change exactly. |
| ReplacePaths attribute_path.Matcher |
| |
| // RelevantAttributes matches the same attributes in Change exactly. |
| RelevantAttributes attribute_path.Matcher |
| } |
| |
| // AsSlice converts the Change into a slice representation by converting the |
| // internal Before, After, Unknown, BeforeSensitive, and AfterSensitive data |
| // structures into generic slices. |
| func (change Change) AsSlice() ChangeSlice { |
| return ChangeSlice{ |
| Before: genericToSlice(change.Before), |
| After: genericToSlice(change.After), |
| Unknown: genericToSlice(change.Unknown), |
| BeforeSensitive: genericToSlice(change.BeforeSensitive), |
| AfterSensitive: genericToSlice(change.AfterSensitive), |
| ReplacePaths: change.ReplacePaths, |
| RelevantAttributes: change.RelevantAttributes, |
| } |
| } |
| |
| // GetChild safely packages up a Change object for the given child, handling |
| // all the cases where the data might be null or a static boolean. |
| func (s ChangeSlice) GetChild(beforeIx, afterIx int) Change { |
| before, beforeExplicit := getFromGenericSlice(s.Before, beforeIx) |
| after, afterExplicit := getFromGenericSlice(s.After, afterIx) |
| unknown, _ := getFromGenericSlice(s.Unknown, afterIx) |
| beforeSensitive, _ := getFromGenericSlice(s.BeforeSensitive, beforeIx) |
| afterSensitive, _ := getFromGenericSlice(s.AfterSensitive, afterIx) |
| |
| mostRelevantIx := beforeIx |
| if beforeIx < 0 || beforeIx >= len(s.Before) { |
| mostRelevantIx = afterIx |
| } |
| |
| return Change{ |
| BeforeExplicit: beforeExplicit, |
| AfterExplicit: afterExplicit, |
| Before: before, |
| After: after, |
| Unknown: unknown, |
| BeforeSensitive: beforeSensitive, |
| AfterSensitive: afterSensitive, |
| ReplacePaths: s.ReplacePaths.GetChildWithIndex(mostRelevantIx), |
| RelevantAttributes: s.RelevantAttributes.GetChildWithIndex(mostRelevantIx), |
| } |
| } |
| |
| func getFromGenericSlice(generic []interface{}, ix int) (interface{}, bool) { |
| if generic == nil { |
| return nil, false |
| } |
| if ix < 0 || ix >= len(generic) { |
| return nil, false |
| } |
| return generic[ix], true |
| } |
| |
| func genericToSlice(generic interface{}) []interface{} { |
| if concrete, ok := generic.([]interface{}); ok { |
| return concrete |
| } |
| return nil |
| } |