1package mongodbatlas
2
3import (
4	"context"
5	"fmt"
6	"net/http"
7)
8
9const privateEndpointsPath = "groups/%s/privateEndpoint"
10
11// PrivateEndpointsService is an interface for interfacing with the Private Endpoints
12// of the MongoDB Atlas API.
13// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint/
14type PrivateEndpointsService interface {
15	Create(context.Context, string, *PrivateEndpointConnection) (*PrivateEndpointConnection, *Response, error)
16	Get(context.Context, string, string) (*PrivateEndpointConnection, *Response, error)
17	List(context.Context, string, *ListOptions) ([]PrivateEndpointConnection, *Response, error)
18	Delete(context.Context, string, string) (*Response, error)
19	AddOneInterfaceEndpoint(context.Context, string, string, string) (*InterfaceEndpointConnection, *Response, error)
20	GetOneInterfaceEndpoint(context.Context, string, string, string) (*InterfaceEndpointConnection, *Response, error)
21	DeleteOneInterfaceEndpoint(context.Context, string, string, string) (*Response, error)
22}
23
24// PrivateEndpointsServiceOp handles communication with the PrivateEndpoints related methods
25// of the MongoDB Atlas API
26type PrivateEndpointsServiceOp service
27
28var _ PrivateEndpointsService = &PrivateEndpointsServiceOp{}
29
30// PrivateEndpointConnection represents MongoDB Private Endpoint Connection.
31type PrivateEndpointConnection struct {
32	ID                  string   `json:"id,omitempty"`                  // Unique identifier of the AWS PrivateLink connection.
33	ProviderName        string   `json:"providerName,omitempty"`        // Name of the cloud provider you want to create the private endpoint connection for. Must be AWS.
34	Region              string   `json:"region,omitempty"`              // Cloud provider region in which you want to create the private endpoint connection.
35	EndpointServiceName string   `json:"endpointServiceName,omitempty"` // Name of the PrivateLink endpoint service in AWS. Returns null while the endpoint service is being created.
36	ErrorMessage        string   `json:"errorMessage,omitempty"`        // Error message pertaining to the AWS PrivateLink connection. Returns null if there are no errors.
37	InterfaceEndpoints  []string `json:"interfaceEndpoints,omitempty"`  // Unique identifiers of the interface endpoints in your VPC that you added to the AWS PrivateLink connection.
38	Status              string   `json:"status,omitempty"`              // Status of the AWS PrivateLink connection: INITIATING, WAITING_FOR_USER, FAILED, DELETING.
39}
40
41// InterfaceEndpointConnection represents MongoDB Interface Endpoint Connection.
42type InterfaceEndpointConnection struct {
43	ID               string `json:"interfaceEndpointId,omitempty"` // Unique identifier of the interface endpoint.
44	DeleteRequested  *bool  `json:"deleteRequested,omitempty"`     // Indicates if Atlas received a request to remove the interface endpoint from the private endpoint connection.
45	ErrorMessage     string `json:"errorMessage,omitempty"`        // Error message pertaining to the interface endpoint. Returns null if there are no errors.
46	ConnectionStatus string `json:"connectionStatus,omitempty"`    // Status of the interface endpoint: NONE, PENDING_ACCEPTANCE, PENDING, AVAILABLE, REJECTED, DELETING.
47}
48
49// Create one private endpoint connection in an Atlas project.
50// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-create-one-private-endpoint-connection/
51func (s *PrivateEndpointsServiceOp) Create(ctx context.Context, groupID string, createRequest *PrivateEndpointConnection) (*PrivateEndpointConnection, *Response, error) {
52	if groupID == "" {
53		return nil, nil, NewArgError("groupID", "must be set")
54	}
55	if createRequest == nil {
56		return nil, nil, NewArgError("createRequest", "cannot be nil")
57	}
58
59	path := fmt.Sprintf(privateEndpointsPath, groupID)
60
61	req, err := s.Client.NewRequest(ctx, http.MethodPost, path, createRequest)
62	if err != nil {
63		return nil, nil, err
64	}
65
66	root := new(PrivateEndpointConnection)
67	resp, err := s.Client.Do(ctx, req, root)
68	if err != nil {
69		return nil, resp, err
70	}
71
72	return root, resp, err
73}
74
75// Get retrieves details for one private endpoint connection by ID in an Atlas project.
76// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-get-one-private-endpoint-connection/
77func (s *PrivateEndpointsServiceOp) Get(ctx context.Context, groupID, privateLinkID string) (*PrivateEndpointConnection, *Response, error) {
78	if groupID == "" {
79		return nil, nil, NewArgError("groupID", "must be set")
80	}
81	if privateLinkID == "" {
82		return nil, nil, NewArgError("privateLinkID", "must be set")
83	}
84
85	basePath := fmt.Sprintf(privateEndpointsPath, groupID)
86	path := fmt.Sprintf("%s/%s", basePath, privateLinkID)
87
88	req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
89	if err != nil {
90		return nil, nil, err
91	}
92
93	root := new(PrivateEndpointConnection)
94	resp, err := s.Client.Do(ctx, req, root)
95	if err != nil {
96		return nil, resp, err
97	}
98
99	return root, resp, err
100}
101
102// List retrieves details for all private endpoint connections in an Atlas project.
103// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-get-all-private-endpoint-connections/
104func (s *PrivateEndpointsServiceOp) List(ctx context.Context, groupID string, listOptions *ListOptions) ([]PrivateEndpointConnection, *Response, error) {
105	if groupID == "" {
106		return nil, nil, NewArgError("groupID", "must be set")
107	}
108
109	path := fmt.Sprintf(privateEndpointsPath, groupID)
110
111	// Add query params from listOptions
112	path, err := setListOptions(path, listOptions)
113	if err != nil {
114		return nil, nil, err
115	}
116
117	req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
118	if err != nil {
119		return nil, nil, err
120	}
121
122	root := new([]PrivateEndpointConnection)
123	resp, err := s.Client.Do(ctx, req, root)
124	if err != nil {
125		return nil, resp, err
126	}
127
128	return *root, resp, nil
129}
130
131// Delete removes one private endpoint connection in an Atlas project.
132// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-delete-one-private-endpoint-connection/
133func (s *PrivateEndpointsServiceOp) Delete(ctx context.Context, groupID, privateLinkID string) (*Response, error) {
134	if groupID == "" {
135		return nil, NewArgError("groupID", "must be set")
136	}
137	if privateLinkID == "" {
138		return nil, NewArgError("privateLinkID", "must be set")
139	}
140
141	basePath := fmt.Sprintf(privateEndpointsPath, groupID)
142	path := fmt.Sprintf("%s/%s", basePath, privateLinkID)
143
144	req, err := s.Client.NewRequest(ctx, http.MethodDelete, path, nil)
145	if err != nil {
146		return nil, err
147	}
148
149	return s.Client.Do(ctx, req, nil)
150}
151
152// AddOneInterfaceEndpoint adds one interface endpoint to a private endpoint connection in an Atlas project.
153// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-create-one-interface-endpoint/
154func (s *PrivateEndpointsServiceOp) AddOneInterfaceEndpoint(ctx context.Context, groupID, privateLinkID, interfaceEndpointID string) (*InterfaceEndpointConnection, *Response, error) {
155	if groupID == "" {
156		return nil, nil, NewArgError("groupID", "must be set")
157	}
158	if privateLinkID == "" {
159		return nil, nil, NewArgError("privateLinkID", "must be set")
160	}
161	if interfaceEndpointID == "" {
162		return nil, nil, NewArgError("interfaceEndpointID", "must be set")
163	}
164
165	basePath := fmt.Sprintf(privateEndpointsPath, groupID)
166	path := fmt.Sprintf("%s/%s/interfaceEndpoints", basePath, privateLinkID)
167
168	req, err := s.Client.NewRequest(ctx, http.MethodPost, path, &InterfaceEndpointConnection{ID: interfaceEndpointID})
169	if err != nil {
170		return nil, nil, err
171	}
172
173	root := new(InterfaceEndpointConnection)
174	resp, err := s.Client.Do(ctx, req, root)
175	if err != nil {
176		return nil, resp, err
177	}
178
179	return root, resp, err
180}
181
182// GetOneInterfaceEndpoint retrieves one interface endpoint in a private endpoint connection in an Atlas project.
183// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-get-one-interface-endpoint/
184func (s *PrivateEndpointsServiceOp) GetOneInterfaceEndpoint(ctx context.Context, groupID, privateLinkID, interfaceEndpointID string) (*InterfaceEndpointConnection, *Response, error) {
185	if groupID == "" {
186		return nil, nil, NewArgError("groupID", "must be set")
187	}
188	if privateLinkID == "" {
189		return nil, nil, NewArgError("privateLinkID", "must be set")
190	}
191	if interfaceEndpointID == "" {
192		return nil, nil, NewArgError("interfaceEndpointID", "must be set")
193	}
194
195	basePath := fmt.Sprintf(privateEndpointsPath, groupID)
196	path := fmt.Sprintf("%s/%s/interfaceEndpoints/%s", basePath, privateLinkID, interfaceEndpointID)
197
198	req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
199	if err != nil {
200		return nil, nil, err
201	}
202
203	root := new(InterfaceEndpointConnection)
204	resp, err := s.Client.Do(ctx, req, root)
205	if err != nil {
206		return nil, resp, err
207	}
208
209	return root, resp, err
210}
211
212// DeleteOneInterfaceEndpoint removes one interface endpoint from a private endpoint connection in an Atlas project.
213// See more: https://docs.atlas.mongodb.com/reference/api/private-endpoint-delete-one-interface-endpoint/
214func (s *PrivateEndpointsServiceOp) DeleteOneInterfaceEndpoint(ctx context.Context, groupID, privateLinkID, interfaceEndpointID string) (*Response, error) {
215	if groupID == "" {
216		return nil, NewArgError("groupID", "must be set")
217	}
218	if privateLinkID == "" {
219		return nil, NewArgError("privateLinkID", "must be set")
220	}
221	if interfaceEndpointID == "" {
222		return nil, NewArgError("interfaceEndpointID", "must be set")
223	}
224
225	basePath := fmt.Sprintf(privateEndpointsPath, groupID)
226	path := fmt.Sprintf("%s/%s/interfaceEndpoints/%s", basePath, privateLinkID, interfaceEndpointID)
227
228	req, err := s.Client.NewRequest(ctx, http.MethodDelete, path, nil)
229	if err != nil {
230		return nil, err
231	}
232
233	return s.Client.Do(ctx, req, nil)
234}
235