Skip to content

Commit

Permalink
Handle Output values in diffs (#682)
Browse files Browse the repository at this point in the history
* Handle Output values in diffs

The server-side diff based on a dryRun doesn't understand Pulumi
Outputs, so it would cause an error for any update that depended
a calculated value.

As a workaround, fallback to a client-side diff if a dryRun diff
returns an error.

* Fix hasComputedValue to handle nested slices
  • Loading branch information
lblackstone authored Aug 1, 2019
1 parent c0b4e12 commit 5d13254
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
### Bug fixes

- Properly reference override values in Python Helm SDK (https://github.com/pulumi/pulumi-kubernetes/pull/676).
- Handle Output values in diffs. (https://github.com/pulumi/pulumi-kubernetes/pull/682).

## 0.25.3 (July 29, 2019)

Expand Down
6 changes: 5 additions & 1 deletion pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,11 @@ func (k *kubeProvider) Diff(
var isInputPatch bool
var patchBase *unstructured.Unstructured

tryDryRun := supportsDryRun && oldInputs.GroupVersionKind().String() == gvk.String()
// TODO: Skipping dry run entirely for resources with computed values is a hack. We will want to address this
// more granularly so that previews are as accurate as possible, but this is an easy workaround for a critical
// bug.
tryDryRun := supportsDryRun && oldInputs.GroupVersionKind().String() == gvk.String() &&
!hasComputedValue(newInputs) && !hasComputedValue(oldInputs)
if tryDryRun {
patch, patchBase, err = k.dryRunPatch(oldInputs, newInputs)

Expand Down
12 changes: 9 additions & 3 deletions pkg/provider/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ func hasComputedValue(obj *unstructured.Unstructured) bool {
}
curr, objects = objects[0], objects[1:]
for _, v := range curr {
if _, isComputed := v.(resource.Computed); isComputed {
switch field := v.(type) {
case resource.Computed:
return true
}
if field, isMap := v.(map[string]interface{}); isMap {
case map[string]interface{}:
objects = append(objects, field)
case []interface{}:
for _, v := range field {
objects = append(objects, map[string]interface{}{"": v})
}
case []map[string]interface{}:
objects = append(objects, field...)
}
}
}
Expand Down
64 changes: 64 additions & 0 deletions pkg/provider/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,70 @@ func TestHasComputedValue(t *testing.T) {
}},
hasComputedValue: true,
},
{
name: "Object with nested slice of map[string]interface{} has a computed value",
obj: &unstructured.Unstructured{Object: map[string]interface{}{
"field1": 1,
"field2": []map[string]interface{}{
{"field3": resource.Computed{}},
},
}},
hasComputedValue: true,
},
{
name: "Object with nested slice of interface{} has a computed value",
obj: &unstructured.Unstructured{Object: map[string]interface{}{
"field1": 1,
"field2": []interface{}{
resource.Computed{},
},
}},
hasComputedValue: true,
},
{
name: "Object with nested slice of map[string]interface{} with nested slice of interface{} has a computed value",
obj: &unstructured.Unstructured{Object: map[string]interface{}{
"field1": 1,
"field2": []map[string]interface{}{
{"field3": []interface{}{
resource.Computed{},
}},
},
}},
hasComputedValue: true,
},
{
name: "Complex nested object with computed value",
obj: &unstructured.Unstructured{Object: map[string]interface{}{
"field1": 1,
"field2": []map[string]interface{}{
{"field3": []interface{}{
[]map[string]interface{}{
{"field4": []interface{}{
resource.Computed{},
}},
},
}},
},
}},
hasComputedValue: true,
},
{
name: "Complex nested object with no computed value",
obj: &unstructured.Unstructured{Object: map[string]interface{}{
"field1": 1,
"field2": []map[string]interface{}{
{"field3": []interface{}{
[]map[string]interface{}{
{"field4": []interface{}{
"field5",
}},
},
}},
},
}},
hasComputedValue: false,
},
}

for _, test := range tests {
Expand Down

0 comments on commit 5d13254

Please sign in to comment.