blob: 914c593e33ee36b086c5ed2b6505d276f2c469a2 [file] [log] [blame]
Jamie Hannaford9fdda582015-02-10 12:15:43 +01001package instances
2
3import (
4 "fmt"
5
6 "github.com/racker/perigee"
7 "github.com/rackspace/gophercloud"
8)
9
10// CreateOptsBuilder is the top-level interface for create options.
11type CreateOptsBuilder interface {
12 ToInstanceCreateMap() (map[string]interface{}, error)
13}
14
15// DatabaseOpts is the struct responsible for configuring a database; often in
16// the context of an instance.
17type DatabaseOpts struct {
18 // Specifies the name of the database. Optional.
19 Name string
20
21 // Set of symbols and encodings. Optional; the default character set is utf8.
22 CharSet string
23
24 // Set of rules for comparing characters in a character set. Optional; the
25 // default value for collate is utf8_general_ci.
26 Collate string
27}
28
29func (opts DatabaseOpts) ToMap() (map[string]string, error) {
30 db := map[string]string{}
31 if opts.Name != "" {
32 db["name"] = opts.Name
33 }
34 if opts.CharSet != "" {
35 db["character_set"] = opts.CharSet
36 }
37 if opts.Collate != "" {
38 db["collate"] = opts.Collate
39 }
40 return db, nil
41}
42
43type DatabasesOpts []DatabaseOpts
44
45func (opts DatabasesOpts) ToMap() ([]map[string]string, error) {
46 var dbs []map[string]string
47 for _, db := range opts {
48 dbMap, err := db.ToMap()
49 if err != nil {
50 return dbs, err
51 }
52 dbs = append(dbs, dbMap)
53 }
54 return dbs, nil
55}
56
57// UserOpts is the struct responsible for configuring a user; often in the
58// context of an instance.
59type UserOpts struct {
60 // Specifies a name for the user.
61 Name string
62
63 // Specifies a password for the user.
64 Password string
65
66 // An array of databases that this user will connect to. The `name` field is
67 // the only requirement for each option.
68 Databases []DatabaseOpts
69
70 // Specifies the host from which a user is allowed to connect to the database.
71 // Possible values are a string containing an IPv4 address or "%" to allow
72 // connecting from any host. Optional; the default is "%".
73 Host string
74}
75
76func (opts UserOpts) ToMap() (map[string]interface{}, error) {
77 user := map[string]interface{}{}
78
79 if opts.Name != "" {
80 user["name"] = opts.Name
81 }
82 if opts.Password != "" {
83 user["password"] = opts.Password
84 }
85 if opts.Host != "" {
86 user["host"] = opts.Host
87 }
88
89 var dbs []map[string]string
90 for _, db := range opts.Databases {
91 dbs = append(dbs, map[string]string{"name": db.Name})
92 }
93 if len(dbs) > 0 {
94 user["databases"] = dbs
95 }
96
97 return user, nil
98}
99
100type UsersOpts []UserOpts
101
102func (opts UsersOpts) ToMap() ([]map[string]interface{}, error) {
103 var users []map[string]interface{}
104 for _, opt := range opts {
105 user, err := opt.ToMap()
106 if err != nil {
107 return users, err
108 }
109 users = append(users, user)
110 }
111 return users, nil
112}
113
114// CreateOpts is the struct responsible for configuring a new database instance.
115type CreateOpts struct {
116 // Either the integer UUID (in string form) of the flavor, or its URI
117 // reference as specified in the response from the List() call. Required.
118 FlavorRef string
119
120 // Specifies the volume size in gigabytes (GB). The value must be between 1
121 // and 300. Required.
122 Size int
123
124 // Name of the instance to create. The length of the name is limited to
125 // 255 characters and any characters are permitted. Optional.
126 Name string
127
128 // A slice of database information options.
129 Databases DatabasesOpts
130
131 // A slice of user information options.
132 Users UsersOpts
133}
134
135func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
136 if opts.Size > 300 || opts.Size < 1 {
137 return nil, fmt.Errorf("Size (GB) must be between 1-300")
138 }
139 if opts.FlavorRef == "" {
140 return nil, fmt.Errorf("FlavorRef is a required field")
141 }
142
143 instance := map[string]interface{}{
144 "volume": map[string]int{"size": opts.Size},
145 "flavorRef": opts.FlavorRef,
146 }
147
148 if opts.Name != "" {
149 instance["name"] = opts.Name
150 }
151 if len(opts.Databases) > 0 {
152 dbs, err := opts.Databases.ToMap()
153 if err != nil {
154 return nil, err
155 }
156 instance["databases"] = dbs
157 }
158 if len(opts.Users) > 0 {
159 users, err := opts.Users.ToMap()
160 if err != nil {
161 return nil, err
162 }
163 instance["users"] = users
164 }
165
166 return map[string]interface{}{"instance": instance}, nil
167}
168
169// Create will provision a new Database instance.
170func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
171 var res CreateResult
172
173 reqBody, err := opts.ToInstanceCreateMap()
174 if err != nil {
175 res.Err = err
176 return res
177 }
178
179 resp, err := perigee.Request("POST", createURL(client), perigee.Options{
180 MoreHeaders: client.AuthenticatedHeaders(),
181 ReqBody: &reqBody,
182 Results: &res.Body,
183 OkCodes: []int{200},
184 })
185
186 res.Header = resp.HttpResponse.Header
187 res.Err = err
188
189 return res
190}