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