@@ -26,12 +26,18 @@ type IResource interface {
2626 // Example: func (*ResourceJob) PrepareState(input *resources.Job) *jobs.JobSettings
2727 PrepareState (input any ) any
2828
29+ // [Required if type(remoteState) != type(state)] RemapState adapts remote state to local state type.
30+ // The adapted remote state will then be compared with newState to detect remote drift.
31+ // Adaptation is not necessary (but possible) if types already match.
32+ // Example: func (*ResourceJob) RemapState(jobs *jobs.Job) *jobs.JobSettings
33+ RemapState (input any ) any
34+
2935 // DoRefresh reads and returns remote state from the backend. The return type defines schema for remote field resolution.
30- // Example: func (r *ResourceJob) DoRefresh(ctx context.Context, id string) (*jobs.Job, error) {
36+ // Example: func (r *ResourceJob) DoRefresh(ctx context.Context, id string) (*jobs.Job, error)
3137 DoRefresh (ctx context.Context , id string ) (remoteState any , e error )
3238
3339 // DoDelete deletes the resource.
34- // Example: func (r *ResourceJob) DoDelete(ctx context.Context, id string) error {
40+ // Example: func (r *ResourceJob) DoDelete(ctx context.Context, id string) error
3541 DoDelete (ctx context.Context , id string ) error
3642
3743 // [Optional] FieldTriggers returns actions to trigger when given fields are changed.
@@ -49,11 +55,11 @@ type IResourceNoRefresh interface {
4955 // We pass newState as a pointer but it is never nil. Changes to it will be persisted in the state, so should be used carefully.
5056
5157 // DoCreate creates a new resource from the newState.
52- // Example: func (r *ResourceJob) DoCreate(ctx context.Context, newState *jobs.JobSettings) (string, error) {
58+ // Example: func (r *ResourceJob) DoCreate(ctx context.Context, newState *jobs.JobSettings) (string, error)
5359 DoCreate (ctx context.Context , newState any ) (id string , e error )
5460
5561 // DoUpdate updates the resource. ID must not change as a result of this operation.
56- // Example: func (r *ResourceJob) DoUpdate(ctx context.Context, id string, newState *jobs.JobSettings) error {
62+ // Example: func (r *ResourceJob) DoUpdate(ctx context.Context, id string, newState *jobs.JobSettings) error
5763 DoUpdate (ctx context.Context , id string , newState any ) error
5864
5965 // [Optional] DoUpdateWithID performs an update that may result in resource having a new ID
@@ -73,11 +79,11 @@ type IResourceNoRefresh interface {
7379// Note, resource implementations don't pick between IResourceNoRefresh and IResourceWithRefresh, they can make independent decision for each of the methods.
7480type IResourceWithRefresh interface {
7581 // DoCreate creates a new resource from the newState. Returns id of the resource and remote state.
76- // Example: func (r *ResourceVolume) DoCreate(ctx context.Context, newState *catalog.CreateWarehouseRequestContent) (string, *catalog.VolumeInfo, error) {
82+ // Example: func (r *ResourceVolume) DoCreate(ctx context.Context, newState *catalog.CreateWarehouseRequestContent) (string, *catalog.VolumeInfo, error)
7783 DoCreate (ctx context.Context , newState any ) (id string , remoteState any , e error )
7884
7985 // DoUpdate updates the resource. ID must not change as a result of this operation. Returns remote state.
80- // Example: func (r *ResourceSchema) DoUpdate(ctx context.Context, id string, newState *catalog.CreateSchema) (*catalog.SchemaInfo, error) {
86+ // Example: func (r *ResourceSchema) DoUpdate(ctx context.Context, id string, newState *catalog.CreateSchema) (*catalog.SchemaInfo, error)
8187 DoUpdate (ctx context.Context , id string , newState any ) (remoteState any , e error )
8288
8389 // Optional: updates that may change ID. Returns new id and remote state when available.
@@ -95,6 +101,7 @@ type IResourceWithRefresh interface {
95101type Adapter struct {
96102 // Required:
97103 prepareState * calladapt.BoundCaller
104+ remapState * calladapt.BoundCaller
98105 doRefresh * calladapt.BoundCaller
99106 doDelete * calladapt.BoundCaller
100107 doCreate * calladapt.BoundCaller
@@ -123,6 +130,7 @@ func NewAdapter(typedNil any, client *databricks.WorkspaceClient) (*Adapter, err
123130 impl := outs [0 ]
124131 adapter := & Adapter {
125132 prepareState : nil ,
133+ remapState : nil ,
126134 doRefresh : nil ,
127135 doDelete : nil ,
128136 doCreate : nil ,
@@ -174,6 +182,12 @@ func (a *Adapter) initMethods(resource any) error {
174182 return err
175183 }
176184
185+ // RemapState is optional when remote type already matches state type.
186+ a .remapState , err = calladapt .PrepareCall (resource , calladapt .TypeOf [IResource ](), "RemapState" )
187+ if err != nil {
188+ return err
189+ }
190+
177191 a .doRefresh , err = prepareCallRequired (resource , "DoRefresh" )
178192 if err != nil {
179193 return err
@@ -251,6 +265,17 @@ func (a *Adapter) validate() error {
251265 "DoUpdate newState" , a .doUpdate .InTypes [2 ], stateType ,
252266 }
253267
268+ // If RemapState is implemented, validate its signature.
269+ // Otherwise require remote type to equal state type so remapping isn't needed.
270+ if a .remapState != nil {
271+ validations = append (validations ,
272+ "RemapState input" , a .remapState .InTypes [0 ], remoteType ,
273+ "RemapState return" , a .remapState .OutTypes [0 ], stateType ,
274+ )
275+ } else if remoteType != stateType {
276+ return fmt .Errorf ("RemapState method not found and remote type %v must match state type %v" , remoteType , stateType )
277+ }
278+
254279 // Check if this is WithRefresh version (returns 3 values: id, remoteState, error)
255280 if len (a .doCreate .OutTypes ) == 3 {
256281 validations = append (validations , "DoCreate remoteState return" , a .doCreate .OutTypes [1 ], remoteType )
@@ -323,6 +348,18 @@ func (a *Adapter) PrepareState(input any) (any, error) {
323348 return outs [0 ], nil
324349}
325350
351+ func (a * Adapter ) RemapState (remoteState any ) (any , error ) {
352+ if a .remapState == nil {
353+ return remoteState , nil
354+ }
355+
356+ outs , err := a .remapState .Call (remoteState )
357+ if err != nil {
358+ return nil , err
359+ }
360+ return outs [0 ], nil
361+ }
362+
326363func (a * Adapter ) DoRefresh (ctx context.Context , id string ) (any , error ) {
327364 outs , err := a .doRefresh .Call (ctx , id )
328365 if err != nil {
0 commit comments