@@ -41,6 +41,7 @@ type WaitReq struct {
4141}
4242
4343type HandleCreateReq struct {
44+ APIOperations ResourceAPIOperations
4445 Resp * resource.CreateResponse
4546 Client * config.MongoDBClient
4647 Plan any
@@ -52,12 +53,8 @@ type HandleCreateReq struct {
5253
5354func HandleCreate (ctx context.Context , req HandleCreateReq ) {
5455 d := & req .Resp .Diagnostics
55- bodyReq , err := Marshal (req .Plan , false )
56- if err != nil {
57- addError (d , opCreate , errBuildingAPIRequest , err )
58- return
59- }
60- bodyResp , _ , err := callAPIWithBody (ctx , req .Client , req .CallParams , bodyReq )
56+
57+ bodyResp , _ , err := req .APIOperations .PerformCreate (ctx , & req )
6158 if err != nil {
6259 addError (d , opCreate , errCallingAPI , err )
6360 return
@@ -72,12 +69,12 @@ func HandleCreate(ctx context.Context, req HandleCreateReq) {
7269 addError (d , opCreate , errResolvingResponse , err )
7370 return
7471 }
75- errWait := handleWaitCreateUpdate (ctx , req .Wait , req .Client , req .Plan )
72+ errWait := handleWaitCreateUpdate (ctx , req .Wait , req .APIOperations , req . Client , req .Plan )
7673 if req .DeleteReq != nil {
7774 // Handle timeout with cleanup if delete_on_create_timeout is enabled.
7875 errWait = cleanup .HandleCreateTimeout (req .DeleteOnCreateTimeout , errWait , func (ctxCleanup context.Context ) error {
7976 deleteReq := req .DeleteReq (req .Plan )
80- return callDelete (ctxCleanup , deleteReq )
77+ return req . APIOperations . PerformDelete (ctxCleanup , deleteReq )
8178 })
8279 }
8380 if errWait != nil {
@@ -88,16 +85,17 @@ func HandleCreate(ctx context.Context, req HandleCreateReq) {
8885}
8986
9087type HandleReadReq struct {
91- Resp * resource.ReadResponse
92- Client * config.MongoDBClient
93- State any
94- CallParams * config.APICallParams
88+ APIOperations ResourceAPIOperations
89+ Resp * resource.ReadResponse
90+ Client * config.MongoDBClient
91+ State any
92+ CallParams * config.APICallParams
9593}
9694
9795func HandleRead (ctx context.Context , req HandleReadReq ) {
9896 d := & req .Resp .Diagnostics
99- bodyResp , apiResp , err := callAPIWithoutBody (ctx , req . Client , req . CallParams )
100- if notFound (bodyResp , apiResp ) {
97+ bodyResp , apiResp , err := req . APIOperations . PerformRead (ctx , & req )
98+ if NotFound (bodyResp , apiResp ) {
10199 req .Resp .State .RemoveResource (ctx )
102100 return
103101 }
@@ -119,21 +117,18 @@ func HandleRead(ctx context.Context, req HandleReadReq) {
119117}
120118
121119type HandleUpdateReq struct {
122- Resp * resource.UpdateResponse
123- Client * config.MongoDBClient
124- Plan any
125- CallParams * config.APICallParams
126- Wait * WaitReq
120+ APIOperations ResourceAPIOperations
121+ Resp * resource.UpdateResponse
122+ Client * config.MongoDBClient
123+ Plan any
124+ CallParams * config.APICallParams
125+ Wait * WaitReq
127126}
128127
129128func HandleUpdate (ctx context.Context , req HandleUpdateReq ) {
130129 d := & req .Resp .Diagnostics
131- bodyReq , err := Marshal (req .Plan , true )
132- if err != nil {
133- addError (d , opUpdate , errBuildingAPIRequest , err )
134- return
135- }
136- bodyResp , _ , err := callAPIWithBody (ctx , req .Client , req .CallParams , bodyReq )
130+
131+ bodyResp , _ , err := req .APIOperations .PerformUpdate (ctx , & req )
137132 if err != nil {
138133 addError (d , opUpdate , errCallingAPI , err )
139134 return
@@ -148,14 +143,15 @@ func HandleUpdate(ctx context.Context, req HandleUpdateReq) {
148143 addError (d , opUpdate , errResolvingResponse , err )
149144 return
150145 }
151- if err := handleWaitCreateUpdate (ctx , req .Wait , req .Client , req .Plan ); err != nil {
146+ if err := handleWaitCreateUpdate (ctx , req .Wait , req .APIOperations , req . Client , req .Plan ); err != nil {
152147 addError (d , opUpdate , errWaitingForChanges , err )
153148 return
154149 }
155150 req .Resp .Diagnostics .Append (req .Resp .State .Set (ctx , req .Plan )... )
156151}
157152
158153type HandleDeleteReq struct {
154+ APIOperations ResourceAPIOperations
159155 Diags * diag.Diagnostics
160156 Client * config.MongoDBClient
161157 State any
@@ -165,22 +161,22 @@ type HandleDeleteReq struct {
165161}
166162
167163func HandleDelete (ctx context.Context , req HandleDeleteReq ) {
168- if err := callDelete (ctx , & req ); err != nil {
164+ if err := req . APIOperations . PerformDelete (ctx , & req ); err != nil {
169165 addError (req .Diags , opDelete , errCallingAPI , err )
170166 return
171167 }
172- if errWait := handleWaitDelete (ctx , req .Wait , req .Client , req .State ); errWait != nil {
168+ if errWait := handleWaitDelete (ctx , req .Wait , req .APIOperations , req . Client , req .State ); errWait != nil {
173169 addError (req .Diags , opDelete , errWaitingForChanges , errWait )
174170 }
175171}
176172
177173// handleWaitCreateUpdate waits until a long-running operation is done if needed.
178174// It also updates the model with the latest JSON response from the API.
179- func handleWaitCreateUpdate (ctx context.Context , wait * WaitReq , client * config.MongoDBClient , model any ) error {
175+ func handleWaitCreateUpdate (ctx context.Context , wait * WaitReq , apiOps ResourceAPIOperations , client * config.MongoDBClient , model any ) error {
180176 if wait == nil {
181177 return nil
182178 }
183- bodyResp , err := waitForChanges (ctx , wait , client , model )
179+ bodyResp , err := waitForChanges (ctx , wait , apiOps , client , model )
184180 if err != nil || isEmptyJSON (bodyResp ) {
185181 return err
186182 }
@@ -191,23 +187,25 @@ func handleWaitCreateUpdate(ctx context.Context, wait *WaitReq, client *config.M
191187}
192188
193189// handleWaitDelete waits until a long-running operation to delete a resource if neeed.
194- func handleWaitDelete (ctx context.Context , wait * WaitReq , client * config.MongoDBClient , model any ) error {
190+ func handleWaitDelete (ctx context.Context , wait * WaitReq , apiOps ResourceAPIOperations , client * config.MongoDBClient , model any ) error {
195191 if wait == nil {
196192 return nil
197193 }
198- if _ , err := waitForChanges (ctx , wait , client , model ); err != nil {
194+ if _ , err := waitForChanges (ctx , wait , apiOps , client , model ); err != nil {
199195 return err
200196 }
201197 return nil
202198}
203199
204- func addError (d * diag.Diagnostics , opName , errSummary string , err error ) {
205- d .AddError (fmt .Sprintf ("Error %s in %s" , errSummary , opName ), err .Error ())
200+ // NotFound returns if the resource is not found (API response is 404 or response body is empty JSON).
201+ // That is because some resources like search_deployment can return an ok status code with empty json when resource doesn't exist.
202+ func NotFound (bodyResp []byte , apiResp * http.Response ) bool {
203+ return validate .StatusNotFound (apiResp ) || isEmptyJSON (bodyResp )
206204}
207205
208- // callAPIWithBody makes a request to the API with the given request body and returns the response body.
206+ // CallAPIWithBody makes a request to the API with the given request body and returns the response body.
209207// It is used for POST, PUT, PATCH and DELETE with static content.
210- func callAPIWithBody (ctx context.Context , client * config.MongoDBClient , callParams * config.APICallParams , bodyReq []byte ) ([]byte , * http.Response , error ) {
208+ func CallAPIWithBody (ctx context.Context , client * config.MongoDBClient , callParams * config.APICallParams , bodyReq []byte ) ([]byte , * http.Response , error ) {
211209 apiResp , err := client .UntypedAPICall (ctx , callParams , bodyReq )
212210 if err != nil {
213211 return nil , apiResp , err
@@ -220,9 +218,9 @@ func callAPIWithBody(ctx context.Context, client *config.MongoDBClient, callPara
220218 return bodyResp , apiResp , nil
221219}
222220
223- // callAPIWithoutBody makes a request to the API without a request body and returns the response body.
221+ // CallAPIWithoutBody makes a request to the API without a request body and returns the response body.
224222// It is used for GET or DELETE requests where no request body is required.
225- func callAPIWithoutBody (ctx context.Context , client * config.MongoDBClient , callParams * config.APICallParams ) ([]byte , * http.Response , error ) {
223+ func CallAPIWithoutBody (ctx context.Context , client * config.MongoDBClient , callParams * config.APICallParams ) ([]byte , * http.Response , error ) {
226224 apiResp , err := client .UntypedAPICall (ctx , callParams , nil )
227225 if err != nil {
228226 return nil , apiResp , err
@@ -235,26 +233,13 @@ func callAPIWithoutBody(ctx context.Context, client *config.MongoDBClient, callP
235233 return bodyResp , apiResp , nil
236234}
237235
238- // callDelete makes a DELETE request to the API, supporting both requests with and without a body.
239- // Returns nil if the resource is not found (already deleted).
240- func callDelete (ctx context.Context , req * HandleDeleteReq ) error {
241- var err error
242- var bodyResp []byte
243- var apiResp * http.Response
244- if req .StaticRequestBody == "" {
245- bodyResp , apiResp , err = callAPIWithoutBody (ctx , req .Client , req .CallParams )
246- } else {
247- bodyResp , apiResp , err = callAPIWithBody (ctx , req .Client , req .CallParams , []byte (req .StaticRequestBody ))
248- }
249- if notFound (bodyResp , apiResp ) { // Resource is already deleted, don't fail.
250- return nil
251- }
252- return err
236+ func addError (d * diag.Diagnostics , opName , errSummary string , err error ) {
237+ d .AddError (fmt .Sprintf ("Error %s in %s" , errSummary , opName ), err .Error ())
253238}
254239
255240// waitForChanges waits until a long-running operation is done.
256241// It returns the latest JSON response from the API so it can be used to update the response state.
257- func waitForChanges (ctx context.Context , wait * WaitReq , client * config.MongoDBClient , model any ) ([]byte , error ) {
242+ func waitForChanges (ctx context.Context , wait * WaitReq , apiOps ResourceAPIOperations , client * config.MongoDBClient , model any ) ([]byte , error ) {
258243 if len (wait .TargetStates ) == 0 {
259244 return nil , fmt .Errorf ("wait must have at least one target state, pending states: %v" , wait .PendingStates )
260245 }
@@ -264,7 +249,7 @@ func waitForChanges(ctx context.Context, wait *WaitReq, client *config.MongoDBCl
264249 Timeout : wait .Timeout ,
265250 MinTimeout : time .Duration (wait .MinTimeoutSeconds ) * time .Second ,
266251 Delay : time .Duration (wait .DelaySeconds ) * time .Second ,
267- Refresh : refreshFunc (ctx , wait , client , model ),
252+ Refresh : refreshFunc (ctx , wait , apiOps , client , model ),
268253 }
269254 bodyResp , err := stateConf .WaitForStateContext (ctx )
270255 if err != nil || bodyResp == nil {
@@ -275,11 +260,16 @@ func waitForChanges(ctx context.Context, wait *WaitReq, client *config.MongoDBCl
275260
276261// refreshFunc retries until a target state or error happens.
277262// It uses a special state value of "DELETED" when the API returns 404 or empty object
278- func refreshFunc (ctx context.Context , wait * WaitReq , client * config.MongoDBClient , model any ) retry.StateRefreshFunc {
263+ func refreshFunc (ctx context.Context , wait * WaitReq , apiOps ResourceAPIOperations , client * config.MongoDBClient , model any ) retry.StateRefreshFunc {
279264 return func () (result any , state string , err error ) {
280265 callParams := wait .CallParams (model )
281- bodyResp , httpResp , err := callAPIWithoutBody (ctx , client , callParams )
282- if notFound (bodyResp , httpResp ) {
266+ bodyResp , httpResp , err := apiOps .PerformRead (ctx , & HandleReadReq {
267+ APIOperations : apiOps ,
268+ Client : client ,
269+ State : model ,
270+ CallParams : callParams ,
271+ })
272+ if NotFound (bodyResp , httpResp ) {
283273 // if "artificial" states continue to grow we can evaluate using a prefix to clearly separate states coming from API and those defined by refreshFunc
284274 return emptyJSON , retrystrategy .RetryStrategyDeletedState , nil
285275 }
@@ -302,12 +292,6 @@ func refreshFunc(ctx context.Context, wait *WaitReq, client *config.MongoDBClien
302292 }
303293}
304294
305- // notFound returns if the resource is not found (API response is 404 or response body is empty JSON).
306- // That is because some resources like search_deployment can return an ok status code with empty json when resource doesn't exist.
307- func notFound (bodyResp []byte , apiResp * http.Response ) bool {
308- return validate .StatusNotFound (apiResp ) || isEmptyJSON (bodyResp )
309- }
310-
311295func isEmptyJSON (raw []byte ) bool {
312296 return len (raw ) == 0 || bytes .Equal (raw , emptyJSON )
313297}
0 commit comments