@@ -34,14 +34,10 @@ type IResource interface {
3434 // Example: func (r *ResourceJob) DoDelete(ctx context.Context, id string) error {
3535 DoDelete (ctx context.Context , id string ) error
3636
37- // [Optional] RecreateFields returns a list of fields that will cause resource recreation if changed
38- // Example: func (r *ResourceJob) RecreateFields() []string { return []string{"name", "type"} }
39- RecreateFields () []string
40-
41- // [Optional] ClassifyChanges provides non-default change classification.
42- // Default is to consider any change "an update" (RecreateFields handled separately).
43- // Example: func (r *ResourceJob) ClassifyChanges(changes []structdiff.Change) deployplan.ActionType { return deployplan.ActionUpdate }
44- ClassifyChanges (changes []structdiff.Change ) deployplan.ActionType
37+ // [Optional] FieldTriggers returns actions to trigger when given fields are changed.
38+ // Keys are field paths (e.g., ".name", ".catalog_name"). Values are actions.
39+ // Unspecified changed fields default to ActionTypeUpdate.
40+ FieldTriggers () map [string ]deployplan.ActionType
4541}
4642
4743// IResourceNoRefresh describes additional methods for resource to implement.
@@ -108,9 +104,8 @@ type Adapter struct {
108104 doUpdateWithID * calladapt.BoundCaller
109105 waitAfterCreate * calladapt.BoundCaller
110106 waitAfterUpdate * calladapt.BoundCaller
111- classifyChanges * calladapt.BoundCaller
112107
113- recreateFields map [string ]struct {}
108+ fieldTriggers map [string ]deployplan. ActionType
114109}
115110
116111func NewAdapter (typedNil any , client * databricks.WorkspaceClient ) (* Adapter , error ) {
@@ -135,29 +130,28 @@ func NewAdapter(typedNil any, client *databricks.WorkspaceClient) (*Adapter, err
135130 doUpdateWithID : nil ,
136131 waitAfterCreate : nil ,
137132 waitAfterUpdate : nil ,
138- classifyChanges : nil ,
139- recreateFields : map [string ]struct {}{},
133+ fieldTriggers : map [string ]deployplan.ActionType {},
140134 }
141135
142136 err = adapter .initMethods (impl )
143137 if err != nil {
144138 return nil , err
145139 }
146140
147- // Load optional RecreateFields method from the unified interface
148- recreateCall , err := calladapt .PrepareCall (impl , calladapt .TypeOf [IResource ](), "RecreateFields " )
141+ // Load optional FieldTriggers method from the unified interface
142+ triggerCall , err := calladapt .PrepareCall (impl , calladapt .TypeOf [IResource ](), "FieldTriggers " )
149143 if err != nil {
150144 return nil , err
151145 }
152- if recreateCall != nil {
153- outs , err := recreateCall .Call ()
146+ if triggerCall != nil {
147+ outs , err := triggerCall .Call ()
154148 if err != nil || len (outs ) != 1 {
155- return nil , fmt .Errorf ("failed to call RecreateFields : %w" , err )
149+ return nil , fmt .Errorf ("failed to call FieldTriggers : %w" , err )
156150 }
157- fields := outs [0 ].([] string )
158- adapter .recreateFields = make (map [string ]struct {} , len (fields ))
159- for _ , field := range fields {
160- adapter .recreateFields [ field ] = struct {}{}
151+ fields := outs [0 ].(map [ string ]deployplan. ActionType )
152+ adapter .fieldTriggers = make (map [string ]deployplan. ActionType , len (fields ))
153+ for k , v := range fields {
154+ adapter .fieldTriggers [ k ] = v
161155 }
162156 }
163157
@@ -217,8 +211,7 @@ func (a *Adapter) initMethods(resource any) error {
217211 return err
218212 }
219213
220- a .classifyChanges , err = calladapt .PrepareCall (resource , calladapt .TypeOf [IResource ](), "ClassifyChanges" )
221- return err
214+ return nil
222215}
223216
224217// validateTypes validates type matches for variadic triples of (name, actual, expected).
@@ -293,8 +286,18 @@ func (a *Adapter) validate() error {
293286 return err
294287 }
295288
296- if a .doUpdateWithID != nil && a .classifyChanges == nil {
297- return errors .New ("if DoUpdateWithID is present, should have implement ClassifyChanges" )
289+ // FieldTriggers validation
290+ hasUpdateWithIDTrigger := false
291+ for _ , action := range a .fieldTriggers {
292+ if action == deployplan .ActionTypeUpdateWithID {
293+ hasUpdateWithIDTrigger = true
294+ }
295+ }
296+ if hasUpdateWithIDTrigger && a .doUpdateWithID == nil {
297+ return errors .New ("FieldTriggers includes update_with_id but DoUpdateWithID is not implemented" )
298+ }
299+ if a .doUpdateWithID != nil && ! hasUpdateWithIDTrigger {
300+ return errors .New ("DoUpdateWithID is implemented but FieldTriggers lacks update_with_id trigger" )
298301 }
299302
300303 return nil
@@ -381,11 +384,6 @@ func (a *Adapter) DoUpdate(ctx context.Context, id string, newState any) (any, e
381384 }
382385}
383386
384- // HasClassifyChanges returns true if the resource implements ClassifyChanges method.
385- func (a * Adapter ) HasClassifyChanges () bool {
386- return a .classifyChanges != nil
387- }
388-
389387// HasDoUpdateWithID returns true if the resource implements DoUpdateWithID method.
390388func (a * Adapter ) HasDoUpdateWithID () bool {
391389 return a .doUpdateWithID != nil
@@ -412,30 +410,26 @@ func (a *Adapter) DoUpdateWithID(ctx context.Context, oldID string, newState any
412410 }
413411}
414412
415- // MustRecreate checks if any of the changes require resource recreation.
416- func (a * Adapter ) MustRecreate (changes []structdiff.Change ) bool {
417- if len (a .recreateFields ) == 0 {
418- return false
413+ // ClassifyByTriggers classifies a set of changes using FieldTriggers.
414+ // Unspecified changed fields default to ActionTypeUpdate. Final action is the
415+ // maximum by precedence. No changes yield ActionTypeNoop.
416+ func (a * Adapter ) ClassifyByTriggers (changes []structdiff.Change ) deployplan.ActionType {
417+ if len (changes ) == 0 {
418+ return deployplan .ActionTypeNoop
419419 }
420+
421+ // Default when there are changes but no explicit trigger is update.
422+ result := deployplan .ActionTypeUpdate
420423 for _ , change := range changes {
421- if _ , ok := a .recreateFields [change .Path .String ()]; ok {
422- return true
424+ action , ok := a .fieldTriggers [change .Path .String ()]
425+ if ! ok {
426+ action = deployplan .ActionTypeUpdate
427+ }
428+ if action > result {
429+ result = action
423430 }
424431 }
425- return false
426- }
427-
428- // ClassifyChanges calls the resource's ClassifyChanges method if implemented.
429- func (a * Adapter ) ClassifyChanges (changes []structdiff.Change ) (deployplan.ActionType , error ) {
430- if a .classifyChanges == nil {
431- return deployplan .ActionTypeUnset , errors .New ("internal error: ClassifyChanges not implemented" )
432- }
433- outs , err := a .classifyChanges .Call (changes )
434- if err != nil {
435- return deployplan .ActionTypeUnset , err
436- }
437- result := outs [0 ].(deployplan.ActionType )
438- return result , nil
432+ return result
439433}
440434
441435// WaitAfterCreate waits for the resource to become ready after creation.
0 commit comments