jsonplan: remove "proposed_unknown" structure in favor of "after_unknown" field in "change" (#19709)
* jsonplan: remove "proposed_unknown" structure in favor of "after_unknown" field in "change"
This commit is contained in:
parent
364d3ffc4a
commit
2b6dc13f29
|
@ -27,7 +27,6 @@ const FormatVersion = "0.1"
|
||||||
type plan struct {
|
type plan struct {
|
||||||
FormatVersion string `json:"format_version,omitempty"`
|
FormatVersion string `json:"format_version,omitempty"`
|
||||||
PlannedValues stateValues `json:"planned_values,omitempty"`
|
PlannedValues stateValues `json:"planned_values,omitempty"`
|
||||||
ProposedUnknown stateValues `json:"proposed_unknown,omitempty"`
|
|
||||||
ResourceChanges []resourceChange `json:"resource_changes,omitempty"`
|
ResourceChanges []resourceChange `json:"resource_changes,omitempty"`
|
||||||
OutputChanges map[string]change `json:"output_changes,omitempty"`
|
OutputChanges map[string]change `json:"output_changes,omitempty"`
|
||||||
PriorState json.RawMessage `json:"prior_state,omitempty"`
|
PriorState json.RawMessage `json:"prior_state,omitempty"`
|
||||||
|
@ -62,8 +61,9 @@ type change struct {
|
||||||
// or "after" is unset (respectively). For ["no-op"], the before and after
|
// or "after" is unset (respectively). For ["no-op"], the before and after
|
||||||
// values are identical. The "after" value will be incomplete if there are
|
// values are identical. The "after" value will be incomplete if there are
|
||||||
// values within it that won't be known until after apply.
|
// values within it that won't be known until after apply.
|
||||||
Before json.RawMessage `json:"before,omitempty"`
|
Before json.RawMessage `json:"before,omitempty"`
|
||||||
After json.RawMessage `json:"after,omitempty"`
|
After json.RawMessage `json:"after,omitempty"`
|
||||||
|
AfterUnknown json.RawMessage `json:"after_unknown,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type output struct {
|
type output struct {
|
||||||
|
@ -81,7 +81,7 @@ func Marshal(
|
||||||
|
|
||||||
output := newPlan()
|
output := newPlan()
|
||||||
|
|
||||||
// marshalPlannedValues populates both PlannedValues and ProposedUnknowns
|
// output.PlannedValues
|
||||||
err := output.marshalPlannedValues(p.Changes, schemas)
|
err := output.marshalPlannedValues(p.Changes, schemas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error in marshalPlannedValues: %s", err)
|
return nil, fmt.Errorf("error in marshalPlannedValues: %s", err)
|
||||||
|
@ -157,16 +157,36 @@ func (p *plan) marshalResourceChanges(changes *plans.Changes, schemas *terraform
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// TODO: what is the expected value if after is not known?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterUnknown, _ := cty.Transform(changeV.After, func(path cty.Path, val cty.Value) (cty.Value, error) {
|
||||||
|
if val.IsNull() {
|
||||||
|
return cty.False, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !val.Type().IsPrimitiveType() {
|
||||||
|
return val, nil // just pass through non-primitives; they already contain our transform results
|
||||||
|
}
|
||||||
|
|
||||||
|
if val.IsKnown() {
|
||||||
|
// null rather than false here so that known values
|
||||||
|
// don't appear at all in JSON serialization of our result
|
||||||
|
return cty.False, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return cty.True, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
a, _ := ctyjson.Marshal(afterUnknown, afterUnknown.Type())
|
||||||
|
|
||||||
r.Change = change{
|
r.Change = change{
|
||||||
Actions: []string{rc.Action.String()},
|
Actions: []string{rc.Action.String()},
|
||||||
Before: json.RawMessage(before),
|
Before: json.RawMessage(before),
|
||||||
After: json.RawMessage(after),
|
After: json.RawMessage(after),
|
||||||
|
AfterUnknown: a,
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Deposed = rc.DeposedKey == states.NotDeposed
|
r.Deposed = rc.DeposedKey == states.NotDeposed
|
||||||
|
|
||||||
key := addr.Resource.Key
|
key := addr.Resource.Key
|
||||||
|
@ -207,6 +227,7 @@ func (p *plan) marshalOutputChanges(changes *plans.Changes) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var before, after []byte
|
var before, after []byte
|
||||||
|
afterUnknown := cty.False
|
||||||
if changeV.Before != cty.NilVal {
|
if changeV.Before != cty.NilVal {
|
||||||
before, err = ctyjson.Marshal(changeV.Before, changeV.Before.Type())
|
before, err = ctyjson.Marshal(changeV.Before, changeV.Before.Type())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -219,13 +240,20 @@ func (p *plan) marshalOutputChanges(changes *plans.Changes) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
afterUnknown = cty.True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var c change
|
a, _ := ctyjson.Marshal(afterUnknown, afterUnknown.Type())
|
||||||
c.Actions = []string{oc.Action.String()}
|
|
||||||
c.Before = json.RawMessage(before)
|
c := change{
|
||||||
c.After = json.RawMessage(after)
|
Actions: []string{oc.Action.String()},
|
||||||
|
Before: json.RawMessage(before),
|
||||||
|
After: json.RawMessage(after),
|
||||||
|
AfterUnknown: a,
|
||||||
|
}
|
||||||
|
|
||||||
p.OutputChanges[oc.Addr.OutputValue.Name] = c
|
p.OutputChanges[oc.Addr.OutputValue.Name] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,20 +262,18 @@ func (p *plan) marshalOutputChanges(changes *plans.Changes) error {
|
||||||
|
|
||||||
func (p *plan) marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) error {
|
func (p *plan) marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) error {
|
||||||
// marshal the planned changes into a module
|
// marshal the planned changes into a module
|
||||||
plan, unknownValues, err := marshalPlannedValues(changes, schemas)
|
plan, err := marshalPlannedValues(changes, schemas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.PlannedValues.RootModule = plan
|
p.PlannedValues.RootModule = plan
|
||||||
p.ProposedUnknown.RootModule = unknownValues
|
|
||||||
|
|
||||||
// marshalPlannedOutputs
|
// marshalPlannedOutputs
|
||||||
outputs, unknownOutputs, err := marshalPlannedOutputs(changes)
|
outputs, err := marshalPlannedOutputs(changes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.PlannedValues.Outputs = outputs
|
p.PlannedValues.Outputs = outputs
|
||||||
p.ProposedUnknown.Outputs = unknownOutputs
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,33 +35,16 @@ func marshalAttributeValues(value cty.Value, schema *configschema.Block) attribu
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalAttributeValuesBool returns an attributeValues structure with "true" and
|
|
||||||
// "false" in place of the values indicating whether the value is known or not.
|
|
||||||
func marshalAttributeValuesBool(value cty.Value, schema *configschema.Block) attributeValues {
|
|
||||||
ret := make(attributeValues)
|
|
||||||
|
|
||||||
it := value.ElementIterator()
|
|
||||||
for it.Next() {
|
|
||||||
k, v := it.Element()
|
|
||||||
if v.IsWhollyKnown() {
|
|
||||||
ret[k.AsString()] = "true"
|
|
||||||
}
|
|
||||||
ret[k.AsString()] = "false"
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// marshalPlannedOutputs takes a list of changes and returns two output maps,
|
// marshalPlannedOutputs takes a list of changes and returns two output maps,
|
||||||
// the former with output values and the latter with true/false in place of
|
// the former with output values and the latter with true/false in place of
|
||||||
// values indicating whether the values are known at plan time.
|
// values indicating whether the values are known at plan time.
|
||||||
func marshalPlannedOutputs(changes *plans.Changes) (map[string]output, map[string]output, error) {
|
func marshalPlannedOutputs(changes *plans.Changes) (map[string]output, error) {
|
||||||
if changes.Outputs == nil {
|
if changes.Outputs == nil {
|
||||||
// No changes - we're done here!
|
// No changes - we're done here!
|
||||||
return nil, nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := make(map[string]output)
|
ret := make(map[string]output)
|
||||||
uRet := make(map[string]output)
|
|
||||||
|
|
||||||
for _, oc := range changes.Outputs {
|
for _, oc := range changes.Outputs {
|
||||||
if oc.ChangeSrc.Action == plans.Delete {
|
if oc.ChangeSrc.Action == plans.Delete {
|
||||||
|
@ -71,23 +54,14 @@ func marshalPlannedOutputs(changes *plans.Changes) (map[string]output, map[strin
|
||||||
var after []byte
|
var after []byte
|
||||||
changeV, err := oc.Decode()
|
changeV, err := oc.Decode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, uRet, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if changeV.After != cty.NilVal {
|
if changeV.After != cty.NilVal {
|
||||||
if changeV.After.IsWhollyKnown() {
|
if changeV.After.IsWhollyKnown() {
|
||||||
after, err = ctyjson.Marshal(changeV.After, changeV.After.Type())
|
after, err = ctyjson.Marshal(changeV.After, changeV.After.Type())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, uRet, err
|
return ret, err
|
||||||
}
|
|
||||||
uRet[oc.Addr.OutputValue.Name] = output{
|
|
||||||
Value: json.RawMessage("true"),
|
|
||||||
Sensitive: oc.Sensitive,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uRet[oc.Addr.OutputValue.Name] = output{
|
|
||||||
Value: json.RawMessage("false"),
|
|
||||||
Sensitive: oc.Sensitive,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,17 +72,14 @@ func marshalPlannedOutputs(changes *plans.Changes) (map[string]output, map[strin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, uRet, nil
|
return ret, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalPlannedValues returns two modules:
|
func marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) (module, error) {
|
||||||
// The former has attribute values populated and the latter has true/false in
|
var ret module
|
||||||
// place of values indicating whether the values are known at plan time.
|
|
||||||
func marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) (module, module, error) {
|
|
||||||
var ret, uRet module
|
|
||||||
if changes.Empty() {
|
if changes.Empty() {
|
||||||
return ret, uRet, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// build two maps:
|
// build two maps:
|
||||||
|
@ -132,27 +103,26 @@ func marshalPlannedValues(changes *plans.Changes, schemas *terraform.Schemas) (m
|
||||||
}
|
}
|
||||||
|
|
||||||
// start with the root module
|
// start with the root module
|
||||||
resources, uResources, err := marshalPlanResources(changes, moduleResourceMap[""], schemas)
|
resources, err := marshalPlanResources(changes, moduleResourceMap[""], schemas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, uRet, err
|
return ret, err
|
||||||
}
|
}
|
||||||
ret.Resources = resources
|
ret.Resources = resources
|
||||||
uRet.Resources = uResources
|
|
||||||
|
|
||||||
childModules, err := marshalPlanModules(changes, schemas, moduleMap[""], moduleMap, moduleResourceMap)
|
childModules, err := marshalPlanModules(changes, schemas, moduleMap[""], moduleMap, moduleResourceMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, uRet, err
|
return ret, err
|
||||||
}
|
}
|
||||||
ret.ChildModules = childModules
|
ret.ChildModules = childModules
|
||||||
|
|
||||||
return ret, uRet, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalPlannedValues returns two resource slices:
|
// marshalPlannedValues returns two resource slices:
|
||||||
// The former has attribute values populated and the latter has true/false in
|
// The former has attribute values populated and the latter has true/false in
|
||||||
// place of values indicating whether the values are known at plan time.
|
// place of values indicating whether the values are known at plan time.
|
||||||
func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstance, schemas *terraform.Schemas) ([]resource, []resource, error) {
|
func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstance, schemas *terraform.Schemas) ([]resource, error) {
|
||||||
var ret, uRet []resource
|
var ret []resource
|
||||||
|
|
||||||
for _, ri := range ris {
|
for _, ri := range ris {
|
||||||
r := changes.ResourceInstance(ri)
|
r := changes.ResourceInstance(ri)
|
||||||
|
@ -174,7 +144,7 @@ func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstanc
|
||||||
case addrs.DataResourceMode:
|
case addrs.DataResourceMode:
|
||||||
resource.Mode = "data"
|
resource.Mode = "data"
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("resource %s has an unsupported mode %s",
|
return nil, fmt.Errorf("resource %s has an unsupported mode %s",
|
||||||
r.Addr.String(),
|
r.Addr.String(),
|
||||||
r.Addr.Resource.Resource.Mode.String(),
|
r.Addr.Resource.Resource.Mode.String(),
|
||||||
)
|
)
|
||||||
|
@ -186,30 +156,24 @@ func marshalPlanResources(changes *plans.Changes, ris []addrs.AbsResourceInstanc
|
||||||
resource.Type,
|
resource.Type,
|
||||||
)
|
)
|
||||||
if schema == nil {
|
if schema == nil {
|
||||||
return nil, nil, fmt.Errorf("no schema found for %s", r.Addr.String())
|
return nil, fmt.Errorf("no schema found for %s", r.Addr.String())
|
||||||
}
|
}
|
||||||
resource.SchemaVersion = schemaVer
|
resource.SchemaVersion = schemaVer
|
||||||
changeV, err := r.Decode(schema.ImpliedType())
|
changeV, err := r.Decode(schema.ImpliedType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var unknownAttributeValues attributeValues
|
|
||||||
if changeV.After != cty.NilVal {
|
if changeV.After != cty.NilVal {
|
||||||
if changeV.After.IsWhollyKnown() {
|
if changeV.After.IsWhollyKnown() {
|
||||||
resource.AttributeValues = marshalAttributeValues(changeV.After, schema)
|
resource.AttributeValues = marshalAttributeValues(changeV.After, schema)
|
||||||
}
|
}
|
||||||
unknownAttributeValues = marshalAttributeValuesBool(changeV.After, schema)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uResource := resource
|
|
||||||
uResource.AttributeValues = unknownAttributeValues
|
|
||||||
|
|
||||||
ret = append(ret, resource)
|
ret = append(ret, resource)
|
||||||
uRet = append(uRet, uResource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, uRet, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// marshalPlanModules iterates over a list of modules to recursively describe
|
// marshalPlanModules iterates over a list of modules to recursively describe
|
||||||
|
@ -232,7 +196,7 @@ func marshalPlanModules(
|
||||||
if child.String() != "" {
|
if child.String() != "" {
|
||||||
cm.Address = child.String()
|
cm.Address = child.String()
|
||||||
}
|
}
|
||||||
rs, _, err := marshalPlanResources(changes, moduleResources, schemas)
|
rs, err := marshalPlanResources(changes, moduleResources, schemas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue