diff --git a/provider/pkg/provider/provider.go b/provider/pkg/provider/provider.go index 006bcc4472..1146176b63 100644 --- a/provider/pkg/provider/provider.go +++ b/provider/pkg/provider/provider.go @@ -1061,7 +1061,7 @@ func (p *cfnProvider) Update(ctx context.Context, req *pulumirpc.UpdateRequest) if customResource, ok := p.customResources[resourceToken]; ok { timeout := time.Duration(req.GetTimeout()) * time.Second // Custom resource - outputs, err = customResource.Update(ctx, urn, id, newInputs, oldInputs, timeout) + outputs, err = customResource.Update(ctx, urn, id, newInputs, oldInputs, oldState, timeout) if err != nil { return nil, err } @@ -1128,8 +1128,13 @@ func (p *cfnProvider) Delete(ctx context.Context, req *pulumirpc.DeleteRequest) return nil, errors.Wrapf(err, "failed to parse inputs for update") } + // Retrieve the state. + state, err := plugin.UnmarshalProperties(req.GetProperties(), plugin.MarshalOptions{ + Label: fmt.Sprintf("%s.state", label), KeepUnknowns: true, SkipNulls: true, KeepSecrets: true, + }) + timeout := time.Duration(req.GetTimeout()) * time.Second - err = customResource.Delete(ctx, urn, id, oldInputs, timeout) + err = customResource.Delete(ctx, urn, id, oldInputs, state, timeout) if err != nil { return nil, err } diff --git a/provider/pkg/provider/provider_test.go b/provider/pkg/provider/provider_test.go index fc2a979d83..0f54cd4c05 100644 --- a/provider/pkg/provider/provider_test.go +++ b/provider/pkg/provider/provider_test.go @@ -397,7 +397,7 @@ func TestUpdate(t *testing.T) { } t.Run("CustomResource", func(t *testing.T) { - mockCustomResource.EXPECT().Update(ctx, urn, "resource-id", gomock.Any(), gomock.Any(), 5*time.Minute).Return( + mockCustomResource.EXPECT().Update(ctx, urn, "resource-id", gomock.Any(), gomock.Any(), gomock.Any(), 5*time.Minute).Return( resource.PropertyMap{"foo": resource.NewStringProperty("bar")}, nil, ) @@ -410,7 +410,7 @@ func TestUpdate(t *testing.T) { }) t.Run("CustomResource/Error", func(t *testing.T) { - mockCustomResource.EXPECT().Update(ctx, urn, "resource-id", gomock.Any(), gomock.Any(), 5*time.Minute).Return( + mockCustomResource.EXPECT().Update(ctx, urn, "resource-id", gomock.Any(), gomock.Any(), gomock.Any(), 5*time.Minute).Return( nil, assert.AnError, ) @@ -509,14 +509,14 @@ func TestDelete(t *testing.T) { } t.Run("CustomResource", func(t *testing.T) { - mockCustomResource.EXPECT().Delete(ctx, urn, "resource-id", gomock.Any(), gomock.Any()).Return(nil) + mockCustomResource.EXPECT().Delete(ctx, urn, "resource-id", gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) _, err := provider.Delete(ctx, req) assert.NoError(t, err) }) t.Run("CustomResource/Error", func(t *testing.T) { - mockCustomResource.EXPECT().Delete(ctx, urn, "resource-id", gomock.Any(), gomock.Any()).Return(assert.AnError) + mockCustomResource.EXPECT().Delete(ctx, urn, "resource-id", gomock.Any(), gomock.Any(), gomock.Any()).Return(assert.AnError) _, err := provider.Delete(ctx, req) assert.Error(t, err) diff --git a/provider/pkg/resources/custom.go b/provider/pkg/resources/custom.go index b25a6214e2..f730772ed8 100644 --- a/provider/pkg/resources/custom.go +++ b/provider/pkg/resources/custom.go @@ -18,7 +18,7 @@ type CustomResource interface { // Read returns the outputs and the updated inputs of the resource. Read(ctx context.Context, urn resource.URN, id string, oldInputs, oldOutputs resource.PropertyMap) (outputs resource.PropertyMap, inputs resource.PropertyMap, exists bool, err error) // Update applies the diff of the inputs to the resource and returns the updated outputs. - Update(ctx context.Context, urn resource.URN, id string, inputs, oldInputs resource.PropertyMap, timeout time.Duration) (resource.PropertyMap, error) + Update(ctx context.Context, urn resource.URN, id string, inputs, oldInputs, state resource.PropertyMap, timeout time.Duration) (resource.PropertyMap, error) // Delete removes the resource from the cloud provider. - Delete(ctx context.Context, urn resource.URN, id string, inputs resource.PropertyMap, timeout time.Duration) error + Delete(ctx context.Context, urn resource.URN, id string, inputs, state resource.PropertyMap, timeout time.Duration) error } diff --git a/provider/pkg/resources/extension_resource.go b/provider/pkg/resources/extension_resource.go index 5f20ab970b..bcaf7d5dd0 100644 --- a/provider/pkg/resources/extension_resource.go +++ b/provider/pkg/resources/extension_resource.go @@ -167,7 +167,7 @@ func (r *extensionResource) Read(ctx context.Context, urn resource.URN, id strin return CheckpointObject(newInputs, rawState), newInputs, true, nil } -func (r *extensionResource) Update(ctx context.Context, urn resource.URN, id string, inputs resource.PropertyMap, oldInputs resource.PropertyMap, timeout time.Duration) (resource.PropertyMap, error) { +func (r *extensionResource) Update(ctx context.Context, urn resource.URN, id string, inputs, oldInputs, state resource.PropertyMap, timeout time.Duration) (resource.PropertyMap, error) { var typedOldInputs ExtensionResourceInputs _, err := resourcex.Unmarshal(&typedOldInputs, oldInputs, resourcex.UnmarshalOptions{}) if err != nil { @@ -198,7 +198,7 @@ func (r *extensionResource) Update(ctx context.Context, urn resource.URN, id str return CheckpointObject(inputs, rawState), nil } -func (r *extensionResource) Delete(ctx context.Context, urn resource.URN, id string, inputs resource.PropertyMap, timeout time.Duration) error { +func (r *extensionResource) Delete(ctx context.Context, urn resource.URN, id string, inputs, state resource.PropertyMap, timeout time.Duration) error { var typedInputs ExtensionResourceInputs _, err := resourcex.Unmarshal(&typedInputs, inputs, resourcex.UnmarshalOptions{}) if err != nil { diff --git a/provider/pkg/resources/mock_custom_resource.go b/provider/pkg/resources/mock_custom_resource.go index 756b1f85ec..e778268c8f 100644 --- a/provider/pkg/resources/mock_custom_resource.go +++ b/provider/pkg/resources/mock_custom_resource.go @@ -75,17 +75,17 @@ func (mr *MockCustomResourceMockRecorder) Create(ctx, urn, inputs, timeout any) } // Delete mocks base method. -func (m *MockCustomResource) Delete(ctx context.Context, urn resource.URN, id string, inputs resource.PropertyMap, timeout time.Duration) error { +func (m *MockCustomResource) Delete(ctx context.Context, urn resource.URN, id string, inputs, state resource.PropertyMap, timeout time.Duration) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Delete", ctx, urn, id, inputs, timeout) + ret := m.ctrl.Call(m, "Delete", ctx, urn, id, inputs, state, timeout) ret0, _ := ret[0].(error) return ret0 } // Delete indicates an expected call of Delete. -func (mr *MockCustomResourceMockRecorder) Delete(ctx, urn, id, inputs, timeout any) *gomock.Call { +func (mr *MockCustomResourceMockRecorder) Delete(ctx, urn, id, inputs, state, timeout any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockCustomResource)(nil).Delete), ctx, urn, id, inputs, timeout) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockCustomResource)(nil).Delete), ctx, urn, id, inputs, state, timeout) } // Read mocks base method. @@ -106,16 +106,16 @@ func (mr *MockCustomResourceMockRecorder) Read(ctx, urn, id, oldInputs, oldOutpu } // Update mocks base method. -func (m *MockCustomResource) Update(ctx context.Context, urn resource.URN, id string, inputs, oldInputs resource.PropertyMap, timeout time.Duration) (resource.PropertyMap, error) { +func (m *MockCustomResource) Update(ctx context.Context, urn resource.URN, id string, inputs, oldInputs, state resource.PropertyMap, timeout time.Duration) (resource.PropertyMap, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Update", ctx, urn, id, inputs, oldInputs, timeout) + ret := m.ctrl.Call(m, "Update", ctx, urn, id, inputs, oldInputs, state, timeout) ret0, _ := ret[0].(resource.PropertyMap) ret1, _ := ret[1].(error) return ret0, ret1 } // Update indicates an expected call of Update. -func (mr *MockCustomResourceMockRecorder) Update(ctx, urn, id, inputs, oldInputs, timeout any) *gomock.Call { +func (mr *MockCustomResourceMockRecorder) Update(ctx, urn, id, inputs, oldInputs, state, timeout any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockCustomResource)(nil).Update), ctx, urn, id, inputs, oldInputs, timeout) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockCustomResource)(nil).Update), ctx, urn, id, inputs, oldInputs, state, timeout) }