github.com/sacloud/iaas-api-go@v1.12.0/fake/ops_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 fake 16 17 import ( 18 "context" 19 "time" 20 21 "github.com/sacloud/iaas-api-go" 22 "github.com/sacloud/iaas-api-go/types" 23 ) 24 25 // Find is fake implementation 26 func (o *DatabaseOp) Find(ctx context.Context, zone string, conditions *iaas.FindCondition) (*iaas.DatabaseFindResult, error) { 27 results, _ := find(o.key, zone, conditions) 28 var values []*iaas.Database 29 for _, res := range results { 30 dest := &iaas.Database{} 31 copySameNameField(res, dest) 32 values = append(values, dest) 33 } 34 return &iaas.DatabaseFindResult{ 35 Total: len(results), 36 Count: len(results), 37 From: 0, 38 Databases: values, 39 }, nil 40 } 41 42 // Create is fake implementation 43 func (o *DatabaseOp) Create(ctx context.Context, zone string, param *iaas.DatabaseCreateRequest) (*iaas.Database, error) { 44 result := &iaas.Database{} 45 copySameNameField(param, result) 46 fill(result, fillID, fillCreatedAt) 47 48 result.Class = "database" 49 result.Availability = types.Availabilities.Available 50 if result.Conf != nil { 51 if result.Conf.DatabaseVersion == "" { 52 result.Conf.DatabaseVersion = "1" 53 } 54 if result.Conf.DatabaseRevision == "" { 55 result.Conf.DatabaseRevision = "1" 56 } 57 } 58 59 putDatabase(zone, result) 60 61 id := result.ID 62 startPowerOn(o.key, zone, func() (interface{}, error) { 63 return o.Read(context.Background(), zone, id) 64 }) 65 return result, nil 66 } 67 68 // Read is fake implementation 69 func (o *DatabaseOp) Read(ctx context.Context, zone string, id types.ID) (*iaas.Database, error) { 70 value := getDatabaseByID(zone, id) 71 if value == nil { 72 return nil, newErrorNotFound(o.key, id) 73 } 74 dest := &iaas.Database{} 75 copySameNameField(value, dest) 76 return dest, nil 77 } 78 79 // Update is fake implementation 80 func (o *DatabaseOp) Update(ctx context.Context, zone string, id types.ID, param *iaas.DatabaseUpdateRequest) (*iaas.Database, error) { 81 value, err := o.Read(ctx, zone, id) 82 if err != nil { 83 return nil, err 84 } 85 copySameNameField(param, value) 86 fill(value, fillModifiedAt) 87 88 putDatabase(zone, value) 89 return value, nil 90 } 91 92 // UpdateSettings is fake implementation 93 func (o *DatabaseOp) UpdateSettings(ctx context.Context, zone string, id types.ID, param *iaas.DatabaseUpdateSettingsRequest) (*iaas.Database, error) { 94 value, err := o.Read(ctx, zone, id) 95 if err != nil { 96 return nil, err 97 } 98 copySameNameField(param, value) 99 fill(value, fillModifiedAt) 100 101 putDatabase(zone, value) 102 return value, nil 103 } 104 105 // Delete is fake implementation 106 func (o *DatabaseOp) Delete(ctx context.Context, zone string, id types.ID) error { 107 _, err := o.Read(ctx, zone, id) 108 if err != nil { 109 return err 110 } 111 112 ds().Delete(o.key, zone, id) 113 return nil 114 } 115 116 // Config is fake implementation 117 func (o *DatabaseOp) Config(ctx context.Context, zone string, id types.ID) error { 118 _, err := o.Read(ctx, zone, id) 119 if err != nil { 120 return err 121 } 122 return nil 123 } 124 125 // Boot is fake implementation 126 func (o *DatabaseOp) Boot(ctx context.Context, zone string, id types.ID) error { 127 value, err := o.Read(ctx, zone, id) 128 if err != nil { 129 return err 130 } 131 if value.InstanceStatus.IsUp() { 132 return newErrorConflict(o.key, id, "Boot is failed") 133 } 134 135 startPowerOn(o.key, zone, func() (interface{}, error) { 136 return o.Read(context.Background(), zone, id) 137 }) 138 139 return err 140 } 141 142 // Shutdown is fake implementation 143 func (o *DatabaseOp) Shutdown(ctx context.Context, zone string, id types.ID, shutdownOption *iaas.ShutdownOption) error { 144 value, err := o.Read(ctx, zone, id) 145 if err != nil { 146 return err 147 } 148 if !value.InstanceStatus.IsUp() { 149 return newErrorConflict(o.key, id, "Shutdown is failed") 150 } 151 152 startPowerOff(o.key, zone, func() (interface{}, error) { 153 return o.Read(context.Background(), zone, id) 154 }) 155 156 return err 157 } 158 159 // Reset is fake implementation 160 func (o *DatabaseOp) Reset(ctx context.Context, zone string, id types.ID) error { 161 value, err := o.Read(ctx, zone, id) 162 if err != nil { 163 return err 164 } 165 if !value.InstanceStatus.IsUp() { 166 return newErrorConflict(o.key, id, "Reset is failed") 167 } 168 169 startPowerOn(o.key, zone, func() (interface{}, error) { 170 return o.Read(context.Background(), zone, id) 171 }) 172 173 return nil 174 } 175 176 // MonitorCPU is fake implementation 177 func (o *DatabaseOp) MonitorCPU(ctx context.Context, zone string, id types.ID, condition *iaas.MonitorCondition) (*iaas.CPUTimeActivity, error) { 178 _, err := o.Read(ctx, zone, id) 179 if err != nil { 180 return nil, err 181 } 182 183 now := time.Now().Truncate(time.Second) 184 m := now.Minute() % 5 185 if m != 0 { 186 now.Add(time.Duration(m) * time.Minute) 187 } 188 189 res := &iaas.CPUTimeActivity{} 190 for i := 0; i < 5; i++ { 191 res.Values = append(res.Values, &iaas.MonitorCPUTimeValue{ 192 Time: now.Add(time.Duration(i*-5) * time.Minute), 193 CPUTime: float64(random(1000)), 194 }) 195 } 196 197 return res, nil 198 } 199 200 // MonitorDisk is fake implementation 201 func (o *DatabaseOp) MonitorDisk(ctx context.Context, zone string, id types.ID, condition *iaas.MonitorCondition) (*iaas.DiskActivity, error) { 202 _, err := o.Read(ctx, zone, id) 203 if err != nil { 204 return nil, err 205 } 206 207 now := time.Now().Truncate(time.Second) 208 m := now.Minute() % 5 209 if m != 0 { 210 now.Add(time.Duration(m) * time.Minute) 211 } 212 213 res := &iaas.DiskActivity{} 214 for i := 0; i < 5; i++ { 215 res.Values = append(res.Values, &iaas.MonitorDiskValue{ 216 Time: now.Add(time.Duration(i*-5) * time.Minute), 217 Read: float64(random(1000)), 218 Write: float64(random(1000)), 219 }) 220 } 221 222 return res, nil 223 } 224 225 // MonitorInterface is fake implementation 226 func (o *DatabaseOp) MonitorInterface(ctx context.Context, zone string, id types.ID, condition *iaas.MonitorCondition) (*iaas.InterfaceActivity, error) { 227 _, err := o.Read(ctx, zone, id) 228 if err != nil { 229 return nil, err 230 } 231 232 now := time.Now().Truncate(time.Second) 233 m := now.Minute() % 5 234 if m != 0 { 235 now.Add(time.Duration(m) * time.Minute) 236 } 237 238 res := &iaas.InterfaceActivity{} 239 for i := 0; i < 5; i++ { 240 res.Values = append(res.Values, &iaas.MonitorInterfaceValue{ 241 Time: now.Add(time.Duration(i*-5) * time.Minute), 242 Receive: float64(random(1000)), 243 Send: float64(random(1000)), 244 }) 245 } 246 247 return res, nil 248 } 249 250 // MonitorDatabase is fake implementation 251 func (o *DatabaseOp) MonitorDatabase(ctx context.Context, zone string, id types.ID, condition *iaas.MonitorCondition) (*iaas.DatabaseActivity, error) { 252 _, err := o.Read(ctx, zone, id) 253 if err != nil { 254 return nil, err 255 } 256 257 now := time.Now().Truncate(time.Second) 258 m := now.Minute() % 5 259 if m != 0 { 260 now.Add(time.Duration(m) * time.Minute) 261 } 262 263 res := &iaas.DatabaseActivity{} 264 for i := 0; i < 5; i++ { 265 res.Values = append(res.Values, &iaas.MonitorDatabaseValue{ 266 Time: now.Add(time.Duration(i*-5) * time.Minute), 267 TotalMemorySize: float64(random(1000)), 268 UsedMemorySize: float64(random(1000)), 269 TotalDisk1Size: float64(random(1000)), 270 UsedDisk1Size: float64(random(1000)), 271 TotalDisk2Size: float64(random(1000)), 272 UsedDisk2Size: float64(random(1000)), 273 BinlogUsedSizeKiB: float64(random(1000)), 274 DelayTimeSec: float64(random(1000)), 275 }) 276 } 277 278 return res, nil 279 } 280 281 // Status is fake implementation 282 func (o *DatabaseOp) Status(ctx context.Context, zone string, id types.ID) (*iaas.DatabaseStatus, error) { 283 value, err := o.Read(ctx, zone, id) 284 if err != nil { 285 return nil, err 286 } 287 288 return &iaas.DatabaseStatus{ 289 Status: value.InstanceStatus, 290 IsFatal: false, 291 MariaDBStatus: "running", 292 Version: &iaas.DatabaseVersionInfo{ 293 LastModified: value.ModifiedAt.String(), 294 CommitHash: "foobar", 295 Status: "up", 296 Tag: "stable", 297 }, 298 }, nil 299 } 300 301 func (o *DatabaseOp) GetParameter(ctx context.Context, zone string, id types.ID) (*iaas.DatabaseParameter, error) { 302 v, err := o.Read(ctx, zone, id) 303 if err != nil { 304 return nil, err 305 } 306 307 var settings map[string]interface{} 308 raw := ds().Get(ResourceDatabase+"Parameter", zone, id) 309 if raw != nil { 310 settings = raw.(map[string]interface{}) 311 } 312 313 meta := fakeDatabaseParameterMetaForMariaDB 314 if v.Conf.DatabaseName == "postgres" { 315 meta = fakeDatabaseParameterMetaForPostgreSQL 316 } 317 return &iaas.DatabaseParameter{ 318 Settings: settings, 319 MetaInfo: meta, 320 }, nil 321 } 322 323 var ( 324 fakeDatabaseParameterMetaForMariaDB = []*iaas.DatabaseParameterMeta{ 325 { 326 Type: "number", 327 Name: "MariaDB/server.cnf/mysqld/max_connections", 328 Label: "max_connections", 329 Text: "同時クライアント接続の最大数を設定します。", 330 Example: "100", 331 Min: 10, 332 Max: 1000, 333 MaxLen: 0, 334 Reboot: "static", 335 }, 336 { 337 Type: "string", 338 Name: "MariaDB/server.cnf/mysqld/event_scheduler", 339 Label: "event_scheduler", 340 Text: "イベントスケジュールの有効無効を設定します。", 341 Example: "ON", 342 Min: 0, 343 Max: 0, 344 MaxLen: 0, 345 Reboot: "dynamic", 346 }, 347 } 348 fakeDatabaseParameterMetaForPostgreSQL = []*iaas.DatabaseParameterMeta{ 349 { 350 Type: "number", 351 Name: "postgres/postgresql.conf/max_connections", 352 Label: "max_connections", 353 Text: "同時クライアント接続の最大数を設定します。", 354 Example: "100", 355 Min: 10, 356 Max: 1000, 357 MaxLen: 0, 358 Reboot: "static", 359 }, 360 { 361 Type: "number", 362 Name: "postgres/postgresql.conf/work_mem", 363 Label: "work_mem", 364 Text: "クエリワークスペースに使用するメモリの最大量を設定します。", 365 Example: "4096", 366 Min: 64, 367 Max: 2147483647, 368 MaxLen: 10, 369 Reboot: "dynamic", 370 }, 371 } 372 ) 373 374 func (o *DatabaseOp) SetParameter(ctx context.Context, zone string, id types.ID, param map[string]interface{}) error { 375 _, err := o.Read(ctx, zone, id) 376 if err != nil { 377 return err 378 } 379 380 var settings map[string]interface{} 381 raw := ds().Get(ResourceDatabase+"Parameter", zone, id) 382 if raw != nil { 383 settings = raw.(map[string]interface{}) 384 } else { 385 settings = make(map[string]interface{}) 386 } 387 for k, v := range param { 388 if v == nil { 389 delete(settings, k) 390 } else { 391 switch v := v.(type) { 392 case int: 393 settings[k] = float64(v) 394 default: 395 settings[k] = v 396 } 397 } 398 } 399 400 ds().Put(ResourceDatabase+"Parameter", zone, id, settings) 401 return nil 402 }