init.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 fake
16
17 import (
18 "fmt"
19 "net"
20 "sync"
21 "time"
22
23 "github.com/sacloud/iaas-api-go"
24 "github.com/sacloud/iaas-api-go/types"
25 "github.com/sacloud/packages-go/size"
26 )
27
28 var initOnce sync.Once
29
30 func ds() Store {
31 InitDataStore()
32 return DataStore
33 }
34
35 // DataStore fakeドライバが利用するデータストア
36 var DataStore Store
37
38 // InitDataStore データストアの初期化
39 func InitDataStore() {
40 initOnce.Do(func() {
41 if DataStore == nil {
42 DataStore = NewInMemoryStore()
43 }
44 if err := DataStore.Init(); err != nil {
45 panic(err)
46 }
47
48 // pool(id,ip,subnet,etc...)
49 p := initValuePool(DataStore)
50
51 if DataStore.NeedInitData() {
52 if err := initData(DataStore, p); err != nil {
53 panic(err)
54 }
55 }
56 })
57 }
58
59 func initData(s Store, p *valuePool) error {
60 initGeneratedArchives(s, p)
61 initBills(s, p)
62 initCoupons(s, p)
63 initGeneratedCDROMs(s, p)
64 initNotes(s, p)
65 initSwitch(s, p)
66 initZones(s, p)
67 initRegions(s, p)
68 initPrivateHostPlan(s, p)
69 initDiskPlan(s, p)
70 initLicensePlan(s, p)
71 initInternetPlan(s, p)
72 initServerPlan(s, p)
73 initServiceClass(s, p)
74 return nil
75 }
76
77 func initGeneratedArchives(s Store, p *valuePool) {
78 for zone, archives := range initArchives { // generated by internal/tools/gen-api-fake-public-archive
79 for _, archive := range archives {
80 s.Put(ResourceArchive, zone, archive.ID, archive)
81 }
82 }
83 }
84
85 func initBills(s Store, p *valuePool) {
86 bills := []*iaas.Bill{
87 {
88 ID: p.generateID(),
89 Amount: 1080,
90 Date: time.Now(),
91 MemberID: "dummy00000",
92 Paid: false,
93 PayLimit: time.Now().AddDate(0, 1, 0),
94 PaymentClassID: 999,
95 },
96 }
97 for _, bill := range bills {
98 s.Put(ResourceBill, iaas.APIDefaultZone, bill.ID, bill)
99 initBillDetails(s, p, bill.ID)
100 }
101 }
102
103 func initBillDetails(s Store, p *valuePool, billID types.ID) {
104 details := []*iaas.BillDetail{
105 {
106 ID: p.generateID(),
107 Amount: 108,
108 Description: "description",
109 ServiceClassID: 999,
110 ServiceClassPath: "fake/cloud/dummy",
111 Usage: 100,
112 FormattedUsage: "1d, 2h",
113 ServiceUsagePath: "fake/cloud/usetime",
114 Zone: "tk1a",
115 ContractEndAt: time.Now(),
116 },
117 }
118 s.Put(ResourceBill+"Details", iaas.APIDefaultZone, billID, &details)
119 }
120
121 func initGeneratedCDROMs(s Store, p *valuePool) {
122 for zone, cdroms := range initCDROM { // generated by internal/tools/gen-api-fake-data
123 for _, cdrom := range cdroms {
124 s.Put(ResourceCDROM, zone, cdrom.ID, cdrom)
125 }
126 }
127 }
128
129 func initCoupons(s Store, p *valuePool) {
130 coupons := []*iaas.Coupon{
131 {
132 ID: p.generateID(),
133 MemberID: "dummy00000",
134 ContractID: p.generateID(),
135 ServiceClassID: 999,
136 Discount: 20000,
137 AppliedAt: time.Now().AddDate(0, -1, 0),
138 UntilAt: time.Now().AddDate(0, 1, 0),
139 },
140 }
141 for _, c := range coupons {
142 s.Put(ResourceCoupon, iaas.APIDefaultZone, c.ID, c)
143 }
144 }
145
146 func initNotes(s Store, p *valuePool) {
147 notes := []*iaas.Note{
148 {
149 ID: 1,
150 Name: "sys-nfs",
151 Class: "json",
152 Content: `
153 {
154 "plans":{
155 "HDD":[
156 {"size": 100,"availability":"available","planId":101},
157 {"size": 500,"availability":"available","planId":102},
158 {"size": 1024,"availability":"available","planId":103},
159 {"size": 2048,"availability":"available","planId":104},
160 {"size": 4096,"availability":"available","planId":105},
161 {"size": 8192,"availability":"available","planId":106},
162 {"size": 12288,"availability":"available","planId":107}
163 ],
164 "SSD":[
165 {"size": 20,"availability":"available","planId":200},
166 {"size": 100,"availability":"available","planId":201},
167 {"size": 500,"availability":"available","planId":202},
168 {"size": 1024,"availability":"available","planId":203},
169 {"size": 2048,"availability":"available","planId":204},
170 {"size": 4096,"availability":"available","planId":205}
171 ]
172 }
173 }`,
174 },
175 {
176 ID: 2,
177 Name: "sys-database",
178 Class: "json",
179 Scope: "shared",
180 Content: `
181 {
182 "Products": [],
183 "Backup": {
184 "LockLimit": 8,
185 "RotateLimit": 8
186 },
187 "AppliancePlans": [
188 {
189 "Class": "database",
190 "Model": "Proxy",
191 "CPU": 4,
192 "MemoryMB": 4096,
193 "DiskSizes": [
194 {
195 "SizeMB": 102400,
196 "DisplaySize": 90,
197 "PlanID": 50721,
198 "ServiceClass": "cloud/appliance/database/4core4gb-100gb-proxy"
199 },
200 {
201 "SizeMB": 256000,
202 "DisplaySize": 240,
203 "PlanID": 50722,
204 "ServiceClass": "cloud/appliance/database/4core4gb-250gb-proxy"
205 },
206 {
207 "SizeMB": 512000,
208 "DisplaySize": 500,
209 "PlanID": 50723,
210 "ServiceClass": "cloud/appliance/database/4core4gb-500gb-proxy"
211 },
212 {
213 "SizeMB": 1048576,
214 "DisplaySize": 1000,
215 "PlanID": 50724,
216 "ServiceClass": "cloud/appliance/database/4core4gb-1tb-proxy"
217 }
218 ]
219 },
220 {
221 "Class": "database",
222 "Model": "Proxy",
223 "CPU": 4,
224 "MemoryMB": 8192,
225 "DiskSizes": [
226 {
227 "SizeMB": 102400,
228 "DisplaySize": 90,
229 "PlanID": 50725,
230 "ServiceClass": "cloud/appliance/database/4core8gb-100gb-proxy"
231 },
232 {
233 "SizeMB": 256000,
234 "DisplaySize": 240,
235 "PlanID": 50726,
236 "ServiceClass": "cloud/appliance/database/4core8gb-250gb-proxy"
237 },
238 {
239 "SizeMB": 512000,
240 "DisplaySize": 500,
241 "PlanID": 50727,
242 "ServiceClass": "cloud/appliance/database/4core8gb-500gb-proxy"
243 },
244 {
245 "SizeMB": 1048576,
246 "DisplaySize": 1000,
247 "PlanID": 50728,
248 "ServiceClass": "cloud/appliance/database/4core8gb-1tb-proxy"
249 }
250 ]
251 }
252 ]
253 }
254 `,
255 },
256 }
257 for _, note := range notes {
258 s.Put(ResourceNote, iaas.APIDefaultZone, note.ID, note)
259 }
260 }
261
262 func initSwitch(s Store, p *valuePool) {
263 sharedNetMask := net.CIDRMask(p.SharedNetMaskLen, 32)
264 sharedNet := p.CurrentSharedIP.Mask(sharedNetMask)
265
266 sharedSegmentSwitch = &iaas.Switch{
267 ID: p.generateID(),
268 Name: "スイッチ",
269 Scope: types.Scopes.Shared,
270 Description: "共有セグメント用スイッチ",
271 NetworkMaskLen: p.SharedNetMaskLen,
272 DefaultRoute: p.SharedDefaultGateway.String(),
273 Subnets: []*iaas.SwitchSubnet{
274 {
275 ID: 1,
276 DefaultRoute: p.SharedDefaultGateway.String(),
277 NextHop: p.SharedDefaultGateway.String(),
278 StaticRoute: p.SharedDefaultGateway.String(),
279 NetworkAddress: sharedNet.String(),
280 NetworkMaskLen: p.SharedNetMaskLen,
281 },
282 },
283 }
284 for _, zone := range zones {
285 s.Put(ResourceSwitch, zone, sharedSegmentSwitch.ID, sharedSegmentSwitch)
286 }
287 }
288
289 func initZones(s Store, p *valuePool) {
290 // zones
291 zones := []*iaas.Zone{
292 {
293 ID: 21001,
294 Name: "tk1a",
295 Description: "東京第1ゾーン",
296 DisplayOrder: 1,
297 Region: &iaas.Region{
298 ID: 210,
299 Name: "東京",
300 Description: "東京",
301 NameServers: []string{
302 "210.188.224.10",
303 "210.188.224.11",
304 },
305 },
306 },
307 {
308 ID: 21002,
309 Name: "tk1b",
310 Description: "東京第2ゾーン",
311 DisplayOrder: 2,
312 Region: &iaas.Region{
313 ID: 210,
314 Name: "東京",
315 Description: "東京",
316 NameServers: []string{
317 "210.188.224.10",
318 "210.188.224.11",
319 },
320 },
321 },
322 {
323 ID: 31001,
324 Name: "is1a",
325 Description: "石狩第1ゾーン",
326 DisplayOrder: 3,
327 Region: &iaas.Region{
328 ID: 310,
329 Name: "石狩",
330 Description: "石狩",
331 NameServers: []string{
332 "133.242.0.3",
333 "133.242.0.4",
334 },
335 },
336 },
337 {
338 ID: 31002,
339 Name: "is1b",
340 Description: "石狩第2ゾーン",
341 DisplayOrder: 4,
342 Region: &iaas.Region{
343 ID: 310,
344 Name: "石狩",
345 Description: "石狩",
346 NameServers: []string{
347 "133.242.0.3",
348 "133.242.0.4",
349 },
350 },
351 },
352 {
353 ID: 29001,
354 Name: "tk1v",
355 Description: "Sandbox",
356 DisplayOrder: 5,
357 IsDummy: true,
358 Region: &iaas.Region{
359 ID: 210,
360 Name: "東京",
361 Description: "東京",
362 NameServers: []string{
363 "210.188.224.10",
364 "210.188.224.11",
365 },
366 },
367 },
368 }
369
370 for _, zone := range zones {
371 s.Put(ResourceZone, iaas.APIDefaultZone, zone.ID, zone)
372 }
373 }
374
375 func initRegions(s Store, p *valuePool) {
376 regions := []*iaas.Region{
377 {
378 ID: 210,
379 Name: "東京",
380 Description: "東京",
381 NameServers: []string{
382 "210.188.224.10",
383 "210.188.224.11",
384 },
385 },
386 {
387 ID: 290,
388 Name: "Sandbox",
389 Description: "Sandbox",
390 NameServers: []string{
391 "133.242.0.3",
392 "133.242.0.4",
393 },
394 },
395 {
396 ID: 310,
397 Name: "石狩",
398 Description: "石狩",
399 NameServers: []string{
400 "133.242.0.3",
401 "133.242.0.4",
402 },
403 },
404 }
405
406 for _, region := range regions {
407 s.Put(ResourceRegion, iaas.APIDefaultZone, region.ID, region)
408 }
409 }
410
411 func initPrivateHostPlan(s Store, p *valuePool) {
412 plans := []*iaas.PrivateHostPlan{
413 {
414 ID: 112900526366,
415 Name: "200Core 224GB 標準",
416 Class: "dynamic",
417 CPU: 200,
418 MemoryMB: 229376,
419 Availability: types.Availabilities.Available,
420 },
421 {
422 ID: 113102196877,
423 Name: "200Core 224GB Windows",
424 Class: "ms_windows",
425 CPU: 200,
426 MemoryMB: 229376,
427 Availability: types.Availabilities.Available,
428 },
429 }
430 for _, zone := range zones {
431 for _, plan := range plans {
432 s.Put(ResourcePrivateHostPlan, zone, plan.ID, plan)
433 }
434 }
435 }
436
437 func initServerPlan(s Store, p *valuePool) {
438 plans := []*iaas.ServerPlan{
439 {
440 ID: p.generateID(),
441 Name: "プラン/1Core-1GB",
442 CPU: 1,
443 MemoryMB: 1 * size.MiB,
444 GPU: 0,
445 CPUModel: "uncategorized",
446 Commitment: types.Commitments.Standard,
447 Generation: 100,
448 Availability: types.Availabilities.Available,
449 },
450 {
451 ID: p.generateID(),
452 Name: "プラン/2Core-4GB",
453 CPU: 2,
454 MemoryMB: 4 * size.MiB,
455 GPU: 0,
456 CPUModel: "uncategorized",
457 Commitment: types.Commitments.Standard,
458 Generation: 100,
459 Availability: types.Availabilities.Available,
460 },
461 {
462 ID: p.generateID(),
463 Name: "GPUプラン/4Core-56GB-1GPU",
464 CPU: 4,
465 MemoryMB: 56 * 1024 * size.MiB,
466 GPU: 1,
467 CPUModel: "uncategorized",
468 Commitment: types.Commitments.Standard,
469 Generation: 200,
470 Availability: types.Availabilities.Available,
471 },
472 {
473 ID: p.generateID(),
474 Name: "コア専有プラン/32Core-120GB",
475 CPU: 32,
476 MemoryMB: 120 * 1024 * size.MiB,
477 GPU: 0,
478 CPUModel: "amd_epyc_7713p",
479 Commitment: types.Commitments.DedicatedCPU,
480 Generation: 200,
481 Availability: types.Availabilities.Available,
482 },
483 // TODO add more plans
484 }
485
486 for _, zone := range zones {
487 for _, plan := range plans {
488 s.Put(ResourceServerPlan, zone, plan.ID, plan)
489 }
490 }
491 }
492
493 func initInternetPlan(s Store, p *valuePool) {
494 bandWidthList := []int{100, 250, 500, 1000, 1500, 2000, 2500, 3000, 5000}
495
496 var plans []*iaas.InternetPlan
497
498 for _, bw := range bandWidthList {
499 plans = append(plans, &iaas.InternetPlan{
500 ID: types.ID(bw),
501 BandWidthMbps: bw,
502 Name: fmt.Sprintf("%dMbps共有", bw),
503 Availability: types.Availabilities.Available,
504 })
505 }
506
507 for _, zone := range zones {
508 for _, plan := range plans {
509 s.Put(ResourceInternetPlan, zone, plan.ID, plan)
510 }
511 }
512 }
513
514 func initDiskPlan(s Store, p *valuePool) {
515 plans := []*iaas.DiskPlan{
516 {
517 ID: 2,
518 Name: "HDDプラン",
519 Availability: types.Availabilities.Available,
520 StorageClass: "iscsi1204",
521 Size: []*iaas.DiskPlanSizeInfo{
522 {
523 Availability: types.Availabilities.Available,
524 DisplaySize: 20,
525 DisplaySuffix: "GB",
526 SizeMB: 20 * size.GiB,
527 },
528 {
529 Availability: types.Availabilities.Available,
530 DisplaySize: 40,
531 DisplaySuffix: "GB",
532 SizeMB: 40 * size.GiB,
533 },
534 },
535 },
536 {
537 ID: 4,
538 Name: "SSDプラン",
539 Availability: types.Availabilities.Available,
540 StorageClass: "iscsi1204",
541 Size: []*iaas.DiskPlanSizeInfo{
542 {
543 Availability: types.Availabilities.Available,
544 DisplaySize: 20,
545 DisplaySuffix: "GB",
546 SizeMB: 20 * size.GiB,
547 },
548 {
549 Availability: types.Availabilities.Available,
550 DisplaySize: 40,
551 DisplaySuffix: "GB",
552 SizeMB: 40 * size.GiB,
553 },
554 },
555 },
556 // TODO add more size-info
557 }
558
559 for _, zone := range zones {
560 for _, plan := range plans {
561 s.Put(ResourceDiskPlan, zone, plan.ID, plan)
562 }
563 }
564 }
565
566 func initLicensePlan(s Store, p *valuePool) {
567 plans := []*iaas.LicenseInfo{
568 {
569 ID: types.ID(10001),
570 Name: "Windows RDS SAL",
571 TermsOfUse: "1ライセンスにつき、1人のユーザが利用できます。",
572 },
573 }
574
575 for _, zone := range zones {
576 for _, plan := range plans {
577 s.Put(ResourceLicenseInfo, zone, plan.ID, plan)
578 }
579 }
580 }
581
582 func initServiceClass(s Store, p *valuePool) {
583 classes := []*iaas.ServiceClass{
584 {
585 ID: types.ID(50050),
586 ServiceClassName: "plan/1",
587 ServiceClassPath: "cloud/plan/1",
588 DisplayName: "プラン1(ディスクなし)",
589 IsPublic: true,
590 Price: &iaas.Price{
591 Base: 0,
592 Daily: 108,
593 Hourly: 10,
594 Monthly: 2139,
595 },
596 },
597 {
598 ID: types.ID(50051),
599 ServiceClassName: "plan/2",
600 ServiceClassPath: "cloud/plan/2",
601 DisplayName: "プラン2(ディスクなし)",
602 IsPublic: true,
603 Price: &iaas.Price{
604 Base: 0,
605 Daily: 172,
606 Hourly: 17,
607 Monthly: 3425,
608 },
609 },
610 }
611
612 for _, zone := range zones {
613 for _, class := range classes {
614 class.Price.Zone = zone
615 s.Put(ResourceServiceClass, zone, class.ID, class)
616 }
617 }
618 }
619