database.go raw
1 // Copyright 2022-2025 The sacloud/iaas-api-go Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package naked
16
17 import (
18 "encoding/json"
19 "strconv"
20 "strings"
21 "time"
22
23 "github.com/sacloud/iaas-api-go/types"
24 )
25
26 // Database データベース
27 type Database struct {
28 ID types.ID `json:",omitempty" yaml:"id,omitempty" structs:",omitempty"`
29 Name string `json:",omitempty" yaml:"name,omitempty" structs:",omitempty"`
30 Description string `yaml:"description"`
31 Tags types.Tags `yaml:"tags"`
32 Icon *Icon `json:",omitempty" yaml:"icon,omitempty" structs:",omitempty"`
33 CreatedAt *time.Time `json:",omitempty" yaml:"created_at,omitempty" structs:",omitempty"`
34 ModifiedAt *time.Time `json:",omitempty" yaml:"modified_at,omitempty" structs:",omitempty"`
35 Availability types.EAvailability `json:",omitempty" yaml:"availability,omitempty" structs:",omitempty"`
36 Class string `json:",omitempty" yaml:"class,omitempty" structs:",omitempty"`
37 ServiceClass string `json:",omitempty" yaml:"service_class,omitempty" structs:",omitempty"`
38 Plan *AppliancePlan `json:",omitempty" yaml:"plan,omitempty" structs:",omitempty"`
39 Instance *Instance `json:",omitempty" yaml:"instance,omitempty" structs:",omitempty"`
40 Interfaces Interfaces `json:",omitempty" yaml:"interfaces,omitempty" structs:",omitempty"`
41 Switch *Switch `json:",omitempty" yaml:"switch,omitempty" structs:",omitempty"`
42 Settings *DatabaseSettings `json:",omitempty" yaml:"settings,omitempty" structs:",omitempty"`
43 SettingsHash string `json:",omitempty" yaml:"settings_hash,omitempty" structs:",omitempty"`
44 Remark *ApplianceRemark `json:",omitempty" yaml:"remark,omitempty" structs:",omitempty"`
45 Disk *DatabaseDisk `json:",omitempty" yaml:"disk,omitempty" structs:",omitempty"`
46
47 Generation interface{}
48 }
49
50 type DatabaseDisk struct {
51 EncryptionAlgorithm types.EDiskEncryptionAlgorithm `json:",omitempty" yaml:"encryption_algorithm,omitempty" structs:",omitempty"`
52 EncryptionKey *EncryptionKey `json:",omitempty" yaml:"kms_key,omitempty" structs:",omitempty"`
53 }
54
55 // DatabaseSettingsUpdate データベース
56 type DatabaseSettingsUpdate struct {
57 Settings *DatabaseSettings `json:",omitempty" yaml:"settings,omitempty" structs:",omitempty"`
58 SettingsHash string `json:",omitempty" yaml:"settings_hash,omitempty" structs:",omitempty"`
59 }
60
61 // DatabaseSettings データベース設定
62 type DatabaseSettings struct {
63 DBConf *DatabaseSetting `json:",omitempty" yaml:"db_conf,omitempty" structs:",omitempty"`
64 MonitoringSuite *MonitoringSuite `json:",omitempty" yaml:"monitoring_suite_log,omitempty" structs:",omitempty"`
65 }
66
67 // DatabaseSetting データベース設定
68 type DatabaseSetting struct {
69 Common *DatabaseSettingCommon `json:",omitempty" yaml:"common,omitempty" structs:",omitempty"`
70 Backup *DatabaseSettingBackup `json:",omitempty" yaml:"backup,omitempty" structs:",omitempty"`
71 Backupv2 *DatabaseSettingBackupv2 `json:",omitempty" yaml:"backupv2,omitempty" structs:",omitempty"`
72 Replication *DatabaseSettingReplication `json:",omitempty" yaml:"replication,omitempty" structs:",omitempty"`
73 Interfaces DatabaseSettingInterfaces `json:",omitempty" yaml:"common,omitempty" structs:",omitempty"`
74 }
75
76 // DatabaseSettingCommon データベース設定 汎用項目設定
77 type DatabaseSettingCommon struct {
78 // WebUI WebUIの有効/無効、またはアクセスするためのアドレス
79 //
80 // [HACK] Create時はbool型、Read/Update時は文字列(FQDN or IP)となる。
81 // また、無効にするにはJSONで要素自体を指定しないことで行う。
82 WebUI interface{} `yaml:"web_ui"`
83 ServicePort int `json:",omitempty" yaml:"service_port,omitempty" structs:",omitempty"`
84 SourceNetwork DatabaseSettingSourceNetworks `yaml:"source_network"`
85 DefaultUser string `json:",omitempty" yaml:"default_user,omitempty" structs:",omitempty"`
86 UserPassword string `json:",omitempty" yaml:"user_password,omitempty" structs:",omitempty"`
87 ReplicaUser string `json:",omitempty" yaml:"replica_user,omitempty" structs:",omitempty"`
88 ReplicaPassword string `json:",omitempty" yaml:"replica_password,omitempty" structs:",omitempty"`
89 }
90
91 // DatabaseSettingSourceNetworks データベースへのアクセスを許可するCIDRリスト
92 //
93 // Note: すべての接続先を許可する場合は"0.0.0.0/0"を指定する。
94 // この処理はMarshalJSON時にDatabaseSettingSourceNetwork側で行われるため、
95 // APIクライアント側は許可したいCIDRブロックのリストを指定する。
96 // libsacloudではすべての接続を拒否する設定はサポートしない。
97 type DatabaseSettingSourceNetworks []string
98
99 // MarshalJSON すべての接続先を許可する場合は"0.0.0.0/0"を指定するための対応
100 func (d DatabaseSettingSourceNetworks) MarshalJSON() ([]byte, error) {
101 type alias DatabaseSettingSourceNetworks
102 dest := alias(d)
103
104 if len(dest) == 0 {
105 dest = append(dest, "0.0.0.0/0")
106 }
107
108 return json.Marshal(dest)
109 }
110
111 func (d *DatabaseSettingSourceNetworks) UnmarshalJSON(b []byte) error {
112 if string(b) == `""` || string(b) == "" {
113 return nil
114 }
115 type alias DatabaseSettingSourceNetworks
116
117 var a alias
118 if err := json.Unmarshal(b, &a); err != nil {
119 return err
120 }
121 if len(a) == 1 && a[0] == "0.0.0.0/0" {
122 return nil
123 }
124 *d = DatabaseSettingSourceNetworks(a)
125 return nil
126 }
127
128 // DatabaseSettingBackup データベース設定 バックアップ設定
129 type DatabaseSettingBackup struct {
130 Rotate int `json:",omitempty" yaml:"rotate,omitempty" structs:",omitempty"`
131 Time string `json:",omitempty" yaml:"time,omitempty" structs:",omitempty"`
132 DayOfWeek []types.EDayOfTheWeek `json:",omitempty" yaml:"day_of_week,omitempty" structs:",omitempty"`
133 Connect string `json:",omitempty" yaml:"connect,omitempty" structs:",omitempty"` // 冗長化オプション有効時のバックアップ先NFS 例:`nfs://192.168.0.41/export`
134 }
135
136 // DatabaseSettingBackupv2 データベース設定 継続的バックアップ(バックアップv2)設定
137 type DatabaseSettingBackupv2 struct {
138 Rotate int `json:",omitempty" yaml:"rotate,omitempty" structs:",omitempty"`
139 Time string `json:",omitempty" yaml:"time,omitempty" structs:",omitempty"`
140 DayOfWeek []types.EDayOfTheWeek `json:",omitempty" yaml:"day_of_week,omitempty" structs:",omitempty"`
141 Connect string `json:",omitempty" yaml:"connect,omitempty" structs:",omitempty"` // バックアップ先NFS: 例:`nfs://192.168.0.41/export`
142 FirstEnabledAt *time.Time `json:",omitempty" yaml:"first_enabled_at,omitempty" structs:",omitempty"`
143 }
144
145 // UnmarshalJSON 配列/オブジェクトが混在することへの対応
146 func (d *DatabaseSettingBackup) UnmarshalJSON(b []byte) error {
147 if string(b) == "[]" {
148 return nil
149 }
150 type alias DatabaseSettingBackup
151
152 var a alias
153 if err := json.Unmarshal(b, &a); err != nil {
154 return err
155 }
156 *d = DatabaseSettingBackup(a)
157 return nil
158 }
159
160 // DatabaseSettingReplication レプリケーション設定
161 type DatabaseSettingReplication struct {
162 Model types.EDatabaseReplicationModel `json:",omitempty" yaml:"model,omitempty" structs:",omitempty"`
163 Appliance *struct {
164 ID types.ID
165 } `json:",omitempty" yaml:"appliance,omitempty" structs:",omitempty"`
166 IPAddress string `json:",omitempty" yaml:"ip_address,omitempty" structs:",omitempty"`
167 Port int `json:",omitempty" yaml:"port,omitempty" structs:",omitempty"`
168 User string `json:",omitempty" yaml:"user,omitempty" structs:",omitempty"`
169 Password string `json:",omitempty" yaml:"password,omitempty" structs:",omitempty"`
170 }
171
172 type DatabaseSettingInterfaces []*DatabaseSettingInterface
173
174 type DatabaseSettingInterface struct {
175 VirtualIPAddress string `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
176 // Index 仮想フィールド、VPCルータなどでInterfaces(実体は[]*Interface)を扱う場合にUnmarshalJSONの中で設定される
177 //
178 // Findした際のAPIからの応答にも同名のフィールドが含まれるが無関係。
179 Index int `json:"-"`
180 }
181
182 // UnmarshalJSON 配列中にnullが返ってくる(VPCルータなど)への対応
183 //
184 // Note: この実装は要素として`[]`が来た場合にゼロ値として返している。
185 //
186 // クライアント側では必要に応じてnil判定ではなくゼロ値である事の判定を行う。
187 func (i *DatabaseSettingInterfaces) UnmarshalJSON(b []byte) error {
188 type alias DatabaseSettingInterfaces
189 var a alias
190 if err := json.Unmarshal(b, &a); err != nil {
191 return err
192 }
193
194 var dest []*DatabaseSettingInterface
195 for i, v := range a {
196 if v != nil {
197 if v.Index == 0 {
198 v.Index = i
199 }
200 dest = append(dest, v)
201 }
202 }
203
204 *i = DatabaseSettingInterfaces(dest)
205 return nil
206 }
207
208 // MarshalJSON 配列中にnullが入る場合(VPCルータなど)への対応
209 func (i *DatabaseSettingInterfaces) MarshalJSON() ([]byte, error) {
210 max := 0
211 for _, iface := range *i {
212 if max < iface.Index {
213 max = iface.Index
214 }
215 }
216
217 var dest = make([]*DatabaseSettingInterface, max+1)
218 for _, iface := range *i {
219 dest[iface.Index] = iface
220 }
221
222 return json.Marshal(dest)
223 }
224
225 // MarshalJSON JSON
226 func (i *DatabaseSettingInterface) MarshalJSON() ([]byte, error) {
227 type alias struct {
228 IPAddress []string `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
229 VirtualIPAddress string `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
230 IPAliases []string `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
231 NetworkMaskLen int `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
232 }
233
234 tmp := alias{
235 VirtualIPAddress: i.VirtualIPAddress,
236 }
237 return json.Marshal(tmp)
238 }
239
240 func (i *DatabaseSettingInterface) UnmarshalJSON(b []byte) error {
241 if string(b) == "[]" {
242 return nil
243 }
244 type alias DatabaseSettingInterface
245
246 var a alias
247 if err := json.Unmarshal(b, &a); err != nil {
248 return err
249 }
250 *i = DatabaseSettingInterface(a)
251 return nil
252 }
253
254 // DatabaseStatusResponse Status APIの戻り値
255 type DatabaseStatusResponse struct {
256 SettingsResponse *DatabaseStatus `json:",omitempty" yaml:"settings_response,omitempty" structs:",omitempty"`
257 }
258
259 // DatabaseStatus データベースのステータス
260 type DatabaseStatus struct {
261 Status types.EServerInstanceStatus `json:",omitempty" yaml:"status,omitempty" structs:",omitempty"`
262 IsFatal bool `json:"is_fatal"`
263 DBConf *DatabaseStatusDBConf `json:",omitempty" yaml:"db_conf,omitempty" structs:",omitempty"`
264 }
265
266 // DatabaseStatusDBConf データベース設定
267 type DatabaseStatusDBConf struct {
268 Version *DatabaseStatusVersion `json:"version,omitempty" yaml:"version,omitempty" structs:",omitempty"`
269 Log []*DatabaseLog `json:"log,omitempty" yaml:"log,omitempty" structs:",omitempty"`
270 Backup *DatabaseBackupInfo `json:"backup,omitempty" yaml:"backup,omitempty" structs:",omitempty"`
271 MariaDB *DatabaseStatusMariaDB `json:",omitempty" yaml:"maria_db,omitempty" structs:",omitempty"`
272 Postgres *DatabaseStatusPostgreSQL `json:"postgres,omitempty" yaml:"postgres,omitempty" structs:",omitempty"`
273
274 // 以下フィールドはサポートしない
275 // Replication
276 }
277
278 type DatabaseStatusMariaDB struct {
279 Status string `json:"status,omitempty"`
280 }
281 type DatabaseStatusPostgreSQL struct {
282 Status string `json:"status,omitempty"`
283 }
284
285 // DatabaseStatusVersion データベース設定バージョン情報
286 type DatabaseStatusVersion struct {
287 LastModified string `json:"lastmodified,omitempty" yaml:"last_modified,omitempty" structs:",omitempty"`
288 CommitHash string `json:"commithash,omitempty" yaml:"commit_hash,omitempty" structs:",omitempty"`
289 Status string `json:"status,omitempty" yaml:"status,omitempty" structs:",omitempty"`
290 Tag interface{} `json:"tag,omitempty" yaml:"tag,omitempty" structs:",omitempty"` // Note: `1.1`や`"1.1"`などと表記揺れがあるためここではinterface{}で受け取る
291 Expire string `json:"expire,omitempty" yaml:"expire,omitempty" structs:",omitempty"`
292 }
293
294 // DatabaseLog データベースログ
295 type DatabaseLog struct {
296 Name string `json:"name,omitempty" yaml:"name,omitempty" structs:",omitempty"`
297 Data string `json:"data,omitempty" yaml:"data,omitempty" structs:",omitempty"`
298 Size types.StringNumber `json:"size,omitempty" yaml:"size,omitempty" structs:",omitempty"`
299 }
300
301 // IsSystemdLog systemctlのログか判定
302 func (l *DatabaseLog) IsSystemdLog() bool {
303 return l.Name == "systemctl"
304 }
305
306 // Logs ログボディ取得
307 func (l *DatabaseLog) Logs() []string {
308 return strings.Split(l.Data, "\n")
309 }
310
311 // ID ログのID取得
312 func (l *DatabaseLog) ID() string {
313 return l.Name
314 }
315
316 // DatabaseBackupInfo データベースバックアップ情報
317 type DatabaseBackupInfo struct {
318 History []*DatabaseBackupHistory `json:"history,omitempty" yaml:"history,omitempty" structs:",omitempty"`
319 }
320
321 // DatabaseBackupHistory データベースバックアップ履歴情報
322 type DatabaseBackupHistory struct {
323 CreatedAt time.Time `json:"createdat,omitempty" yaml:"created_at,omitempty" structs:",omitempty"`
324 Availability string `json:"availability,omitempty" yaml:"availability,omitempty" structs:",omitempty"`
325 RecoveredAt *time.Time `json:"recoveredat,omitempty" yaml:"recovered_at,omitempty" structs:",omitempty"`
326 Size int64 `json:"size,omitempty" yaml:"size,omitempty" structs:",omitempty"`
327 }
328
329 // ID バックアップ履歴のID取得
330 func (h *DatabaseBackupHistory) ID() string {
331 return h.CreatedAt.Format(time.RFC3339)
332 }
333
334 // FormatCreatedAt 指定のレイアウトで作成日時を文字列化
335 func (h *DatabaseBackupHistory) FormatCreatedAt(layout string) string {
336 return h.CreatedAt.Format(layout)
337 }
338
339 // FormatRecoveredAt 指定のレイアウトで復元日時を文字列化
340 //
341 // 復元日時がnilの場合は空の文字列を返す
342 func (h *DatabaseBackupHistory) FormatRecoveredAt(layout string) string {
343 if h.RecoveredAt == nil {
344 return ""
345 }
346 return h.RecoveredAt.Format(layout)
347 }
348
349 // UnmarshalJSON JSON復号処理
350 func (h *DatabaseBackupHistory) UnmarshalJSON(data []byte) error {
351 var tmpMap = map[string]interface{}{}
352 if err := json.Unmarshal(data, &tmpMap); err != nil {
353 return err
354 }
355
356 if recoveredAt, ok := tmpMap["recoveredat"]; ok {
357 if strRecoveredAt, ok := recoveredAt.(string); ok {
358 if _, err := time.Parse(time.RFC3339, strRecoveredAt); err != nil {
359 tmpMap["recoveredat"] = nil
360 }
361 }
362 }
363
364 data, err := json.Marshal(tmpMap)
365 if err != nil {
366 return err
367 }
368
369 tmp := &struct {
370 CreatedAt time.Time `json:"createdat,omitempty"`
371 Availability string `json:"availability,omitempty"`
372 RecoveredAt *time.Time `json:"recoveredat,omitempty"`
373 Size string `json:"size,omitempty"`
374 }{}
375 if err := json.Unmarshal(data, &tmp); err != nil {
376 return err
377 }
378
379 h.CreatedAt = tmp.CreatedAt
380 h.Availability = tmp.Availability
381 h.RecoveredAt = tmp.RecoveredAt
382 s, err := strconv.ParseInt(tmp.Size, 10, 64)
383 if err == nil {
384 h.Size = s
385 } else {
386 return err
387 }
388
389 return nil
390 }
391
392 // DatabaseParameter RDBMSごとに固有のパラメータ設定
393 type DatabaseParameter struct {
394 Parameter *DatabaseParameterSetting `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
395 Remark *DatabaseParameterRemark `json:",omitempty" yaml:",omitempty" structs:",omitempty"`
396 }
397
398 type DatabaseParameterSetting struct {
399 NoteID types.ID `json:",omitempty" yaml:"note_id,omitempty" structs:",omitempty"`
400 Attr DatabaseParameterSettingAttr `json:",omitempty" yaml:"attr,omitempty" structs:",omitempty"`
401 }
402
403 type DatabaseParameterSettingAttr map[string]interface{}
404
405 // UnmarshalJSON 配列/オブジェクトが混在することへの対応
406 func (d *DatabaseParameterSettingAttr) UnmarshalJSON(b []byte) error {
407 if string(b) == "[]" {
408 return nil
409 }
410 type alias map[string]interface{}
411
412 var a alias
413 if err := json.Unmarshal(b, &a); err != nil {
414 return err
415 }
416 *d = DatabaseParameterSettingAttr(a)
417 return nil
418 }
419
420 type DatabaseParameterRemark struct {
421 Settings []interface{} // どのような値が入るのか不明
422 Form []*DatabaseParameterFormMeta `json:",omitempty" yaml:"form,omitempty" structs:",omitempty"`
423 }
424
425 type DatabaseParameterFormMeta struct {
426 Type string `json:"type" yaml:"yaml"`
427 Name string `json:"name" yaml:"name"`
428 Label string `json:"label" yaml:"label"`
429 Options *DatabaseParameterFormMetaOptions `json:"options" yaml:"options"`
430 Items [][]interface{} `json:"items,omitempty" yaml:"items,omitempty" structs:",omitempty"` // 例: [["value1", "text1"],[ "value2", "text2"]] ※ valueは数値となる可能性がある
431 }
432
433 type DatabaseParameterFormMetaOptions struct {
434 Validator string `json:"validator" yaml:"validator"`
435 Example string `json:"ex" yaml:"ex"`
436 Min float64 `json:"min" yaml:"min"`
437 Max float64 `json:"max" yaml:"max"`
438 MaxLen int `json:"maxlen" yaml:"maxlen"`
439 Text string `json:"text" yaml:"text"`
440 Reboot string `json:"reboot" yaml:"reboot"`
441 Type string `json:"type" yaml:"type"`
442 Integer bool `json:"integer" yaml:"integer"` // postgres用のパラメータにだけ存在する模様
443 }
444