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