package linodego import ( "context" "encoding/json" "fmt" "time" "github.com/go-resty/resty/v2" "github.com/linode/linodego/internal/parseabletime" ) type MySQLDatabaseTarget string type MySQLDatabaseMaintenanceWindow = DatabaseMaintenanceWindow const ( MySQLDatabaseTargetPrimary MySQLDatabaseTarget = "primary" MySQLDatabaseTargetSecondary MySQLDatabaseTarget = "secondary" ) // A MySQLDatabase is a instance of Linode MySQL Managed Databases type MySQLDatabase struct { ID int `json:"id"` Status DatabaseStatus `json:"status"` Label string `json:"label"` Hosts DatabaseHost `json:"hosts"` Region string `json:"region"` Type string `json:"type"` Engine string `json:"engine"` Version string `json:"version"` ClusterSize int `json:"cluster_size"` ReplicationType string `json:"replication_type"` SSLConnection bool `json:"ssl_connection"` Encrypted bool `json:"encrypted"` AllowList []string `json:"allow_list"` InstanceURI string `json:"instance_uri"` Created *time.Time `json:"-"` Updated *time.Time `json:"-"` Updates DatabaseMaintenanceWindow `json:"updates"` } func (d *MySQLDatabase) UnmarshalJSON(b []byte) error { type Mask MySQLDatabase p := struct { *Mask Created *parseabletime.ParseableTime `json:"created"` Updated *parseabletime.ParseableTime `json:"updated"` }{ Mask: (*Mask)(d), } if err := json.Unmarshal(b, &p); err != nil { return err } d.Created = (*time.Time)(p.Created) d.Updated = (*time.Time)(p.Updated) return nil } // MySQLCreateOptions fields are used when creating a new MySQL Database type MySQLCreateOptions struct { Label string `json:"label"` Region string `json:"region"` Type string `json:"type"` Engine string `json:"engine"` AllowList []string `json:"allow_list,omitempty"` ReplicationType string `json:"replication_type,omitempty"` ClusterSize int `json:"cluster_size,omitempty"` Encrypted bool `json:"encrypted,omitempty"` SSLConnection bool `json:"ssl_connection,omitempty"` } // MySQLUpdateOptions fields are used when altering the existing MySQL Database type MySQLUpdateOptions struct { Label string `json:"label,omitempty"` AllowList *[]string `json:"allow_list,omitempty"` Updates *DatabaseMaintenanceWindow `json:"updates,omitempty"` } // MySQLDatabaseBackup is information for interacting with a backup for the existing MySQL Database type MySQLDatabaseBackup struct { ID int `json:"id"` Label string `json:"label"` Type string `json:"type"` Created *time.Time `json:"-"` } // MySQLBackupCreateOptions are options used for CreateMySQLDatabaseBackup(...) type MySQLBackupCreateOptions struct { Label string `json:"label"` Target MySQLDatabaseTarget `json:"target"` } func (d *MySQLDatabaseBackup) UnmarshalJSON(b []byte) error { type Mask MySQLDatabaseBackup p := struct { *Mask Created *parseabletime.ParseableTime `json:"created"` }{ Mask: (*Mask)(d), } if err := json.Unmarshal(b, &p); err != nil { return err } d.Created = (*time.Time)(p.Created) return nil } type MySQLDatabasesPagedResponse struct { *PageOptions Data []MySQLDatabase `json:"data"` } func (MySQLDatabasesPagedResponse) endpoint(_ ...any) string { return "databases/mysql/instances" } func (resp *MySQLDatabasesPagedResponse) castResult(r *resty.Request, e string) (int, int, error) { res, err := coupleAPIErrors(r.SetResult(MySQLDatabasesPagedResponse{}).Get(e)) if err != nil { return 0, 0, err } castedRes := res.Result().(*MySQLDatabasesPagedResponse) resp.Data = append(resp.Data, castedRes.Data...) return castedRes.Pages, castedRes.Results, nil } // MySQLDatabaseCredential is the Root Credentials to access the Linode Managed Database type MySQLDatabaseCredential struct { Username string `json:"username"` Password string `json:"password"` } // MySQLDatabaseSSL is the SSL Certificate to access the Linode Managed MySQL Database type MySQLDatabaseSSL struct { CACertificate []byte `json:"ca_certificate"` } // ListMySQLDatabases lists all MySQL Databases associated with the account func (c *Client) ListMySQLDatabases(ctx context.Context, opts *ListOptions) ([]MySQLDatabase, error) { response := MySQLDatabasesPagedResponse{} err := c.listHelper(ctx, &response, opts) if err != nil { return nil, err } return response.Data, nil } type MySQLDatabaseBackupsPagedResponse struct { *PageOptions Data []MySQLDatabaseBackup `json:"data"` } func (MySQLDatabaseBackupsPagedResponse) endpoint(ids ...any) string { id := ids[0].(int) return fmt.Sprintf("databases/mysql/instances/%d/backups", id) } func (resp *MySQLDatabaseBackupsPagedResponse) castResult(r *resty.Request, e string) (int, int, error) { res, err := coupleAPIErrors(r.SetResult(MySQLDatabaseBackupsPagedResponse{}).Get(e)) if err != nil { return 0, 0, err } castedRes := res.Result().(*MySQLDatabaseBackupsPagedResponse) resp.Data = append(resp.Data, castedRes.Data...) return castedRes.Pages, castedRes.Results, nil } // ListMySQLDatabaseBackups lists all MySQL Database Backups associated with the given MySQL Database func (c *Client) ListMySQLDatabaseBackups(ctx context.Context, databaseID int, opts *ListOptions) ([]MySQLDatabaseBackup, error) { response := MySQLDatabaseBackupsPagedResponse{} err := c.listHelper(ctx, &response, opts, databaseID) if err != nil { return nil, err } return response.Data, nil } // GetMySQLDatabase returns a single MySQL Database matching the id func (c *Client) GetMySQLDatabase(ctx context.Context, databaseID int) (*MySQLDatabase, error) { e := fmt.Sprintf("databases/mysql/instances/%d", databaseID) req := c.R(ctx).SetResult(&MySQLDatabase{}) r, err := coupleAPIErrors(req.Get(e)) if err != nil { return nil, err } return r.Result().(*MySQLDatabase), nil } // CreateMySQLDatabase creates a new MySQL Database using the createOpts as configuration, returns the new MySQL Database func (c *Client) CreateMySQLDatabase(ctx context.Context, opts MySQLCreateOptions) (*MySQLDatabase, error) { body, err := json.Marshal(opts) if err != nil { return nil, err } e := "databases/mysql/instances" req := c.R(ctx).SetResult(&MySQLDatabase{}).SetBody(string(body)) r, err := coupleAPIErrors(req.Post(e)) if err != nil { return nil, err } return r.Result().(*MySQLDatabase), nil } // DeleteMySQLDatabase deletes an existing MySQL Database with the given id func (c *Client) DeleteMySQLDatabase(ctx context.Context, databaseID int) error { e := fmt.Sprintf("databases/mysql/instances/%d", databaseID) _, err := coupleAPIErrors(c.R(ctx).Delete(e)) return err } // UpdateMySQLDatabase updates the given MySQL Database with the provided opts, returns the MySQLDatabase with the new settings func (c *Client) UpdateMySQLDatabase(ctx context.Context, databaseID int, opts MySQLUpdateOptions) (*MySQLDatabase, error) { body, err := json.Marshal(opts) if err != nil { return nil, err } e := fmt.Sprintf("databases/mysql/instances/%d", databaseID) req := c.R(ctx).SetResult(&MySQLDatabase{}).SetBody(string(body)) r, err := coupleAPIErrors(req.Put(e)) if err != nil { return nil, err } return r.Result().(*MySQLDatabase), nil } // GetMySQLDatabaseSSL returns the SSL Certificate for the given MySQL Database func (c *Client) GetMySQLDatabaseSSL(ctx context.Context, databaseID int) (*MySQLDatabaseSSL, error) { e := fmt.Sprintf("databases/mysql/instances/%d/ssl", databaseID) req := c.R(ctx).SetResult(&MySQLDatabaseSSL{}) r, err := coupleAPIErrors(req.Get(e)) if err != nil { return nil, err } return r.Result().(*MySQLDatabaseSSL), nil } // GetMySQLDatabaseCredentials returns the Root Credentials for the given MySQL Database func (c *Client) GetMySQLDatabaseCredentials(ctx context.Context, databaseID int) (*MySQLDatabaseCredential, error) { e := fmt.Sprintf("databases/mysql/instances/%d/credentials", databaseID) req := c.R(ctx).SetResult(&MySQLDatabaseCredential{}) r, err := coupleAPIErrors(req.Get(e)) if err != nil { return nil, err } return r.Result().(*MySQLDatabaseCredential), nil } // ResetMySQLDatabaseCredentials returns the Root Credentials for the given MySQL Database (may take a few seconds to work) func (c *Client) ResetMySQLDatabaseCredentials(ctx context.Context, databaseID int) error { e := fmt.Sprintf("databases/mysql/instances/%d/credentials/reset", databaseID) _, err := coupleAPIErrors(c.R(ctx).Post(e)) return err } // GetMySQLDatabaseBackup returns a specific MySQL Database Backup with the given ids func (c *Client) GetMySQLDatabaseBackup(ctx context.Context, databaseID int, backupID int) (*MySQLDatabaseBackup, error) { e := fmt.Sprintf("databases/mysql/instances/%d/backups/%d", databaseID, backupID) req := c.R(ctx).SetResult(&MySQLDatabaseBackup{}) r, err := coupleAPIErrors(req.Get(e)) if err != nil { return nil, err } return r.Result().(*MySQLDatabaseBackup), nil } // RestoreMySQLDatabaseBackup returns the given MySQL Database with the given Backup func (c *Client) RestoreMySQLDatabaseBackup(ctx context.Context, databaseID int, backupID int) error { e := fmt.Sprintf("databases/mysql/instances/%d/backups/%d/restore", databaseID, backupID) _, err := coupleAPIErrors(c.R(ctx).Post(e)) return err } // CreateMySQLDatabaseBackup creates a snapshot for the given MySQL database func (c *Client) CreateMySQLDatabaseBackup(ctx context.Context, databaseID int, opts MySQLBackupCreateOptions) error { body, err := json.Marshal(opts) if err != nil { return err } e := fmt.Sprintf("databases/mysql/instances/%d/backups", databaseID) _, err = coupleAPIErrors(c.R(ctx).SetBody(string(body)).Post(e)) return err } // PatchMySQLDatabase applies security patches and updates to the underlying operating system of the Managed MySQL Database func (c *Client) PatchMySQLDatabase(ctx context.Context, databaseID int) error { e := fmt.Sprintf("databases/mysql/instances/%d/patch", databaseID) _, err := coupleAPIErrors(c.R(ctx).Post(e)) return err }