diff --git a/.github/workflows/acceptance-tests-runner.yml b/.github/workflows/acceptance-tests-runner.yml index 58385a710c..cc041b5209 100644 --- a/.github/workflows/acceptance-tests-runner.yml +++ b/.github/workflows/acceptance-tests-runner.yml @@ -305,6 +305,7 @@ jobs: - 'internal/serviceapi/databaseuserapi/*.go' - 'internal/serviceapi/maintenancewindowapi/*.go' - 'internal/serviceapi/orgserviceaccountapi/*.go' + - 'internal/serviceapi/orgserviceaccountsecretapi/*.go' - 'internal/serviceapi/projectapi/*.go' - 'internal/serviceapi/projectsettingsapi/*.go' - 'internal/serviceapi/resourcepolicyapi/*.go' diff --git a/internal/common/autogen/handle_operations.go b/internal/common/autogen/handle_operations.go index 1f8b31110b..d41d93b99d 100644 --- a/internal/common/autogen/handle_operations.go +++ b/internal/common/autogen/handle_operations.go @@ -41,6 +41,7 @@ type WaitReq struct { } type HandleCreateReq struct { + APIOperations ResourceAPIOperations Resp *resource.CreateResponse Client *config.MongoDBClient Plan any @@ -52,12 +53,8 @@ type HandleCreateReq struct { func HandleCreate(ctx context.Context, req HandleCreateReq) { d := &req.Resp.Diagnostics - bodyReq, err := Marshal(req.Plan, false) - if err != nil { - addError(d, opCreate, errBuildingAPIRequest, err) - return - } - bodyResp, _, err := callAPIWithBody(ctx, req.Client, req.CallParams, bodyReq) + + bodyResp, _, err := req.APIOperations.PerformCreate(ctx, &req) if err != nil { addError(d, opCreate, errCallingAPI, err) return @@ -72,12 +69,12 @@ func HandleCreate(ctx context.Context, req HandleCreateReq) { addError(d, opCreate, errResolvingResponse, err) return } - errWait := handleWaitCreateUpdate(ctx, req.Wait, req.Client, req.Plan) + errWait := handleWaitCreateUpdate(ctx, req.Wait, req.APIOperations, req.Client, req.Plan) if req.DeleteReq != nil { // Handle timeout with cleanup if delete_on_create_timeout is enabled. errWait = cleanup.HandleCreateTimeout(req.DeleteOnCreateTimeout, errWait, func(ctxCleanup context.Context) error { deleteReq := req.DeleteReq(req.Plan) - return callDelete(ctxCleanup, deleteReq) + return req.APIOperations.PerformDelete(ctxCleanup, deleteReq) }) } if errWait != nil { @@ -88,16 +85,17 @@ func HandleCreate(ctx context.Context, req HandleCreateReq) { } type HandleReadReq struct { - Resp *resource.ReadResponse - Client *config.MongoDBClient - State any - CallParams *config.APICallParams + APIOperations ResourceAPIOperations + Resp *resource.ReadResponse + Client *config.MongoDBClient + State any + CallParams *config.APICallParams } func HandleRead(ctx context.Context, req HandleReadReq) { d := &req.Resp.Diagnostics - bodyResp, apiResp, err := callAPIWithoutBody(ctx, req.Client, req.CallParams) - if notFound(bodyResp, apiResp) { + bodyResp, apiResp, err := req.APIOperations.PerformRead(ctx, &req) + if NotFound(bodyResp, apiResp) { req.Resp.State.RemoveResource(ctx) return } @@ -119,21 +117,18 @@ func HandleRead(ctx context.Context, req HandleReadReq) { } type HandleUpdateReq struct { - Resp *resource.UpdateResponse - Client *config.MongoDBClient - Plan any - CallParams *config.APICallParams - Wait *WaitReq + APIOperations ResourceAPIOperations + Resp *resource.UpdateResponse + Client *config.MongoDBClient + Plan any + CallParams *config.APICallParams + Wait *WaitReq } func HandleUpdate(ctx context.Context, req HandleUpdateReq) { d := &req.Resp.Diagnostics - bodyReq, err := Marshal(req.Plan, true) - if err != nil { - addError(d, opUpdate, errBuildingAPIRequest, err) - return - } - bodyResp, _, err := callAPIWithBody(ctx, req.Client, req.CallParams, bodyReq) + + bodyResp, _, err := req.APIOperations.PerformUpdate(ctx, &req) if err != nil { addError(d, opUpdate, errCallingAPI, err) return @@ -148,7 +143,7 @@ func HandleUpdate(ctx context.Context, req HandleUpdateReq) { addError(d, opUpdate, errResolvingResponse, err) return } - if err := handleWaitCreateUpdate(ctx, req.Wait, req.Client, req.Plan); err != nil { + if err := handleWaitCreateUpdate(ctx, req.Wait, req.APIOperations, req.Client, req.Plan); err != nil { addError(d, opUpdate, errWaitingForChanges, err) return } @@ -156,6 +151,7 @@ func HandleUpdate(ctx context.Context, req HandleUpdateReq) { } type HandleDeleteReq struct { + APIOperations ResourceAPIOperations Diags *diag.Diagnostics Client *config.MongoDBClient State any @@ -165,22 +161,22 @@ type HandleDeleteReq struct { } func HandleDelete(ctx context.Context, req HandleDeleteReq) { - if err := callDelete(ctx, &req); err != nil { + if err := req.APIOperations.PerformDelete(ctx, &req); err != nil { addError(req.Diags, opDelete, errCallingAPI, err) return } - if errWait := handleWaitDelete(ctx, req.Wait, req.Client, req.State); errWait != nil { + if errWait := handleWaitDelete(ctx, req.Wait, req.APIOperations, req.Client, req.State); errWait != nil { addError(req.Diags, opDelete, errWaitingForChanges, errWait) } } // handleWaitCreateUpdate waits until a long-running operation is done if needed. // It also updates the model with the latest JSON response from the API. -func handleWaitCreateUpdate(ctx context.Context, wait *WaitReq, client *config.MongoDBClient, model any) error { +func handleWaitCreateUpdate(ctx context.Context, wait *WaitReq, apiOps ResourceAPIOperations, client *config.MongoDBClient, model any) error { if wait == nil { return nil } - bodyResp, err := waitForChanges(ctx, wait, client, model) + bodyResp, err := waitForChanges(ctx, wait, apiOps, client, model) if err != nil || isEmptyJSON(bodyResp) { return err } @@ -191,23 +187,25 @@ func handleWaitCreateUpdate(ctx context.Context, wait *WaitReq, client *config.M } // handleWaitDelete waits until a long-running operation to delete a resource if neeed. -func handleWaitDelete(ctx context.Context, wait *WaitReq, client *config.MongoDBClient, model any) error { +func handleWaitDelete(ctx context.Context, wait *WaitReq, apiOps ResourceAPIOperations, client *config.MongoDBClient, model any) error { if wait == nil { return nil } - if _, err := waitForChanges(ctx, wait, client, model); err != nil { + if _, err := waitForChanges(ctx, wait, apiOps, client, model); err != nil { return err } return nil } -func addError(d *diag.Diagnostics, opName, errSummary string, err error) { - d.AddError(fmt.Sprintf("Error %s in %s", errSummary, opName), err.Error()) +// NotFound returns if the resource is not found (API response is 404 or response body is empty JSON). +// That is because some resources like search_deployment can return an ok status code with empty json when resource doesn't exist. +func NotFound(bodyResp []byte, apiResp *http.Response) bool { + return validate.StatusNotFound(apiResp) || isEmptyJSON(bodyResp) } -// callAPIWithBody makes a request to the API with the given request body and returns the response body. +// CallAPIWithBody makes a request to the API with the given request body and returns the response body. // It is used for POST, PUT, PATCH and DELETE with static content. -func callAPIWithBody(ctx context.Context, client *config.MongoDBClient, callParams *config.APICallParams, bodyReq []byte) ([]byte, *http.Response, error) { +func CallAPIWithBody(ctx context.Context, client *config.MongoDBClient, callParams *config.APICallParams, bodyReq []byte) ([]byte, *http.Response, error) { apiResp, err := client.UntypedAPICall(ctx, callParams, bodyReq) if err != nil { return nil, apiResp, err @@ -220,9 +218,9 @@ func callAPIWithBody(ctx context.Context, client *config.MongoDBClient, callPara return bodyResp, apiResp, nil } -// callAPIWithoutBody makes a request to the API without a request body and returns the response body. +// CallAPIWithoutBody makes a request to the API without a request body and returns the response body. // It is used for GET or DELETE requests where no request body is required. -func callAPIWithoutBody(ctx context.Context, client *config.MongoDBClient, callParams *config.APICallParams) ([]byte, *http.Response, error) { +func CallAPIWithoutBody(ctx context.Context, client *config.MongoDBClient, callParams *config.APICallParams) ([]byte, *http.Response, error) { apiResp, err := client.UntypedAPICall(ctx, callParams, nil) if err != nil { return nil, apiResp, err @@ -235,26 +233,13 @@ func callAPIWithoutBody(ctx context.Context, client *config.MongoDBClient, callP return bodyResp, apiResp, nil } -// callDelete makes a DELETE request to the API, supporting both requests with and without a body. -// Returns nil if the resource is not found (already deleted). -func callDelete(ctx context.Context, req *HandleDeleteReq) error { - var err error - var bodyResp []byte - var apiResp *http.Response - if req.StaticRequestBody == "" { - bodyResp, apiResp, err = callAPIWithoutBody(ctx, req.Client, req.CallParams) - } else { - bodyResp, apiResp, err = callAPIWithBody(ctx, req.Client, req.CallParams, []byte(req.StaticRequestBody)) - } - if notFound(bodyResp, apiResp) { // Resource is already deleted, don't fail. - return nil - } - return err +func addError(d *diag.Diagnostics, opName, errSummary string, err error) { + d.AddError(fmt.Sprintf("Error %s in %s", errSummary, opName), err.Error()) } // waitForChanges waits until a long-running operation is done. // It returns the latest JSON response from the API so it can be used to update the response state. -func waitForChanges(ctx context.Context, wait *WaitReq, client *config.MongoDBClient, model any) ([]byte, error) { +func waitForChanges(ctx context.Context, wait *WaitReq, apiOps ResourceAPIOperations, client *config.MongoDBClient, model any) ([]byte, error) { if len(wait.TargetStates) == 0 { return nil, fmt.Errorf("wait must have at least one target state, pending states: %v", wait.PendingStates) } @@ -264,7 +249,7 @@ func waitForChanges(ctx context.Context, wait *WaitReq, client *config.MongoDBCl Timeout: wait.Timeout, MinTimeout: time.Duration(wait.MinTimeoutSeconds) * time.Second, Delay: time.Duration(wait.DelaySeconds) * time.Second, - Refresh: refreshFunc(ctx, wait, client, model), + Refresh: refreshFunc(ctx, wait, apiOps, client, model), } bodyResp, err := stateConf.WaitForStateContext(ctx) if err != nil || bodyResp == nil { @@ -275,11 +260,16 @@ func waitForChanges(ctx context.Context, wait *WaitReq, client *config.MongoDBCl // refreshFunc retries until a target state or error happens. // It uses a special state value of "DELETED" when the API returns 404 or empty object -func refreshFunc(ctx context.Context, wait *WaitReq, client *config.MongoDBClient, model any) retry.StateRefreshFunc { +func refreshFunc(ctx context.Context, wait *WaitReq, apiOps ResourceAPIOperations, client *config.MongoDBClient, model any) retry.StateRefreshFunc { return func() (result any, state string, err error) { callParams := wait.CallParams(model) - bodyResp, httpResp, err := callAPIWithoutBody(ctx, client, callParams) - if notFound(bodyResp, httpResp) { + bodyResp, httpResp, err := apiOps.PerformRead(ctx, &HandleReadReq{ + APIOperations: apiOps, + Client: client, + State: model, + CallParams: callParams, + }) + if NotFound(bodyResp, httpResp) { // if "artificial" states continue to grow we can evaluate using a prefix to clearly separate states coming from API and those defined by refreshFunc return emptyJSON, retrystrategy.RetryStrategyDeletedState, nil } @@ -302,12 +292,6 @@ func refreshFunc(ctx context.Context, wait *WaitReq, client *config.MongoDBClien } } -// notFound returns if the resource is not found (API response is 404 or response body is empty JSON). -// That is because some resources like search_deployment can return an ok status code with empty json when resource doesn't exist. -func notFound(bodyResp []byte, apiResp *http.Response) bool { - return validate.StatusNotFound(apiResp) || isEmptyJSON(bodyResp) -} - func isEmptyJSON(raw []byte) bool { return len(raw) == 0 || bytes.Equal(raw, emptyJSON) } diff --git a/internal/common/autogen/resource_api_operations.go b/internal/common/autogen/resource_api_operations.go new file mode 100644 index 0000000000..bb8c615aba --- /dev/null +++ b/internal/common/autogen/resource_api_operations.go @@ -0,0 +1,55 @@ +package autogen + +import ( + "context" + "fmt" + "net/http" +) + +var _ ResourceAPIOperations = &DefaultResourceAPIOperations{} + +// ResourceAPIOperations defines the interface for API operations in autogen resources. +type ResourceAPIOperations interface { + PerformRead(ctx context.Context, req *HandleReadReq) ([]byte, *http.Response, error) + PerformCreate(ctx context.Context, req *HandleCreateReq) ([]byte, *http.Response, error) + PerformUpdate(ctx context.Context, req *HandleUpdateReq) ([]byte, *http.Response, error) + PerformDelete(ctx context.Context, req *HandleDeleteReq) error +} + +// DefaultResourceAPIOperations is used as an embedded struct for all autogen resources and provides default implementations for all API operations. +type DefaultResourceAPIOperations struct{} + +func (d *DefaultResourceAPIOperations) PerformRead(ctx context.Context, req *HandleReadReq) ([]byte, *http.Response, error) { + return CallAPIWithoutBody(ctx, req.Client, req.CallParams) +} + +func (d *DefaultResourceAPIOperations) PerformCreate(ctx context.Context, req *HandleCreateReq) ([]byte, *http.Response, error) { + bodyReq, err := Marshal(req.Plan, false) + if err != nil { + return nil, nil, fmt.Errorf("%s: %w", errBuildingAPIRequest, err) + } + return CallAPIWithBody(ctx, req.Client, req.CallParams, bodyReq) +} + +func (d *DefaultResourceAPIOperations) PerformUpdate(ctx context.Context, req *HandleUpdateReq) ([]byte, *http.Response, error) { + bodyReq, err := Marshal(req.Plan, true) + if err != nil { + return nil, nil, fmt.Errorf("%s: %w", errBuildingAPIRequest, err) + } + return CallAPIWithBody(ctx, req.Client, req.CallParams, bodyReq) +} + +func (d *DefaultResourceAPIOperations) PerformDelete(ctx context.Context, req *HandleDeleteReq) error { + var err error + var bodyResp []byte + var apiResp *http.Response + if req.StaticRequestBody == "" { + bodyResp, apiResp, err = CallAPIWithoutBody(ctx, req.Client, req.CallParams) + } else { + bodyResp, apiResp, err = CallAPIWithBody(ctx, req.Client, req.CallParams, []byte(req.StaticRequestBody)) + } + if NotFound(bodyResp, apiResp) { + return nil // Already deleted + } + return err +} diff --git a/internal/serviceapi/alertconfigurationapi/resource.go b/internal/serviceapi/alertconfigurationapi/resource.go index f87930a417..6254724134 100755 --- a/internal/serviceapi/alertconfigurationapi/resource.go +++ b/internal/serviceapi/alertconfigurationapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PUT", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -130,15 +135,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "id": model.Id.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/alertConfigs/{id}", diff --git a/internal/serviceapi/auditingapi/resource.go b/internal/serviceapi/auditingapi/resource.go index a8019c9dc0..50b31a94af 100755 --- a/internal/serviceapi/auditingapi/resource.go +++ b/internal/serviceapi/auditingapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -92,10 +96,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -106,7 +111,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -128,14 +133,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/auditLog", diff --git a/internal/serviceapi/clusterapi/resource.go b/internal/serviceapi/clusterapi/resource.go index d2684816c7..e769d2daca 100755 --- a/internal/serviceapi/clusterapi/resource.go +++ b/internal/serviceapi/clusterapi/resource.go @@ -16,6 +16,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} var _ resource.ResourceWithMoveState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-08-05+json" @@ -29,6 +30,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -57,12 +59,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -85,10 +88,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -118,10 +122,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "stateName", PendingStates: []string{"CREATING", "UPDATING", "REPAIRING", "REPEATING", "PENDING", "DELETING"}, @@ -141,7 +146,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) timeout, diags := state.Timeouts.Delete(ctx, 10800*time.Second) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -178,15 +183,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "name": model.Name.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/clusters/{name}", diff --git a/internal/serviceapi/clusteroldapi/resource.go b/internal/serviceapi/clusteroldapi/resource.go index 800cec8b6c..0f400455e9 100755 --- a/internal/serviceapi/clusteroldapi/resource.go +++ b/internal/serviceapi/clusteroldapi/resource.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-02-01+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -56,12 +58,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -84,10 +87,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -117,10 +121,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "stateName", PendingStates: []string{"CREATING", "UPDATING", "REPAIRING", "REPEATING", "PENDING", "DELETING"}, @@ -140,7 +145,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) timeout, diags := state.Timeouts.Delete(ctx, 10800*time.Second) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -177,15 +182,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "name": model.Name.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/clusters/{name}", diff --git a/internal/serviceapi/customdbroleapi/resource.go b/internal/serviceapi/customdbroleapi/resource.go index 914123d598..3b90e5f73f 100755 --- a/internal/serviceapi/customdbroleapi/resource.go +++ b/internal/serviceapi/customdbroleapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -130,15 +135,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "roleName": model.RoleName.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/customDBRoles/roles/{roleName}", diff --git a/internal/serviceapi/databaseuserapi/resource.go b/internal/serviceapi/databaseuserapi/resource.go index 2c06e66407..eae86b7a08 100755 --- a/internal/serviceapi/databaseuserapi/resource.go +++ b/internal/serviceapi/databaseuserapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -94,10 +98,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -108,7 +113,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -132,16 +137,17 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "databaseName": model.DatabaseName.ValueString(), "username": model.Username.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", diff --git a/internal/serviceapi/maintenancewindowapi/resource.go b/internal/serviceapi/maintenancewindowapi/resource.go index d538dea6f9..b7b243e918 100755 --- a/internal/serviceapi/maintenancewindowapi/resource.go +++ b/internal/serviceapi/maintenancewindowapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -92,10 +96,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -106,7 +111,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -128,14 +133,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/maintenanceWindow", diff --git a/internal/serviceapi/orgserviceaccountapi/resource.go b/internal/serviceapi/orgserviceaccountapi/resource.go index ff87eb2636..886e34ed02 100755 --- a/internal/serviceapi/orgserviceaccountapi/resource.go +++ b/internal/serviceapi/orgserviceaccountapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-08-05+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -130,15 +135,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "orgId": model.OrgId.ValueString(), "clientId": model.ClientId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}", diff --git a/internal/serviceapi/orgserviceaccountsecretapi/custom_operations.go b/internal/serviceapi/orgserviceaccountsecretapi/custom_operations.go new file mode 100644 index 0000000000..9360cbf6b4 --- /dev/null +++ b/internal/serviceapi/orgserviceaccountsecretapi/custom_operations.go @@ -0,0 +1,41 @@ +package orgserviceaccountsecretapi + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/autogen" +) + +type response struct { + Secrets []map[string]any `tfsdk:"secrets"` +} + +func (r *rs) PerformRead(ctx context.Context, req *autogen.HandleReadReq) ([]byte, *http.Response, error) { + model := req.State.(*TFModel) + + bodyResp, apiResp, err := autogen.CallAPIWithoutBody(ctx, req.Client, req.CallParams) + if err != nil { + return nil, apiResp, fmt.Errorf("failed to read service account secret: %w", err) + } + + var responseJSON response + if err := json.Unmarshal(bodyResp, &responseJSON); err != nil { + return nil, nil, err + } + + id := model.Id.ValueString() + for _, secret := range responseJSON.Secrets { + if secret["id"] == id { + marshaledSecret, err := json.Marshal(secret) + if err != nil { + return nil, nil, err + } + return marshaledSecret, apiResp, nil + } + } + + return nil, apiResp, nil +} diff --git a/internal/serviceapi/orgserviceaccountsecretapi/main_test.go b/internal/serviceapi/orgserviceaccountsecretapi/main_test.go new file mode 100644 index 0000000000..82a79bb910 --- /dev/null +++ b/internal/serviceapi/orgserviceaccountsecretapi/main_test.go @@ -0,0 +1,15 @@ +package orgserviceaccountsecretapi_test + +import ( + "os" + "testing" + + "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" +) + +func TestMain(m *testing.M) { + cleanup := acc.SetupSharedResources() + exitCode := m.Run() + cleanup() + os.Exit(exitCode) +} diff --git a/internal/serviceapi/orgserviceaccountsecretapi/resource.go b/internal/serviceapi/orgserviceaccountsecretapi/resource.go new file mode 100755 index 0000000000..a637931fe9 --- /dev/null +++ b/internal/serviceapi/orgserviceaccountsecretapi/resource.go @@ -0,0 +1,132 @@ +// Code generated by terraform-provider-mongodbatlas using `make generate-resource`. DO NOT EDIT. + +package orgserviceaccountsecretapi + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/autogen" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/conversion" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/config" +) + +var _ resource.ResourceWithConfigure = &rs{} +var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} + +const apiVersionHeader = "application/vnd.atlas.2024-08-05+json" + +func Resource() resource.Resource { + return &rs{ + RSCommon: config.RSCommon{ + ResourceName: "org_service_account_secret_api", + }, + } +} + +type rs struct { + config.RSCommon + autogen.DefaultResourceAPIOperations +} + +func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = ResourceSchema(ctx) + conversion.UpdateSchemaDescription(&resp.Schema) +} + +func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan TFModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + pathParams := map[string]string{ + "orgId": plan.OrgId.ValueString(), + "clientId": plan.ClientId.ValueString(), + } + callParams := config.APICallParams{ + VersionHeader: apiVersionHeader, + RelativePath: "/api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}/secrets", + PathParams: pathParams, + Method: "POST", + } + reqHandle := autogen.HandleCreateReq{ + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, + } + autogen.HandleCreate(ctx, reqHandle) +} + +func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var state TFModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + reqHandle := autogen.HandleReadReq{ + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), + } + autogen.HandleRead(ctx, reqHandle) +} + +func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.AddError("Operation not supported", "This resource does not support updates. Delete and recreate the resource to apply changes.") +} + +func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state TFModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) + autogen.HandleDelete(ctx, *reqHandle) +} + +func (r *rs) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + idAttributes := []string{"id", "org_id", "client_id"} + autogen.HandleImport(ctx, idAttributes, req, resp) +} + +func readAPICallParams(model any) *config.APICallParams { + m := model.(*TFModel) + pathParams := map[string]string{ + "orgId": m.OrgId.ValueString(), + "clientId": m.ClientId.ValueString(), + } + return &config.APICallParams{ + VersionHeader: apiVersionHeader, + RelativePath: "/api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}", + PathParams: pathParams, + Method: "GET", + } +} + +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { + pathParams := map[string]string{ + "orgId": model.OrgId.ValueString(), + "clientId": model.ClientId.ValueString(), + "id": model.Id.ValueString(), + } + return &autogen.HandleDeleteReq{ + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, + CallParams: &config.APICallParams{ + VersionHeader: apiVersionHeader, + RelativePath: "/api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}/secrets/{id}", + PathParams: pathParams, + Method: "DELETE", + }, + } +} diff --git a/internal/serviceapi/orgserviceaccountsecretapi/resource_schema.go b/internal/serviceapi/orgserviceaccountsecretapi/resource_schema.go new file mode 100755 index 0000000000..b0f0e410d0 --- /dev/null +++ b/internal/serviceapi/orgserviceaccountsecretapi/resource_schema.go @@ -0,0 +1,71 @@ +// Code generated by terraform-provider-mongodbatlas using `make generate-resource`. DO NOT EDIT. + +package orgserviceaccountsecretapi + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/common/customplanmodifier" +) + +func ResourceSchema(ctx context.Context) schema.Schema { + return schema.Schema{ + Attributes: map[string]schema.Attribute{ + "client_id": schema.StringAttribute{ + Required: true, + MarkdownDescription: "The Client ID of the Service Account.", + PlanModifiers: []planmodifier.String{customplanmodifier.CreateOnly()}, + }, + "created_at": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The date that the secret was created on. This parameter expresses its value in the ISO 8601 timestamp format in UTC.", + }, + "expires_at": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The date for the expiration of the secret. This parameter expresses its value in the ISO 8601 timestamp format in UTC.", + }, + "id": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "Unique 24-hexadecimal digit string that identifies the secret.", + }, + "last_used_at": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The last time the secret was used. This parameter expresses its value in the ISO 8601 timestamp format in UTC.", + }, + "masked_secret_value": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The masked Service Account secret.", + }, + "org_id": schema.StringAttribute{ + Required: true, + MarkdownDescription: "Unique 24-hexadecimal digit string that identifies the organization that contains your projects. Use the [/orgs](#tag/Organizations/operation/listOrganizations) endpoint to retrieve all organizations to which the authenticated user has access.", + PlanModifiers: []planmodifier.String{customplanmodifier.CreateOnly()}, + }, + "secret": schema.StringAttribute{ + Computed: true, + MarkdownDescription: "The secret for the Service Account. It will be returned only the first time after creation.", + Sensitive: true, + }, + "secret_expires_after_hours": schema.Int64Attribute{ + Required: true, + MarkdownDescription: "The expiration time of the new Service Account secret, provided in hours. The minimum and maximum allowed expiration times are subject to change and are controlled by the organization's settings.", + PlanModifiers: []planmodifier.Int64{customplanmodifier.CreateOnly()}, + }, + }, + } +} + +type TFModel struct { + ClientId types.String `tfsdk:"client_id" autogen:"omitjson"` + CreatedAt types.String `tfsdk:"created_at" autogen:"omitjson"` + ExpiresAt types.String `tfsdk:"expires_at" autogen:"omitjson"` + Id types.String `tfsdk:"id" autogen:"omitjson"` + LastUsedAt types.String `tfsdk:"last_used_at" autogen:"omitjson"` + MaskedSecretValue types.String `tfsdk:"masked_secret_value" autogen:"omitjson"` + OrgId types.String `tfsdk:"org_id" autogen:"omitjson"` + Secret types.String `tfsdk:"secret" autogen:"sensitive,omitjson"` + SecretExpiresAfterHours types.Int64 `tfsdk:"secret_expires_after_hours" autogen:"omitjsonupdate"` +} diff --git a/internal/serviceapi/orgserviceaccountsecretapi/resource_test.go b/internal/serviceapi/orgserviceaccountsecretapi/resource_test.go new file mode 100644 index 0000000000..931f86c311 --- /dev/null +++ b/internal/serviceapi/orgserviceaccountsecretapi/resource_test.go @@ -0,0 +1,136 @@ +package orgserviceaccountsecretapi_test + +import ( + "context" + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/mongodb/terraform-provider-mongodbatlas/internal/testutil/acc" +) + +const resourceName = "mongodbatlas_org_service_account_secret_api.test" + +func TestAccOrgServiceAccountSecretAPI_basic(t *testing.T) { + var ( + orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") + name = acc.RandomName() + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acc.PreCheckBasic(t) }, + ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, + CheckDestroy: checkDestroy, + Steps: []resource.TestStep{ + { + Config: configBasic(orgID, name), + Check: checkBasic(), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: importStateIDFunc(resourceName), + ImportStateVerifyIdentifierAttribute: "id", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"secret", "masked_secret_value"}, // create returns secret only, import returns masked secret only + }, + }, + }) +} + +func configBasic(orgID, saName string) string { + return fmt.Sprintf(` + resource "mongodbatlas_org_service_account_api" "test" { + org_id = %[1]q + name = %[2]q + description = "Acceptance Test SA" + roles = ["ORG_OWNER"] + secret_expires_after_hours = 12 + } + + resource "mongodbatlas_org_service_account_secret_api" "test" { + org_id = %[1]q + client_id = mongodbatlas_org_service_account_api.test.client_id + secret_expires_after_hours = 12 + } + `, orgID, saName) +} + +func checkBasic() resource.TestCheckFunc { + checks := acc.AddAttrSetChecks(resourceName, nil, "client_id", "created_at", "expires_at", "secret") + checks = append( + checks, + resource.TestCheckNoResourceAttr(resourceName, "masked_secret_value"), + checkExists(resourceName), + ) + return resource.ComposeAggregateTestCheckFunc(checks...) +} + +func checkExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + id := rs.Primary.Attributes["id"] + orgID := rs.Primary.Attributes["org_id"] + clientID := rs.Primary.Attributes["client_id"] + if id == "" || orgID == "" || clientID == "" { + return fmt.Errorf("checkExists, attributes not found for: %s", resourceName) + } + orgServiceAccount, _, err := acc.ConnV2().ServiceAccountsApi.GetOrgServiceAccount(context.Background(), orgID, clientID).Execute() + if err != nil { + return fmt.Errorf("failed to get org service account: %w", err) + } + if orgServiceAccount.Secrets != nil { + for _, secret := range *orgServiceAccount.Secrets { + if secret.Id == id { + return nil + } + } + } + return fmt.Errorf("service account secret (%s/%s/%s) does not exist", id, orgID, clientID) + } +} + +func checkDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "mongodbatlas_org_service_account_secret_api" { + continue + } + id := rs.Primary.Attributes["id"] + orgID := rs.Primary.Attributes["org_id"] + clientID := rs.Primary.Attributes["client_id"] + if id == "" || orgID == "" || clientID == "" { + return fmt.Errorf("checkDestroy, attributes not found for: %s", resourceName) + } + + orgServiceAccount, _, err := acc.ConnV2().ServiceAccountsApi.GetOrgServiceAccount(context.Background(), orgID, clientID).Execute() + if err == nil && orgServiceAccount.Secrets != nil { + for _, secret := range *orgServiceAccount.Secrets { + if secret.Id == id { + return fmt.Errorf("org service account secret (%s/%s/%s) still exists", id, orgID, clientID) + } + } + } + } + return nil +} + +func importStateIDFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + id := rs.Primary.Attributes["id"] + orgID := rs.Primary.Attributes["org_id"] + clientID := rs.Primary.Attributes["client_id"] + if id == "" || orgID == "" || clientID == "" { + return "", fmt.Errorf("import, attributes not found for: %s", resourceName) + } + return fmt.Sprintf("%s/%s/%s", id, orgID, clientID), nil + } +} diff --git a/internal/serviceapi/projectapi/resource.go b/internal/serviceapi/projectapi/resource.go index eaa17f467d..36c775a8a9 100755 --- a/internal/serviceapi/projectapi/resource.go +++ b/internal/serviceapi/projectapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -48,10 +50,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -63,10 +66,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -90,10 +94,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -104,7 +109,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -126,14 +131,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "id": model.Id.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{id}", diff --git a/internal/serviceapi/projectsettingsapi/resource.go b/internal/serviceapi/projectsettingsapi/resource.go index d32df4c4da..141fa07848 100755 --- a/internal/serviceapi/projectsettingsapi/resource.go +++ b/internal/serviceapi/projectsettingsapi/resource.go @@ -13,6 +13,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -26,6 +27,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -49,10 +51,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -64,10 +67,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -91,10 +95,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } diff --git a/internal/serviceapi/pushbasedlogexportapi/resource.go b/internal/serviceapi/pushbasedlogexportapi/resource.go index 36d23ccf42..3c1905fbba 100755 --- a/internal/serviceapi/pushbasedlogexportapi/resource.go +++ b/internal/serviceapi/pushbasedlogexportapi/resource.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-01-01+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -56,12 +58,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -84,10 +87,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -116,10 +120,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "state", PendingStates: []string{"INITIATING", "BUCKET_VERIFIED"}, @@ -139,7 +144,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) timeout, diags := state.Timeouts.Delete(ctx, 900*time.Second) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -175,14 +180,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/pushBasedLogExport", diff --git a/internal/serviceapi/resourcepolicyapi/resource.go b/internal/serviceapi/resourcepolicyapi/resource.go index 1505c95721..1e585e8fc7 100755 --- a/internal/serviceapi/resourcepolicyapi/resource.go +++ b/internal/serviceapi/resourcepolicyapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-08-05+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -130,15 +135,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "orgId": model.OrgId.ValueString(), "id": model.Id.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/orgs/{orgId}/resourcePolicies/{id}", diff --git a/internal/serviceapi/searchdeploymentapi/resource.go b/internal/serviceapi/searchdeploymentapi/resource.go index b0436afe50..a7f5149036 100755 --- a/internal/serviceapi/searchdeploymentapi/resource.go +++ b/internal/serviceapi/searchdeploymentapi/resource.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2025-03-12+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -57,12 +59,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -85,10 +88,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -118,10 +122,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "stateName", PendingStates: []string{"UPDATING", "PAUSED"}, @@ -141,7 +146,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) timeout, diags := state.Timeouts.Delete(ctx, 10800*time.Second) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -178,15 +183,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "clusterName": model.ClusterName.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/deployment", diff --git a/internal/serviceapi/searchindexapi/resource.go b/internal/serviceapi/searchindexapi/resource.go index 4fd852440e..2aab1fac2c 100755 --- a/internal/serviceapi/searchindexapi/resource.go +++ b/internal/serviceapi/searchindexapi/resource.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -57,12 +59,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -85,10 +88,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -119,10 +123,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "status", PendingStates: []string{"PENDING", "BUILDING", "IN_PROGRESS", "MIGRATING"}, @@ -142,7 +147,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -166,16 +171,17 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "clusterName": model.ClusterName.ValueString(), "indexID": model.IndexID.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/indexes/{indexID}", diff --git a/internal/serviceapi/streaminstanceapi/resource.go b/internal/serviceapi/streaminstanceapi/resource.go index 9a4f82e7b1..8d71f9420f 100755 --- a/internal/serviceapi/streaminstanceapi/resource.go +++ b/internal/serviceapi/streaminstanceapi/resource.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2023-02-01+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -130,15 +135,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "name": model.Name.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/streams/{name}", diff --git a/internal/serviceapi/streamprocessorapi/resource.go b/internal/serviceapi/streamprocessorapi/resource.go index 1442c18ca0..83b6a48ae0 100755 --- a/internal/serviceapi/streamprocessorapi/resource.go +++ b/internal/serviceapi/streamprocessorapi/resource.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -57,12 +59,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -85,10 +88,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -119,10 +123,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "state", PendingStates: []string{"INIT", "CREATING"}, @@ -142,7 +147,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) timeout, diags := state.Timeouts.Delete(ctx, 300*time.Second) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -180,16 +185,17 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "groupId": model.GroupId.ValueString(), "tenantName": model.TenantName.ValueString(), "name": model.Name.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/atlas/v2/groups/{groupId}/streams/{tenantName}/processor/{name}", diff --git a/tools/codegen/codespec/api_to_provider_spec_mapper.go b/tools/codegen/codespec/api_to_provider_spec_mapper.go index b992abb0d8..ac3d429cdc 100644 --- a/tools/codegen/codespec/api_to_provider_spec_mapper.go +++ b/tools/codegen/codespec/api_to_provider_spec_mapper.go @@ -43,7 +43,8 @@ func ToCodeSpecModel(atlasAdminAPISpecFilePath, configPath string, resourceName } var results []Resource - for name, resourceConfig := range resourceConfigsToIterate { + for name := range resourceConfigsToIterate { + resourceConfig := resourceConfigsToIterate[name] log.Printf("[INFO] Generating resource model: %s", name) // find resource operations, schemas, etc from OAS oasResource, err := getAPISpecResource(&apiSpec.Model, &resourceConfig, name) @@ -63,7 +64,8 @@ func ToCodeSpecModel(atlasAdminAPISpecFilePath, configPath string, resourceName func validateRequiredOperations(resourceConfigs map[string]config.Resource) error { var validationErrors []error - for name, resourceConfig := range resourceConfigs { + for name := range resourceConfigs { + resourceConfig := resourceConfigs[name] if resourceConfig.Create == nil { validationErrors = append(validationErrors, fmt.Errorf("resource %s missing Create operation in config file", name)) } @@ -78,6 +80,7 @@ func validateRequiredOperations(resourceConfigs map[string]config.Resource) erro } func apiSpecResourceToCodeSpecModel(oasResource APISpecResource, resourceConfig *config.Resource, name string) (*Resource, error) { + var err error createOp := oasResource.CreateOp updateOp := oasResource.UpdateOp readOp := oasResource.ReadOp @@ -88,16 +91,16 @@ func apiSpecResourceToCodeSpecModel(oasResource APISpecResource, resourceConfig configuredVersion = &resourceConfig.VersionHeader } - createRequestAttributes, err := opRequestToAttributes(createOp, configuredVersion) + createRequestAttributes, err := opRequestToAttributes(createOp, resourceConfig.Create, configuredVersion) if err != nil { return nil, fmt.Errorf("failed to process create request attributes for %s: %w", name, err) } - updateRequestAttributes, err := opRequestToAttributes(updateOp, configuredVersion) + updateRequestAttributes, err := opRequestToAttributes(updateOp, resourceConfig.Update, configuredVersion) if err != nil { return nil, fmt.Errorf("failed to process update request attributes for %s: %w", name, err) } - createResponseAttributes := opResponseToAttributes(createOp, configuredVersion) - readResponseAttributes := opResponseToAttributes(readOp, configuredVersion) + createResponseAttributes := opResponseToAttributes(createOp, resourceConfig.Create, configuredVersion) + readResponseAttributes := opResponseToAttributes(readOp, resourceConfig.Read, configuredVersion) attributes := mergeAttributes(&attributeDefinitionSources{ createPathParams: createPathParams, @@ -127,11 +130,12 @@ func apiSpecResourceToCodeSpecModel(oasResource APISpecResource, resourceConfig } resource := &Resource{ - Name: name, - PackageName: strings.ReplaceAll(name, "_", ""), - Schema: schema, - MoveState: moveState, - Operations: operations, + Name: name, + PackageName: strings.ReplaceAll(name, "_", ""), + Schema: schema, + MoveState: moveState, + Operations: operations, + IDAttributes: resourceConfig.IDAttributes, } if err := applyTransformationsWithConfigOpts(resourceConfig, resource); err != nil { @@ -215,8 +219,8 @@ func pathParamsToAttributes(createOp *high.Operation) Attributes { return pathAttributes } -func opRequestToAttributes(op *high.Operation, configuredVersion *string) (Attributes, error) { - if op == nil { +func opRequestToAttributes(op *high.Operation, opConfig *config.APIOperation, configuredVersion *string) (Attributes, error) { + if op == nil || opConfig.SchemaIgnore { return nil, nil } var requestAttributes Attributes @@ -233,7 +237,10 @@ func opRequestToAttributes(op *high.Operation, configuredVersion *string) (Attri return requestAttributes, nil } -func opResponseToAttributes(op *high.Operation, configuredVersion *string) Attributes { +func opResponseToAttributes(op *high.Operation, opConfig *config.APIOperation, configuredVersion *string) Attributes { + if opConfig.SchemaIgnore { + return nil + } var responseAttributes Attributes responseSchema, err := buildSchemaFromResponse(op, configuredVersion) if err != nil { diff --git a/tools/codegen/codespec/model.go b/tools/codegen/codespec/model.go index 8875ad6f3a..a57ab0d0fc 100644 --- a/tools/codegen/codespec/model.go +++ b/tools/codegen/codespec/model.go @@ -39,11 +39,12 @@ type Model struct { } type Resource struct { - Schema *Schema `yaml:"schema,omitempty"` - Operations APIOperations `yaml:"operations"` - MoveState *MoveState `yaml:"move_state,omitempty"` - Name string `yaml:"name"` - PackageName string `yaml:"packageName"` + Schema *Schema `yaml:"schema,omitempty"` + Operations APIOperations `yaml:"operations"` + MoveState *MoveState `yaml:"move_state,omitempty"` + Name string `yaml:"name"` + PackageName string `yaml:"packageName"` + IDAttributes []string `yaml:"id_attributes,omitempty"` } type APIOperations struct { diff --git a/tools/codegen/config.yml b/tools/codegen/config.yml index ceb84a7357..a0df33ce1f 100644 --- a/tools/codegen/config.yml +++ b/tools/codegen/config.yml @@ -761,6 +761,25 @@ resources: roles: type: set + org_service_account_secret_api: + read: + path: /api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId} + schema_ignore: true + method: GET + create: + path: /api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}/secrets + method: POST + delete: + path: /api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}/secrets/{secretId} + method: DELETE + id_attributes: ["id", "org_id", "client_id"] + schema: + aliases: + secretId: id # path param name does not match the API request property. + overrides: + secret: + sensitive: true + alert_configuration_api: read: path: /api/atlas/v2/groups/{groupId}/alertConfigs/{alertConfigId} diff --git a/tools/codegen/config/config_model.go b/tools/codegen/config/config_model.go index c6a09bd540..a52d0f8983 100644 --- a/tools/codegen/config/config_model.go +++ b/tools/codegen/config/config_model.go @@ -13,6 +13,7 @@ type Resource struct { VersionHeader string `yaml:"version_header"` // when not defined latest version defined in API Spec of the resource is used DeprecationMessage *string `yaml:"deprecation_message"` SchemaOptions SchemaOptions `yaml:"schema"` + IDAttributes []string `yaml:"id_attributes"` // when not defined, id attributes are obtained from the read operation path parameters } type APIOperation struct { @@ -20,6 +21,7 @@ type APIOperation struct { Path string `yaml:"path"` Method string `yaml:"method"` StaticRequestBody string `yaml:"static_request_body"` // use at the moment for Delete when it's done with a PATCH or PUT and needs to send a static request body. + SchemaIgnore bool `yaml:"schema_ignore"` } type Wait struct { diff --git a/tools/codegen/gofilegen/codetemplate/resource-file.go.tmpl b/tools/codegen/gofilegen/codetemplate/resource-file.go.tmpl index 9189aa44aa..1bab20e010 100644 --- a/tools/codegen/gofilegen/codetemplate/resource-file.go.tmpl +++ b/tools/codegen/gofilegen/codetemplate/resource-file.go.tmpl @@ -22,19 +22,21 @@ var _ resource.ResourceWithImportState = &rs{} {{- if .MoveState}} var _ resource.ResourceWithMoveState = &rs{} {{- end}} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "{{ .APIOperations.VersionHeader }}" func Resource() resource.Resource { return &rs{ - RSCommon: config.RSCommon{ - ResourceName: "{{ .ResourceName }}", - }, + RSCommon: config.RSCommon{ + ResourceName: "{{ .ResourceName }}", + }, } } type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -66,6 +68,7 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou } {{- end }} reqHandle := autogen.HandleCreateReq { + APIOperations: r, Resp: resp, Client: r.Client, Plan: &plan, @@ -73,7 +76,7 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou {{- with .APIOperations.Create.Wait }} {{- if $.APIOperations.Delete }} DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), {{- end }} @@ -98,6 +101,7 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq { + APIOperations: r, Resp: resp, Client: r.Client, State: &state, @@ -134,6 +138,7 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou } {{ end -}} reqHandle := autogen.HandleUpdateReq { + APIOperations: r, Resp: resp, Client: r.Client, Plan: &plan, @@ -163,7 +168,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) {{- with .APIOperations.Delete.Wait }} timeout, diags := state.Timeouts.Delete(ctx, {{ .TimeoutSeconds }}*time.Second) resp.Diagnostics.Append(diags...) @@ -204,13 +209,14 @@ func readAPICallParams(model any) *config.APICallParams { } {{with .APIOperations.Delete}} -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ {{range .PathParams }} "{{ .CamelCaseName }}": model.{{ .PascalCaseName }}.ValueString(), {{- end }} } return &autogen.HandleDeleteReq{ - Client: client, + APIOperations: r, + Client: r.Client, State: model, Diags: diags, CallParams: &config.APICallParams{ diff --git a/tools/codegen/gofilegen/resource/resource_file.go b/tools/codegen/gofilegen/resource/resource_file.go index 93c146eace..02a5114dbc 100644 --- a/tools/codegen/gofilegen/resource/resource_file.go +++ b/tools/codegen/gofilegen/resource/resource_file.go @@ -22,7 +22,7 @@ func GenerateGoCode(input *codespec.Resource) ([]byte, error) { Delete: toCodeTemplateOpModel(input.Operations.Delete), }, MoveState: toCodeTemplateMoveStateModel(input.MoveState), - IDAttributes: getIDAttributes(input.Operations.Read.Path), + IDAttributes: getIDAttributes(input), } result := codetemplate.ApplyResourceFileTemplate(&tmplInputs) @@ -85,8 +85,11 @@ func getPathParams(s string) []codetemplate.Param { return params } -func getIDAttributes(readPath string) []string { - params := getPathParams(readPath) +func getIDAttributes(input *codespec.Resource) []string { + if input.IDAttributes != nil { + return input.IDAttributes + } + params := getPathParams(input.Operations.Read.Path) result := make([]string, len(params)) for i, param := range params { result[i] = stringcase.ToSnakeCase(param.CamelCaseName) diff --git a/tools/codegen/gofilegen/resource/resource_file_test.go b/tools/codegen/gofilegen/resource/resource_file_test.go index cc3418bb67..0b7dfb93d5 100644 --- a/tools/codegen/gofilegen/resource/resource_file_test.go +++ b/tools/codegen/gofilegen/resource/resource_file_test.go @@ -9,8 +9,8 @@ import ( ) type resourceGenerationTestCase struct { - inputModel codespec.Resource goldenFileName string + inputModel codespec.Resource } func TestResourceGenerationFromCodeSpec(t *testing.T) { diff --git a/tools/codegen/gofilegen/resource/testdata/different-urls-with-path-params.golden.go b/tools/codegen/gofilegen/resource/testdata/different-urls-with-path-params.golden.go index ec1bc5c650..e76af0d502 100644 --- a/tools/codegen/gofilegen/resource/testdata/different-urls-with-path-params.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/different-urls-with-path-params.golden.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -130,15 +135,16 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "projectId": model.ProjectId.ValueString(), "roleName": model.RoleName.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/v1/testname/{projectId}/{roleName}", diff --git a/tools/codegen/gofilegen/resource/testdata/move-state.golden.go b/tools/codegen/gofilegen/resource/testdata/move-state.golden.go index 844348e957..302487aa39 100644 --- a/tools/codegen/gofilegen/resource/testdata/move-state.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/move-state.golden.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} var _ resource.ResourceWithMoveState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -51,10 +53,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -66,10 +69,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -93,10 +97,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -107,7 +112,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -129,14 +134,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "projectId": model.ProjectId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/v1/testname/{projectId}", diff --git a/tools/codegen/gofilegen/resource/testdata/no-op-delete-operation.golden.go b/tools/codegen/gofilegen/resource/testdata/no-op-delete-operation.golden.go index 08319462a0..0d0e7982ea 100644 --- a/tools/codegen/gofilegen/resource/testdata/no-op-delete-operation.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/no-op-delete-operation.golden.go @@ -13,6 +13,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -26,6 +27,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -49,10 +51,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -64,10 +67,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -91,10 +95,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } diff --git a/tools/codegen/gofilegen/resource/testdata/static-request-body-delete.golden.go b/tools/codegen/gofilegen/resource/testdata/static-request-body-delete.golden.go index 6b1d7fda76..322032799e 100644 --- a/tools/codegen/gofilegen/resource/testdata/static-request-body-delete.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/static-request-body-delete.golden.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -92,10 +96,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PATCH", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -106,7 +111,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -128,14 +133,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "projectId": model.ProjectId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/v1/testname/{projectId}", diff --git a/tools/codegen/gofilegen/resource/testdata/unsupported-update-operation.golden.go b/tools/codegen/gofilegen/resource/testdata/unsupported-update-operation.golden.go index bbafa3224c..13109a68c5 100644 --- a/tools/codegen/gofilegen/resource/testdata/unsupported-update-operation.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/unsupported-update-operation.golden.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -83,7 +87,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -105,14 +109,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "projectId": model.ProjectId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/v1/testname/{projectId}", diff --git a/tools/codegen/gofilegen/resource/testdata/update-with-put.golden.go b/tools/codegen/gofilegen/resource/testdata/update-with-put.golden.go index 46109faf6d..1ff08d592e 100644 --- a/tools/codegen/gofilegen/resource/testdata/update-with-put.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/update-with-put.golden.go @@ -14,6 +14,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -27,6 +28,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -50,10 +52,11 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou Method: "POST", } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleCreate(ctx, reqHandle) } @@ -65,10 +68,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -92,10 +96,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou Method: "PUT", } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, } autogen.HandleUpdate(ctx, reqHandle) } @@ -106,7 +111,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) autogen.HandleDelete(ctx, *reqHandle) } @@ -128,14 +133,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "projectId": model.ProjectId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/v1/testname/{projectId}", diff --git a/tools/codegen/gofilegen/resource/testdata/wait-configuration.golden.go b/tools/codegen/gofilegen/resource/testdata/wait-configuration.golden.go index 44e3405a9a..f6e71d520d 100644 --- a/tools/codegen/gofilegen/resource/testdata/wait-configuration.golden.go +++ b/tools/codegen/gofilegen/resource/testdata/wait-configuration.golden.go @@ -15,6 +15,7 @@ import ( var _ resource.ResourceWithConfigure = &rs{} var _ resource.ResourceWithImportState = &rs{} +var _ autogen.ResourceAPIOperations = &rs{} const apiVersionHeader = "application/vnd.atlas.2024-05-30+json" @@ -28,6 +29,7 @@ func Resource() resource.Resource { type rs struct { config.RSCommon + autogen.DefaultResourceAPIOperations } func (r *rs) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { @@ -56,12 +58,13 @@ func (r *rs) Create(ctx context.Context, req resource.CreateRequest, resp *resou return } reqHandle := autogen.HandleCreateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, DeleteReq: func(model any) *autogen.HandleDeleteReq { - return deleteRequest(r.Client, model.(*TFModel), &resp.Diagnostics) + return deleteRequest(r, model.(*TFModel), &resp.Diagnostics) }, DeleteOnCreateTimeout: plan.DeleteOnCreateTimeout.ValueBool(), Wait: &autogen.WaitReq{ @@ -84,10 +87,11 @@ func (r *rs) Read(ctx context.Context, req resource.ReadRequest, resp *resource. return } reqHandle := autogen.HandleReadReq{ - Resp: resp, - Client: r.Client, - State: &state, - CallParams: readAPICallParams(&state), + APIOperations: r, + Resp: resp, + Client: r.Client, + State: &state, + CallParams: readAPICallParams(&state), } autogen.HandleRead(ctx, reqHandle) } @@ -116,10 +120,11 @@ func (r *rs) Update(ctx context.Context, req resource.UpdateRequest, resp *resou return } reqHandle := autogen.HandleUpdateReq{ - Resp: resp, - Client: r.Client, - Plan: &plan, - CallParams: &callParams, + APIOperations: r, + Resp: resp, + Client: r.Client, + Plan: &plan, + CallParams: &callParams, Wait: &autogen.WaitReq{ StateProperty: "state", PendingStates: []string{"UPDATING"}, @@ -139,7 +144,7 @@ func (r *rs) Delete(ctx context.Context, req resource.DeleteRequest, resp *resou if resp.Diagnostics.HasError() { return } - reqHandle := deleteRequest(r.Client, &state, &resp.Diagnostics) + reqHandle := deleteRequest(r, &state, &resp.Diagnostics) timeout, diags := state.Timeouts.Delete(ctx, 300*time.Second) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -175,14 +180,15 @@ func readAPICallParams(model any) *config.APICallParams { } } -func deleteRequest(client *config.MongoDBClient, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { +func deleteRequest(r *rs, model *TFModel, diags *diag.Diagnostics) *autogen.HandleDeleteReq { pathParams := map[string]string{ "projectId": model.ProjectId.ValueString(), } return &autogen.HandleDeleteReq{ - Client: client, - State: model, - Diags: diags, + APIOperations: r, + Client: r.Client, + State: model, + Diags: diags, CallParams: &config.APICallParams{ VersionHeader: apiVersionHeader, RelativePath: "/api/v1/testname/{projectId}", diff --git a/tools/codegen/gofilegen/schema/schema_file_test.go b/tools/codegen/gofilegen/schema/schema_file_test.go index a2a201f62c..bbfd4070a9 100644 --- a/tools/codegen/gofilegen/schema/schema_file_test.go +++ b/tools/codegen/gofilegen/schema/schema_file_test.go @@ -43,8 +43,8 @@ func doubleCustomNestedListAttr(ancestorName string) codespec.Attribute { } type schemaGenerationTestCase struct { - inputModel codespec.Resource goldenFileName string + inputModel codespec.Resource } //nolint:funlen // Long test data diff --git a/tools/codegen/models/org_service_account_secret_api.yaml b/tools/codegen/models/org_service_account_secret_api.yaml new file mode 100755 index 0000000000..467877d35f --- /dev/null +++ b/tools/codegen/models/org_service_account_secret_api.yaml @@ -0,0 +1,93 @@ +schema: + description: Create a secret for the specified Service Account. + attributes: + - string: {} + description: The Client ID of the Service Account. + computed_optional_required: required + tf_schema_name: client_id + tf_model_name: ClientId + req_body_usage: omit_always + sensitive: false + create_only: true + - string: {} + description: The date that the secret was created on. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + computed_optional_required: computed + tf_schema_name: created_at + tf_model_name: CreatedAt + req_body_usage: omit_always + sensitive: false + create_only: false + - string: {} + description: The date for the expiration of the secret. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + computed_optional_required: computed + tf_schema_name: expires_at + tf_model_name: ExpiresAt + req_body_usage: omit_always + sensitive: false + create_only: false + - string: {} + description: Unique 24-hexadecimal digit string that identifies the secret. + computed_optional_required: computed + tf_schema_name: id + tf_model_name: Id + req_body_usage: omit_always + sensitive: false + create_only: false + - string: {} + description: The last time the secret was used. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + computed_optional_required: computed + tf_schema_name: last_used_at + tf_model_name: LastUsedAt + req_body_usage: omit_always + sensitive: false + create_only: false + - string: {} + description: The masked Service Account secret. + computed_optional_required: computed + tf_schema_name: masked_secret_value + tf_model_name: MaskedSecretValue + req_body_usage: omit_always + sensitive: false + create_only: false + - string: {} + description: Unique 24-hexadecimal digit string that identifies the organization that contains your projects. Use the [/orgs](#tag/Organizations/operation/listOrganizations) endpoint to retrieve all organizations to which the authenticated user has access. + computed_optional_required: required + tf_schema_name: org_id + tf_model_name: OrgId + req_body_usage: omit_always + sensitive: false + create_only: true + - string: {} + description: The secret for the Service Account. It will be returned only the first time after creation. + computed_optional_required: computed + tf_schema_name: secret + tf_model_name: Secret + req_body_usage: omit_always + sensitive: true + create_only: false + - int64: {} + description: The expiration time of the new Service Account secret, provided in hours. The minimum and maximum allowed expiration times are subject to change and are controlled by the organization's settings. + computed_optional_required: required + tf_schema_name: secret_expires_after_hours + tf_model_name: SecretExpiresAfterHours + req_body_usage: omit_in_update_body + sensitive: false + create_only: true +operations: + delete: + http_method: DELETE + path: /api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}/secrets/{id} + create: + http_method: POST + path: /api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId}/secrets + read: + http_method: GET + path: /api/atlas/v2/orgs/{orgId}/serviceAccounts/{clientId} + update: null + version_header: application/vnd.atlas.2024-08-05+json +name: org_service_account_secret_api +packageName: orgserviceaccountsecretapi +id_attributes: + - id + - org_id + - client_id