mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Add support for the replace paths data in the structured renderer (#32392)
* prep for processing the structured run output * undo unwanted change to a json key * Add skeleton functions and API for refactored renderer * goimports * Fix documentation of the RenderOpts struct * Add rendering functionality for primitives to the structured renderer * add test case for override * Add support for parsing and rendering sensitive values in the renderer * Add support for unknown/computed values in the structured renderer * delete missing unit tests * Add support for object attributes in the structured renderer * goimports * Add support for the replace paths data in the structured renderer
This commit is contained in:
parent
1eebcf875f
commit
b097d8873d
@ -82,7 +82,7 @@ type Value struct {
|
|||||||
// ReplacePaths generally contains nested slices that describe paths to
|
// ReplacePaths generally contains nested slices that describe paths to
|
||||||
// elements or attributes that are causing the overall resource to be
|
// elements or attributes that are causing the overall resource to be
|
||||||
// replaced.
|
// replaced.
|
||||||
ReplacePaths interface{}
|
ReplacePaths []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueFromJsonChange unmarshals the raw []byte values in the jsonplan.Change
|
// ValueFromJsonChange unmarshals the raw []byte values in the jsonplan.Change
|
||||||
@ -94,7 +94,7 @@ func ValueFromJsonChange(change jsonplan.Change) Value {
|
|||||||
Unknown: unmarshalGeneric(change.AfterUnknown),
|
Unknown: unmarshalGeneric(change.AfterUnknown),
|
||||||
BeforeSensitive: unmarshalGeneric(change.BeforeSensitive),
|
BeforeSensitive: unmarshalGeneric(change.BeforeSensitive),
|
||||||
AfterSensitive: unmarshalGeneric(change.AfterSensitive),
|
AfterSensitive: unmarshalGeneric(change.AfterSensitive),
|
||||||
ReplacePaths: unmarshalGeneric(change.ReplacePaths),
|
ReplacePaths: decodePaths(unmarshalGeneric(change.ReplacePaths)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,8 +129,10 @@ func (v Value) AsChange(renderer change.Renderer) change.Change {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) replacePath() bool {
|
func (v Value) replacePath() bool {
|
||||||
if replace, ok := v.ReplacePaths.(bool); ok {
|
for _, path := range v.ReplacePaths {
|
||||||
return replace
|
if len(path.([]interface{})) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -198,3 +200,10 @@ func unmarshalGeneric(raw json.RawMessage) interface{} {
|
|||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodePaths(paths interface{}) []interface{} {
|
||||||
|
if paths == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return paths.([]interface{})
|
||||||
|
}
|
||||||
|
@ -20,6 +20,9 @@ type ValueMap struct {
|
|||||||
// AfterSensitive contains the after sensitive status of any
|
// AfterSensitive contains the after sensitive status of any
|
||||||
// elements/attributes of this map/object.
|
// elements/attributes of this map/object.
|
||||||
AfterSensitive map[string]interface{}
|
AfterSensitive map[string]interface{}
|
||||||
|
|
||||||
|
// ReplacePaths matches the same attributes in Value exactly.
|
||||||
|
ReplacePaths []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Value) asMap() ValueMap {
|
func (v Value) asMap() ValueMap {
|
||||||
@ -29,6 +32,7 @@ func (v Value) asMap() ValueMap {
|
|||||||
Unknown: genericToMap(v.Unknown),
|
Unknown: genericToMap(v.Unknown),
|
||||||
BeforeSensitive: genericToMap(v.BeforeSensitive),
|
BeforeSensitive: genericToMap(v.BeforeSensitive),
|
||||||
AfterSensitive: genericToMap(v.AfterSensitive),
|
AfterSensitive: genericToMap(v.AfterSensitive),
|
||||||
|
ReplacePaths: v.ReplacePaths,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +51,26 @@ func (m ValueMap) getChild(key string) Value {
|
|||||||
Unknown: unknown,
|
Unknown: unknown,
|
||||||
BeforeSensitive: beforeSensitive,
|
BeforeSensitive: beforeSensitive,
|
||||||
AfterSensitive: afterSensitive,
|
AfterSensitive: afterSensitive,
|
||||||
|
ReplacePaths: m.processReplacePaths(key),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m ValueMap) processReplacePaths(key string) []interface{} {
|
||||||
|
var ret []interface{}
|
||||||
|
for _, p := range m.ReplacePaths {
|
||||||
|
path := p.([]interface{})
|
||||||
|
|
||||||
|
if len(path) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if path[0].(string) == key {
|
||||||
|
ret = append(ret, path[1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func getFromGenericMap(generic map[string]interface{}, key string) (interface{}, bool) {
|
func getFromGenericMap(generic map[string]interface{}, key string) (interface{}, bool) {
|
||||||
if generic == nil {
|
if generic == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -317,6 +317,48 @@ func TestValue_ObjectAttributes(t *testing.T) {
|
|||||||
validateAction: plans.NoOp,
|
validateAction: plans.NoOp,
|
||||||
validateReplace: false,
|
validateReplace: false,
|
||||||
},
|
},
|
||||||
|
"object_update_replace_self": {
|
||||||
|
input: Value{
|
||||||
|
Before: map[string]interface{}{
|
||||||
|
"attribute_one": "old",
|
||||||
|
},
|
||||||
|
After: map[string]interface{}{
|
||||||
|
"attribute_one": "new",
|
||||||
|
},
|
||||||
|
ReplacePaths: []interface{}{
|
||||||
|
[]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributes: map[string]cty.Type{
|
||||||
|
"attribute_one": cty.String,
|
||||||
|
},
|
||||||
|
validateChanges: map[string]change.ValidateChangeFunc{
|
||||||
|
"attribute_one": change.ValidatePrimitive(strptr("\"old\""), strptr("\"new\""), plans.Update, false),
|
||||||
|
},
|
||||||
|
validateAction: plans.Update,
|
||||||
|
validateReplace: true,
|
||||||
|
},
|
||||||
|
"object_update_replace_attribute": {
|
||||||
|
input: Value{
|
||||||
|
Before: map[string]interface{}{
|
||||||
|
"attribute_one": "old",
|
||||||
|
},
|
||||||
|
After: map[string]interface{}{
|
||||||
|
"attribute_one": "new",
|
||||||
|
},
|
||||||
|
ReplacePaths: []interface{}{
|
||||||
|
[]interface{}{"attribute_one"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attributes: map[string]cty.Type{
|
||||||
|
"attribute_one": cty.String,
|
||||||
|
},
|
||||||
|
validateChanges: map[string]change.ValidateChangeFunc{
|
||||||
|
"attribute_one": change.ValidatePrimitive(strptr("\"old\""), strptr("\"new\""), plans.Update, true),
|
||||||
|
},
|
||||||
|
validateAction: plans.Update,
|
||||||
|
validateReplace: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range tcs {
|
for name, tc := range tcs {
|
||||||
@ -484,6 +526,19 @@ func TestValue_Attribute(t *testing.T) {
|
|||||||
},
|
},
|
||||||
validateChange: change.ValidateComputed(change.ValidatePrimitive(strptr("\"old\""), nil, plans.Delete, false), plans.Update, false),
|
validateChange: change.ValidateComputed(change.ValidatePrimitive(strptr("\"old\""), nil, plans.Delete, false), plans.Update, false),
|
||||||
},
|
},
|
||||||
|
"primitive_update_replace": {
|
||||||
|
input: Value{
|
||||||
|
Before: "old",
|
||||||
|
After: "new",
|
||||||
|
ReplacePaths: []interface{}{
|
||||||
|
[]interface{}{}, // An empty path suggests this attribute should be true.
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attribute: &jsonprovider.Attribute{
|
||||||
|
AttributeType: unmarshalType(t, cty.String),
|
||||||
|
},
|
||||||
|
validateChange: change.ValidatePrimitive(strptr("\"old\""), strptr("\"new\""), plans.Update, true),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for name, tc := range tcs {
|
for name, tc := range tcs {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user