1package v2
2
3import (
4	"context"
5	"net/url"
6	"time"
7
8	apiv2 "github.com/exoscale/egoscale/v2/api"
9	papi "github.com/exoscale/egoscale/v2/internal/public-api"
10)
11
12// DatabaseBackupConfig represents a Database Backup configuration.
13type DatabaseBackupConfig struct {
14	FrequentIntervalMinutes    *int64
15	FrequentOldestAgeMinutes   *int64
16	InfrequentIntervalMinutes  *int64
17	InfrequentOldestAgeMinutes *int64
18	Interval                   *int64
19	MaxCount                   *int64
20	RecoveryMode               *string
21}
22
23func databaseBackupConfigFromAPI(c *papi.DbaasBackupConfig) *DatabaseBackupConfig {
24	return &DatabaseBackupConfig{
25		FrequentIntervalMinutes:    c.FrequentIntervalMinutes,
26		FrequentOldestAgeMinutes:   c.FrequentOldestAgeMinutes,
27		InfrequentIntervalMinutes:  c.InfrequentIntervalMinutes,
28		InfrequentOldestAgeMinutes: c.InfrequentOldestAgeMinutes,
29		Interval:                   c.Interval,
30		MaxCount:                   c.MaxCount,
31		RecoveryMode:               c.RecoveryMode,
32	}
33}
34
35// DatabasePlan represents a Database Plan.
36type DatabasePlan struct {
37	BackupConfig     *DatabaseBackupConfig
38	DiskSpace        *int64
39	MaxMemoryPercent *int64
40	Name             *string
41	Nodes            *int64
42	NodeCPUs         *int64
43	NodeMemory       *int64
44}
45
46func databasePlanFromAPI(p *papi.DbaasPlan) *DatabasePlan {
47	return &DatabasePlan{
48		BackupConfig:     databaseBackupConfigFromAPI(p.BackupConfig),
49		DiskSpace:        p.DiskSpace,
50		MaxMemoryPercent: p.MaxMemoryPercent,
51		Name:             p.Name,
52		Nodes:            p.NodeCount,
53		NodeCPUs:         p.NodeCpuCount,
54		NodeMemory:       p.NodeMemory,
55	}
56}
57
58// DatabaseServiceType represents a Database Service type.
59type DatabaseServiceType struct {
60	DefaultVersion   *string
61	Description      *string
62	LatestVersion    *string
63	Name             *string
64	Plans            []*DatabasePlan
65	UserConfigSchema map[string]interface{}
66}
67
68func databaseServiceTypeFromAPI(t *papi.DbaasServiceType) *DatabaseServiceType {
69	return &DatabaseServiceType{
70		DefaultVersion: t.DefaultVersion,
71		Description:    t.Description,
72		LatestVersion:  t.LatestVersion,
73		Name:           (*string)(t.Name),
74		Plans: func() []*DatabasePlan {
75			plans := make([]*DatabasePlan, 0)
76			if t.Plans != nil {
77				for _, plan := range *t.Plans {
78					plan := plan
79					plans = append(plans, databasePlanFromAPI(&plan))
80				}
81			}
82			return plans
83		}(),
84		UserConfigSchema: func() map[string]interface{} {
85			if t.UserConfigSchema != nil {
86				return t.UserConfigSchema.AdditionalProperties
87			}
88			return nil
89		}(),
90	}
91}
92
93// DatabaseServiceBackup represents a Database Service backup.
94type DatabaseServiceBackup struct {
95	Name *string
96	Size *int64
97	Date *time.Time
98}
99
100// DatabaseServiceMaintenance represents a Database Service maintenance.
101type DatabaseServiceMaintenance struct {
102	DOW  string
103	Time string
104}
105
106func databaseServiceMaintenanceFromAPI(m *papi.DbaasServiceMaintenance) *DatabaseServiceMaintenance {
107	return &DatabaseServiceMaintenance{
108		DOW:  string(m.Dow),
109		Time: m.Time,
110	}
111}
112
113func databaseServiceBackupFromAPI(b *papi.DbaasServiceBackup) *DatabaseServiceBackup {
114	return &DatabaseServiceBackup{
115		Name: &b.BackupName,
116		Size: &b.DataSize,
117		Date: &b.BackupTime,
118	}
119}
120
121// DatabaseServiceUser represents a Database Service user.
122type DatabaseServiceUser struct {
123	Password *string
124	Type     *string
125	UserName *string
126}
127
128func databaseServiceUserFromAPI(u *papi.DbaasServiceUser) *DatabaseServiceUser {
129	return &DatabaseServiceUser{
130		Password: u.Password,
131		UserName: &u.Username,
132		Type:     &u.Type,
133	}
134}
135
136// DatabaseService represents a Database Service.
137type DatabaseService struct {
138	Backups               []*DatabaseServiceBackup
139	ConnectionInfo        map[string]interface{}
140	CreatedAt             *time.Time
141	DiskSize              *int64
142	Features              map[string]interface{}
143	Maintenance           *DatabaseServiceMaintenance
144	Metadata              map[string]interface{}
145	Name                  *string
146	Nodes                 *int64
147	NodeCPUs              *int64
148	NodeMemory            *int64
149	Plan                  *string
150	State                 *string
151	TerminationProtection *bool
152	Type                  *string
153	UpdatedAt             *time.Time
154	URI                   *url.URL
155	UserConfig            *map[string]interface{}
156	Users                 []*DatabaseServiceUser
157}
158
159func databaseServiceFromAPI(s *papi.DbaasService) *DatabaseService {
160	return &DatabaseService{
161		Backups: func() []*DatabaseServiceBackup {
162			backups := make([]*DatabaseServiceBackup, 0)
163			if s.Backups != nil {
164				for _, b := range *s.Backups {
165					backups = append(backups, databaseServiceBackupFromAPI(&b))
166				}
167			}
168			return backups
169		}(),
170		ConnectionInfo: func() (v map[string]interface{}) {
171			if s.ConnectionInfo != nil {
172				v = s.ConnectionInfo.AdditionalProperties
173			}
174			return
175		}(),
176		CreatedAt: s.CreatedAt,
177		DiskSize:  s.DiskSize,
178		Features: func() (v map[string]interface{}) {
179			if s.Features != nil {
180				v = s.Features.AdditionalProperties
181			}
182			return
183		}(),
184		Maintenance: func() (v *DatabaseServiceMaintenance) {
185			if s.Maintenance != nil {
186				return databaseServiceMaintenanceFromAPI(s.Maintenance)
187			}
188			return
189		}(),
190		Metadata: func() (v map[string]interface{}) {
191			if s.Metadata != nil {
192				v = s.Metadata.AdditionalProperties
193			}
194			return
195		}(),
196		Name:                  (*string)(&s.Name),
197		Nodes:                 s.NodeCount,
198		NodeCPUs:              s.NodeCpuCount,
199		NodeMemory:            s.NodeMemory,
200		Plan:                  &s.Plan,
201		State:                 (*string)(s.State),
202		TerminationProtection: s.TerminationProtection,
203		Type:                  (*string)(&s.Type),
204		UpdatedAt:             s.UpdatedAt,
205		URI: func() *url.URL {
206			if s.Uri != nil {
207				if u, _ := url.Parse(*s.Uri); u != nil {
208					return u
209				}
210			}
211			return nil
212		}(),
213		UserConfig: func() (v *map[string]interface{}) {
214			if s.UserConfig != nil {
215				v = &s.UserConfig.AdditionalProperties
216			}
217			return
218		}(),
219		Users: func() []*DatabaseServiceUser {
220			users := make([]*DatabaseServiceUser, 0)
221			if s.Users != nil {
222				for _, u := range *s.Users {
223					users = append(users, databaseServiceUserFromAPI(&u))
224				}
225			}
226			return users
227		}(),
228	}
229}
230
231// ListDatabaseServiceTypes returns the list of existing Database Service types.
232func (c *Client) ListDatabaseServiceTypes(ctx context.Context, zone string) ([]*DatabaseServiceType, error) {
233	list := make([]*DatabaseServiceType, 0)
234
235	resp, err := c.ListDbaasServiceTypesWithResponse(apiv2.WithZone(ctx, zone))
236	if err != nil {
237		return nil, err
238	}
239
240	if resp.JSON200.DbaasServiceTypes != nil {
241		for i := range *resp.JSON200.DbaasServiceTypes {
242			list = append(list, databaseServiceTypeFromAPI(&(*resp.JSON200.DbaasServiceTypes)[i]))
243		}
244	}
245
246	return list, nil
247}
248
249// GetDatabaseServiceType returns the Database Service type corresponding to the specified name.
250func (c *Client) GetDatabaseServiceType(ctx context.Context, zone, name string) (*DatabaseServiceType, error) {
251	resp, err := c.GetDbaasServiceTypeWithResponse(apiv2.WithZone(ctx, zone), name)
252	if err != nil {
253		return nil, err
254	}
255
256	return databaseServiceTypeFromAPI(resp.JSON200), nil
257}
258
259// CreateDatabaseService creates a Database Service.
260func (c *Client) CreateDatabaseService(
261	ctx context.Context,
262	zone string,
263	databaseService *DatabaseService,
264) (*DatabaseService, error) {
265	_, err := c.CreateDbaasServiceWithResponse(
266		apiv2.WithZone(ctx, zone),
267		papi.CreateDbaasServiceJSONRequestBody{
268			Maintenance: func() (v *struct {
269				Dow  papi.CreateDbaasServiceJSONBodyMaintenanceDow `json:"dow"`
270				Time string                                        `json:"time"`
271			}) {
272				if databaseService.Maintenance != nil {
273					v = &struct {
274						Dow  papi.CreateDbaasServiceJSONBodyMaintenanceDow `json:"dow"`
275						Time string                                        `json:"time"`
276					}{
277						Dow:  papi.CreateDbaasServiceJSONBodyMaintenanceDow(databaseService.Maintenance.DOW),
278						Time: databaseService.Maintenance.Time,
279					}
280				}
281				return
282			}(),
283			Name:                  papi.DbaasServiceName(*databaseService.Name),
284			Plan:                  *databaseService.Plan,
285			TerminationProtection: databaseService.TerminationProtection,
286			Type:                  papi.DbaasServiceTypeName(*databaseService.Type),
287			UserConfig: func() (v *papi.CreateDbaasServiceJSONBody_UserConfig) {
288				if databaseService.UserConfig != nil {
289					v = &papi.CreateDbaasServiceJSONBody_UserConfig{
290						AdditionalProperties: *databaseService.UserConfig,
291					}
292				}
293				return
294			}(),
295		})
296	if err != nil {
297		return nil, err
298	}
299
300	return c.GetDatabaseService(ctx, zone, *databaseService.Name)
301}
302
303// ListDatabaseServices returns the list of Database Services.
304func (c *Client) ListDatabaseServices(ctx context.Context, zone string) ([]*DatabaseService, error) {
305	list := make([]*DatabaseService, 0)
306
307	resp, err := c.ListDbaasServicesWithResponse(apiv2.WithZone(ctx, zone))
308	if err != nil {
309		return nil, err
310	}
311
312	if resp.JSON200.DbaasServices != nil {
313		for i := range *resp.JSON200.DbaasServices {
314			list = append(list, databaseServiceFromAPI(&(*resp.JSON200.DbaasServices)[i]))
315		}
316	}
317
318	return list, nil
319}
320
321// GetDatabaseService returns the Database Service corresponding to the specified name.
322func (c *Client) GetDatabaseService(ctx context.Context, zone, name string) (*DatabaseService, error) {
323	resp, err := c.GetDbaasServiceWithResponse(apiv2.WithZone(ctx, zone), name)
324	if err != nil {
325		return nil, err
326	}
327
328	return databaseServiceFromAPI(resp.JSON200), nil
329}
330
331// UpdateDatabaseService updates the specified Database Service.
332func (c *Client) UpdateDatabaseService(ctx context.Context, zone string, databaseService *DatabaseService) error {
333	_, err := c.UpdateDbaasServiceWithResponse(
334		apiv2.WithZone(ctx, zone),
335		*databaseService.Name,
336		papi.UpdateDbaasServiceJSONRequestBody{
337			Maintenance: func() (v *struct {
338				Dow  papi.UpdateDbaasServiceJSONBodyMaintenanceDow `json:"dow"`
339				Time string                                        `json:"time"`
340			}) {
341				if databaseService.Maintenance != nil {
342					v = &struct {
343						Dow  papi.UpdateDbaasServiceJSONBodyMaintenanceDow `json:"dow"`
344						Time string                                        `json:"time"`
345					}{
346						Dow:  papi.UpdateDbaasServiceJSONBodyMaintenanceDow(databaseService.Maintenance.DOW),
347						Time: databaseService.Maintenance.Time,
348					}
349				}
350				return
351			}(),
352			Plan:                  databaseService.Plan,
353			TerminationProtection: databaseService.TerminationProtection,
354			UserConfig: func() (v *papi.UpdateDbaasServiceJSONBody_UserConfig) {
355				if databaseService.UserConfig != nil {
356					v = &papi.UpdateDbaasServiceJSONBody_UserConfig{
357						AdditionalProperties: *databaseService.UserConfig,
358					}
359				}
360				return
361			}(),
362		})
363	if err != nil {
364		return err
365	}
366
367	return nil
368}
369
370// DeleteDatabaseService deletes the specified Database Service.
371func (c *Client) DeleteDatabaseService(ctx context.Context, zone, name string) error {
372	_, err := c.TerminateDbaasServiceWithResponse(apiv2.WithZone(ctx, zone), name)
373	if err != nil {
374		return err
375	}
376
377	return nil
378}
379