diff --git a/.stats.yml b/.stats.yml index 23c324b..32935aa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nirvana-labs%2Fnirvana-78dacb6faebeaf3e5cbd36aae89474fb1ba31185f6042fa4790d387c12ba43fa.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/nirvana-labs%2Fnirvana-bdc8de991fbbaabca059dd096a38a4fa1cb038f5c78025c47d826eb3c748afa1.yml diff --git a/README.md b/README.md index af95a3a..6fe9d72 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,9 @@ func main() { option.WithAuthToken("My Auth Token"), // defaults to os.LookupEnv("NIRVANA_LABS_AUTH_TOKEN") ) operation, err := client.VMs.New(context.TODO(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -62,18 +65,12 @@ func main() { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err != nil { panic(err.Error()) @@ -197,6 +194,9 @@ To handle errors, we recommend that you use the `errors.As` pattern: ```go _, err := client.VMs.New(context.TODO(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -206,18 +206,12 @@ _, err := client.VMs.New(context.TODO(), vms.VMNewParams{ Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err != nil { var apierr *nirvana.Error @@ -246,6 +240,9 @@ defer cancel() client.VMs.New( ctx, vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -255,18 +252,12 @@ client.VMs.New( Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }, // This sets the per-retry timeout option.WithRequestTimeout(20*time.Second), @@ -304,6 +295,9 @@ client := nirvana.NewClient( client.VMs.New( context.TODO(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -313,18 +307,12 @@ client.VMs.New( Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }, option.WithMaxRetries(5), ) diff --git a/api.md b/api.md index 556cc5c..fd8746f 100644 --- a/api.md +++ b/api.md @@ -17,20 +17,12 @@ Params Types: - vms.CPUParam - vms.RamParam -- vms.RamUnit - vms.SSHKeyParam -- vms.StorageParam -- vms.StorageType -- vms.StorageUnit Response Types: - vms.CPU - vms.Ram -- vms.RamUnit -- vms.Storage -- vms.StorageType -- vms.StorageUnit - vms.VM - vms.VMListResponse @@ -97,6 +89,15 @@ Methods: # Volumes +Params Types: + +- volumes.StorageType + +Response Types: + +- volumes.StorageType +- volumes.Volume + Methods: - client.Volumes.New(ctx context.Context, vmID string, body volumes.VolumeNewParams) (shared.Operation, error) diff --git a/client_test.go b/client_test.go index 8a20725..5684efd 100644 --- a/client_test.go +++ b/client_test.go @@ -40,6 +40,9 @@ func TestUserAgentHeader(t *testing.T) { }), ) client.VMs.New(context.Background(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -49,18 +52,12 @@ func TestUserAgentHeader(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if userAgent != fmt.Sprintf("NirvanaLabs/Go %s", internal.PackageVersion) { t.Errorf("Expected User-Agent to be correct, but got: %#v", userAgent) @@ -85,6 +82,9 @@ func TestRetryAfter(t *testing.T) { }), ) res, err := client.VMs.New(context.Background(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -94,18 +94,12 @@ func TestRetryAfter(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("Expected there to be a cancel error and for the response to be nil") @@ -141,6 +135,9 @@ func TestDeleteRetryCountHeader(t *testing.T) { option.WithHeaderDel("X-Stainless-Retry-Count"), ) res, err := client.VMs.New(context.Background(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -150,18 +147,12 @@ func TestDeleteRetryCountHeader(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("Expected there to be a cancel error and for the response to be nil") @@ -192,6 +183,9 @@ func TestOverwriteRetryCountHeader(t *testing.T) { option.WithHeader("X-Stainless-Retry-Count", "42"), ) res, err := client.VMs.New(context.Background(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -201,18 +195,12 @@ func TestOverwriteRetryCountHeader(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("Expected there to be a cancel error and for the response to be nil") @@ -242,6 +230,9 @@ func TestRetryAfterMs(t *testing.T) { }), ) res, err := client.VMs.New(context.Background(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -251,18 +242,12 @@ func TestRetryAfterMs(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("Expected there to be a cancel error and for the response to be nil") @@ -286,6 +271,9 @@ func TestContextCancel(t *testing.T) { cancelCtx, cancel := context.WithCancel(context.Background()) cancel() res, err := client.VMs.New(cancelCtx, vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -295,18 +283,12 @@ func TestContextCancel(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("Expected there to be a cancel error and for the response to be nil") @@ -327,6 +309,9 @@ func TestContextCancelDelay(t *testing.T) { cancelCtx, cancel := context.WithTimeout(context.Background(), 2*time.Millisecond) defer cancel() res, err := client.VMs.New(cancelCtx, vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -336,18 +321,12 @@ func TestContextCancelDelay(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("expected there to be a cancel error and for the response to be nil") @@ -374,6 +353,9 @@ func TestContextDeadline(t *testing.T) { }), ) res, err := client.VMs.New(deadlineCtx, vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -383,18 +365,12 @@ func TestContextDeadline(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err == nil || res != nil { t.Error("expected there to be a deadline error and for the response to be nil") diff --git a/usage_test.go b/usage_test.go index b060058..12d6993 100644 --- a/usage_test.go +++ b/usage_test.go @@ -27,6 +27,9 @@ func TestUsage(t *testing.T) { option.WithAuthToken("My Auth Token"), ) operation, err := client.VMs.New(context.TODO(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -36,18 +39,12 @@ func TestUsage(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - }}), }) if err != nil { t.Error(err) diff --git a/vms/vm.go b/vms/vm.go index ef9e519..592fb24 100644 --- a/vms/vm.go +++ b/vms/vm.go @@ -15,6 +15,7 @@ import ( "github.com/nirvana-labs/nirvana-go/internal/requestconfig" "github.com/nirvana-labs/nirvana-go/option" "github.com/nirvana-labs/nirvana-go/shared" + "github.com/nirvana-labs/nirvana-go/volumes" "github.com/nirvana-labs/nirvana-go/vpcs" ) @@ -124,16 +125,13 @@ func (r CPUParam) MarshalJSON() (data []byte, err error) { // RAM details. type Ram struct { // RAM size - Size int64 `json:"size,required"` - // Unit (GB, MB, etc.) - Unit RamUnit `json:"unit,required"` + Size int64 `json:"size,required"` JSON ramJSON `json:"-"` } // ramJSON contains the JSON metadata for the struct [Ram] type ramJSON struct { Size apijson.Field - Unit apijson.Field raw string ExtraFields map[string]apijson.Field } @@ -150,29 +148,12 @@ func (r ramJSON) RawJSON() string { type RamParam struct { // RAM size Size param.Field[int64] `json:"size,required"` - // Unit (GB, MB, etc.) - Unit param.Field[RamUnit] `json:"unit,required"` } func (r RamParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -// Unit (GB, MB, etc.) -type RamUnit string - -const ( - RamUnitGB RamUnit = "GB" -) - -func (r RamUnit) IsKnown() bool { - switch r { - case RamUnitGB: - return true - } - return false -} - // SSH key details. type SSHKeyParam struct { PublicKey param.Field[string] `json:"public_key,required"` @@ -182,97 +163,22 @@ func (r SSHKeyParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -// Storage details. -type Storage struct { - // Storage size - Size int64 `json:"size,required"` - // Storage type. - Type StorageType `json:"type,required"` - // Storage unit. - Unit StorageUnit `json:"unit,required"` - // Disk name, used later - DiskName string `json:"disk_name"` - JSON storageJSON `json:"-"` -} - -// storageJSON contains the JSON metadata for the struct [Storage] -type storageJSON struct { - Size apijson.Field - Type apijson.Field - Unit apijson.Field - DiskName apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Storage) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r storageJSON) RawJSON() string { - return r.raw -} - -// Storage details. -type StorageParam struct { - // Storage size - Size param.Field[int64] `json:"size,required"` - // Storage type. - Type param.Field[StorageType] `json:"type,required"` - // Storage unit. - Unit param.Field[StorageUnit] `json:"unit,required"` - // Disk name, used later - DiskName param.Field[string] `json:"disk_name"` -} - -func (r StorageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// Storage type. -type StorageType string - -const ( - StorageTypeNvme StorageType = "nvme" -) - -func (r StorageType) IsKnown() bool { - switch r { - case StorageTypeNvme: - return true - } - return false -} - -// Storage unit. -type StorageUnit string - -const ( - StorageUnitGB StorageUnit = "GB" -) - -func (r StorageUnit) IsKnown() bool { - switch r { - case StorageUnitGB: - return true - } - return false -} - // VM details. type VM struct { ID string `json:"id,required"` + // Volume details. + BootVolume volumes.Volume `json:"boot_volume,required"` // CPU details. - CPUConfig CPU `json:"cpu_config,required"` - CreatedAt string `json:"created_at,required"` + CPUConfig CPU `json:"cpu_config,required"` + CreatedAt string `json:"created_at,required"` + DataVolumes []volumes.Volume `json:"data_volumes,required"` // RAM details. - MemConfig Ram `json:"mem_config,required"` - Name string `json:"name,required"` - PublicIP string `json:"public_ip,required"` - Region shared.RegionName `json:"region,required"` - Status shared.ResourceStatus `json:"status,required"` - StorageConfig []Storage `json:"storage_config,required"` - UpdatedAt string `json:"updated_at,required"` + MemConfig Ram `json:"mem_config,required"` + Name string `json:"name,required"` + PublicIP string `json:"public_ip,required"` + Region shared.RegionName `json:"region,required"` + Status shared.ResourceStatus `json:"status,required"` + UpdatedAt string `json:"updated_at,required"` // VPC details. VPC vpcs.VPC `json:"vpc,required"` JSON vmJSON `json:"-"` @@ -280,19 +186,20 @@ type VM struct { // vmJSON contains the JSON metadata for the struct [VM] type vmJSON struct { - ID apijson.Field - CPUConfig apijson.Field - CreatedAt apijson.Field - MemConfig apijson.Field - Name apijson.Field - PublicIP apijson.Field - Region apijson.Field - Status apijson.Field - StorageConfig apijson.Field - UpdatedAt apijson.Field - VPC apijson.Field - raw string - ExtraFields map[string]apijson.Field + ID apijson.Field + BootVolume apijson.Field + CPUConfig apijson.Field + CreatedAt apijson.Field + DataVolumes apijson.Field + MemConfig apijson.Field + Name apijson.Field + PublicIP apijson.Field + Region apijson.Field + Status apijson.Field + UpdatedAt apijson.Field + VPC apijson.Field + raw string + ExtraFields map[string]apijson.Field } func (r *VM) UnmarshalJSON(data []byte) (err error) { @@ -324,6 +231,8 @@ func (r vmListResponseJSON) RawJSON() string { } type VMNewParams struct { + // Boot volume create request. + BootVolume param.Field[VMNewParamsBootVolume] `json:"boot_volume,required"` // CPU details. CPU param.Field[CPUParam] `json:"cpu,required"` Name param.Field[string] `json:"name,required"` @@ -335,27 +244,69 @@ type VMNewParams struct { Region param.Field[shared.RegionName] `json:"region,required"` SourceAddress param.Field[string] `json:"source_address,required"` // SSH key details. - SSHKey param.Field[SSHKeyParam] `json:"ssh_key,required"` - Storage param.Field[[]StorageParam] `json:"storage,required"` - SubnetID param.Field[string] `json:"subnet_id"` + SSHKey param.Field[SSHKeyParam] `json:"ssh_key,required"` + DataVolumes param.Field[[]VMNewParamsDataVolume] `json:"data_volumes"` + SubnetID param.Field[string] `json:"subnet_id"` } func (r VMNewParams) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } +// Boot volume create request. +type VMNewParamsBootVolume struct { + Size param.Field[int64] `json:"size,required"` +} + +func (r VMNewParamsBootVolume) MarshalJSON() (data []byte, err error) { + return apijson.MarshalRoot(r) +} + +// Data volume create request. +type VMNewParamsDataVolume struct { + Size param.Field[int64] `json:"size,required"` + // Storage type. + Type param.Field[volumes.StorageType] `json:"type"` +} + +func (r VMNewParamsDataVolume) MarshalJSON() (data []byte, err error) { + return apijson.MarshalRoot(r) +} + type VMUpdateParams struct { + // Boot volume create request. + BootVolume param.Field[VMUpdateParamsBootVolume] `json:"boot_volume"` // CPU details. - CPU param.Field[CPUParam] `json:"cpu"` + CPU param.Field[CPUParam] `json:"cpu"` + DataVolumes param.Field[[]VMUpdateParamsDataVolume] `json:"data_volumes"` // RAM details. - Ram param.Field[RamParam] `json:"ram"` - Storage param.Field[[]StorageParam] `json:"storage"` + Ram param.Field[RamParam] `json:"ram"` } func (r VMUpdateParams) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } +// Boot volume create request. +type VMUpdateParamsBootVolume struct { + Size param.Field[int64] `json:"size,required"` +} + +func (r VMUpdateParamsBootVolume) MarshalJSON() (data []byte, err error) { + return apijson.MarshalRoot(r) +} + +// Data volume create request. +type VMUpdateParamsDataVolume struct { + Size param.Field[int64] `json:"size,required"` + // Storage type. + Type param.Field[volumes.StorageType] `json:"type"` +} + +func (r VMUpdateParamsDataVolume) MarshalJSON() (data []byte, err error) { + return apijson.MarshalRoot(r) +} + type VMListParams struct { // Region Region param.Field[string] `query:"region,required"` diff --git a/vms/vm_test.go b/vms/vm_test.go index 3c7d61b..943e414 100644 --- a/vms/vm_test.go +++ b/vms/vm_test.go @@ -13,6 +13,7 @@ import ( "github.com/nirvana-labs/nirvana-go/option" "github.com/nirvana-labs/nirvana-go/shared" "github.com/nirvana-labs/nirvana-go/vms" + "github.com/nirvana-labs/nirvana-go/volumes" ) func TestVMNewWithOptionalParams(t *testing.T) { @@ -28,6 +29,9 @@ func TestVMNewWithOptionalParams(t *testing.T) { option.WithAuthToken("My Auth Token"), ) _, err := client.VMs.New(context.TODO(), vms.VMNewParams{ + BootVolume: nirvana.F(vms.VMNewParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), @@ -37,18 +41,15 @@ func TestVMNewWithOptionalParams(t *testing.T) { Ports: nirvana.F([]string{"22", "80", "443"}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), Region: nirvana.F(shared.RegionNameAmsterdam), SourceAddress: nirvana.F("0.0.0.0/0"), SSHKey: nirvana.F(vms.SSHKeyParam{ PublicKey: nirvana.F("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1234567890"), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - DiskName: nirvana.F("disk_name"), + DataVolumes: nirvana.F([]vms.VMNewParamsDataVolume{{ + Size: nirvana.F(int64(100)), + Type: nirvana.F(volumes.StorageTypeNvme), }}), SubnetID: nirvana.F("123e4567-e89b-12d3-a456-426614174000"), }) @@ -77,19 +78,19 @@ func TestVMUpdateWithOptionalParams(t *testing.T) { context.TODO(), "vm_id", vms.VMUpdateParams{ + BootVolume: nirvana.F(vms.VMUpdateParamsBootVolume{ + Size: nirvana.F(int64(100)), + }), CPU: nirvana.F(vms.CPUParam{ Cores: nirvana.F(int64(2)), }), + DataVolumes: nirvana.F([]vms.VMUpdateParamsDataVolume{{ + Size: nirvana.F(int64(100)), + Type: nirvana.F(volumes.StorageTypeNvme), + }}), Ram: nirvana.F(vms.RamParam{ Size: nirvana.F(int64(2)), - Unit: nirvana.F(vms.RamUnitGB), }), - Storage: nirvana.F([]vms.StorageParam{{ - Size: nirvana.F(int64(100)), - Type: nirvana.F(vms.StorageTypeNvme), - Unit: nirvana.F(vms.StorageUnitGB), - DiskName: nirvana.F("disk_name"), - }}), }, ) if err != nil { diff --git a/volumes/volume.go b/volumes/volume.go index 75004b1..78d78bc 100644 --- a/volumes/volume.go +++ b/volumes/volume.go @@ -62,8 +62,51 @@ func (r *VolumeService) Delete(ctx context.Context, vmID string, volumeID string return } +// Storage type. +type StorageType string + +const ( + StorageTypeNvme StorageType = "nvme" +) + +func (r StorageType) IsKnown() bool { + switch r { + case StorageTypeNvme: + return true + } + return false +} + +// Volume details. +type Volume struct { + ID string `json:"id,required"` + Size int64 `json:"size,required"` + // Storage type. + Type StorageType `json:"type,required"` + JSON volumeJSON `json:"-"` +} + +// volumeJSON contains the JSON metadata for the struct [Volume] +type volumeJSON struct { + ID apijson.Field + Size apijson.Field + Type apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *Volume) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r volumeJSON) RawJSON() string { + return r.raw +} + type VolumeNewParams struct { Size param.Field[int64] `json:"size,required"` + // Storage type. + Type param.Field[StorageType] `json:"type"` } func (r VolumeNewParams) MarshalJSON() (data []byte, err error) { diff --git a/volumes/volume_test.go b/volumes/volume_test.go index 5359427..21bd459 100644 --- a/volumes/volume_test.go +++ b/volumes/volume_test.go @@ -14,7 +14,7 @@ import ( "github.com/nirvana-labs/nirvana-go/volumes" ) -func TestVolumeNew(t *testing.T) { +func TestVolumeNewWithOptionalParams(t *testing.T) { baseURL := "http://localhost:4010" if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { baseURL = envURL @@ -31,6 +31,7 @@ func TestVolumeNew(t *testing.T) { "vm_id", volumes.VolumeNewParams{ Size: nirvana.F(int64(100)), + Type: nirvana.F(volumes.StorageTypeNvme), }, ) if err != nil {