blob: 6fe423b987c49d4612031504dbf5e750d5798ba9 [file] [log] [blame]
package instances
import (
"fmt"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
)
// CreateOptsBuilder is the top-level interface for create options.
type CreateOptsBuilder interface {
ToInstanceCreateMap() (map[string]interface{}, error)
}
// DatabaseOpts is the struct responsible for configuring a database; often in
// the context of an instance.
type DatabaseOpts struct {
// Specifies the name of the database. Optional.
Name string
// Set of symbols and encodings. Optional; the default character set is utf8.
CharSet string
// Set of rules for comparing characters in a character set. Optional; the
// default value for collate is utf8_general_ci.
Collate string
}
func (opts DatabaseOpts) ToMap() (map[string]string, error) {
db := map[string]string{}
if opts.Name != "" {
db["name"] = opts.Name
}
if opts.CharSet != "" {
db["character_set"] = opts.CharSet
}
if opts.Collate != "" {
db["collate"] = opts.Collate
}
return db, nil
}
type DatabasesOpts []DatabaseOpts
func (opts DatabasesOpts) ToMap() ([]map[string]string, error) {
var dbs []map[string]string
for _, db := range opts {
dbMap, err := db.ToMap()
if err != nil {
return dbs, err
}
dbs = append(dbs, dbMap)
}
return dbs, nil
}
// UserOpts is the struct responsible for configuring a user; often in the
// context of an instance.
type UserOpts struct {
// Specifies a name for the user.
Name string
// Specifies a password for the user.
Password string
// An array of databases that this user will connect to. The `name` field is
// the only requirement for each option.
Databases []DatabaseOpts
// Specifies the host from which a user is allowed to connect to the database.
// Possible values are a string containing an IPv4 address or "%" to allow
// connecting from any host. Optional; the default is "%".
Host string
}
func (opts UserOpts) ToMap() (map[string]interface{}, error) {
user := map[string]interface{}{}
if opts.Name != "" {
user["name"] = opts.Name
}
if opts.Password != "" {
user["password"] = opts.Password
}
if opts.Host != "" {
user["host"] = opts.Host
}
var dbs []map[string]string
for _, db := range opts.Databases {
dbs = append(dbs, map[string]string{"name": db.Name})
}
if len(dbs) > 0 {
user["databases"] = dbs
}
return user, nil
}
type UsersOpts []UserOpts
func (opts UsersOpts) ToMap() ([]map[string]interface{}, error) {
var users []map[string]interface{}
for _, opt := range opts {
user, err := opt.ToMap()
if err != nil {
return users, err
}
users = append(users, user)
}
return users, nil
}
// CreateOpts is the struct responsible for configuring a new database instance.
type CreateOpts struct {
// Either the integer UUID (in string form) of the flavor, or its URI
// reference as specified in the response from the List() call. Required.
FlavorRef string
// Specifies the volume size in gigabytes (GB). The value must be between 1
// and 300. Required.
Size int
// Name of the instance to create. The length of the name is limited to
// 255 characters and any characters are permitted. Optional.
Name string
// A slice of database information options.
Databases DatabasesOpts
// A slice of user information options.
Users UsersOpts
}
func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
if opts.Size > 300 || opts.Size < 1 {
return nil, fmt.Errorf("Size (GB) must be between 1-300")
}
if opts.FlavorRef == "" {
return nil, fmt.Errorf("FlavorRef is a required field")
}
instance := map[string]interface{}{
"volume": map[string]int{"size": opts.Size},
"flavorRef": opts.FlavorRef,
}
if opts.Name != "" {
instance["name"] = opts.Name
}
if len(opts.Databases) > 0 {
dbs, err := opts.Databases.ToMap()
if err != nil {
return nil, err
}
instance["databases"] = dbs
}
if len(opts.Users) > 0 {
users, err := opts.Users.ToMap()
if err != nil {
return nil, err
}
instance["users"] = users
}
return map[string]interface{}{"instance": instance}, nil
}
// Create will provision a new Database instance.
func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
var res CreateResult
reqBody, err := opts.ToInstanceCreateMap()
if err != nil {
res.Err = err
return res
}
resp, err := perigee.Request("POST", baseURL(client), perigee.Options{
MoreHeaders: client.AuthenticatedHeaders(),
ReqBody: &reqBody,
Results: &res.Body,
OkCodes: []int{200},
})
res.Header = resp.HttpResponse.Header
res.Err = err
return res
}
func List(client *gophercloud.ServiceClient) pagination.Pager {
createPageFn := func(r pagination.PageResult) pagination.Page {
return InstancePage{pagination.LinkedPageBase{PageResult: r}}
}
return pagination.NewPager(client, baseURL(client), createPageFn)
}
func Get(client *gophercloud.ServiceClient, id string) GetResult {
var res GetResult
resp, err := perigee.Request("GET", resourceURL(client, id), perigee.Options{
MoreHeaders: client.AuthenticatedHeaders(),
Results: &res.Body,
OkCodes: []int{200},
})
res.Header = resp.HttpResponse.Header
res.Err = err
return res
}
func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
var res DeleteResult
resp, err := perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
MoreHeaders: client.AuthenticatedHeaders(),
OkCodes: []int{202},
})
res.Header = resp.HttpResponse.Header
res.Err = err
return res
}