diff --git a/apis/common/common_types.go b/apis/common/common_types.go index e52bdd2..244076a 100644 --- a/apis/common/common_types.go +++ b/apis/common/common_types.go @@ -6,3 +6,8 @@ type StandQueryParameters struct { Page int `json:"page"` PerPage int `json:"perPage"` } + +type BasicOperationResponse struct { + Code int `json:"code"` + Data string `json:"data"` +} diff --git a/apis/common/query_test.go b/apis/common/query_test.go index f7f37ce..4dbad4b 100644 --- a/apis/common/query_test.go +++ b/apis/common/query_test.go @@ -6,12 +6,12 @@ import ( ) type queryParamsSample struct { - IsRGpu *bool `json:"is_rgpu"` - Limit int `json:"limit"` - Name string `json:"name"` - Options StandQueryParameters `json:"options"` - Tags []string `json:"tags"` - Skip string `json:"-"` + IsRGpu *bool `json:"is_rgpu"` + Limit int `json:"limit"` + Name string `json:"name"` + Options StandQueryParameters `json:"options"` + Tags []string `json:"tags"` + Skip string `json:"-"` NoTag string } diff --git a/apis/common/vnc.go b/apis/common/vnc.go new file mode 100644 index 0000000..ccc51ea --- /dev/null +++ b/apis/common/vnc.go @@ -0,0 +1,19 @@ +package common + +import "strconv" + +type VncConnectionInfo struct { + Code int `json:"code"` + Data VncConnectionData `json:"data"` +} + +type VncConnectionData struct { + RequestURL string `json:"RequestURL"` // 空 + RedirectURL string `json:"RedirectURL"` // 空 + PVEAuth string `json:"PVEAuth"` // 空 + VNCProxyURL string `json:"VNCProxyURL"` // PVE代理地址(连接地址),里面会有一个unicode码(\u0026)(&),转码后就是可以直接在浏览器上使用的VNC连接地址 +} + +func GetVncConnectURL(v *VncConnectionInfo) (string, error) { + return strconv.Unquote(v.Data.VNCProxyURL) +} diff --git a/apis/rcs/backup.go b/apis/rcs/backup.go new file mode 100644 index 0000000..20c527f --- /dev/null +++ b/apis/rcs/backup.go @@ -0,0 +1,58 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type CreateRcsBackupRequest struct { + Label string `json:"label"` // 备份名称 +} + +type RcsSetBackupOptionsRequest struct { + AutoBackupHour int `json:"auto_backup_hour"` // 自动备份时间的小时 + AutoBackupMinute int `json:"auto_backup_minute"` // 自动备份时间的分钟 + KeepLast int `json:"keep_last"` // 保留份数(1/3/7) +} + +func (s *RcsService) CreateRcsBackup(id int, label string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/backup", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, CreateRcsBackupRequest{Label: label}, &resp) + return &resp, err +} + +func (s *RcsService) DeleteRcsBackup(id, bid int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/backup/%d", id, bid) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) CancelRcsBackup(id, bid int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/backup/%d/cancel", id, bid) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) RestoreRcsBackup(id, bid int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/backup/%d/restore", id, bid) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) EnableRcsAutoBackup(id int, req *RcsSetBackupOptionsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/backup/setting", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PATCH, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/changeos.go b/apis/rcs/changeos.go new file mode 100644 index 0000000..3cd46b8 --- /dev/null +++ b/apis/rcs/changeos.go @@ -0,0 +1,26 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type ReinstallRcsRequest struct { + AppVars []struct { + AppID int `json:"app_id"` + Retry bool `json:"retry"` // 重发之前的任务,此项存在时,无需传入参数 + Vars any `json:"vars"` + } `json:"app_vars"` // 当空数组时,进行单次任务下发 + OsID int `json:"os_id"` // 系统ID + ResetOsd bool `json:"reset_osd"` // 重置系统盘容量 +} + +func (s *RcsService) ReinstallRcs(id int, req *ReinstallRcsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/changeos", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/create_rcs.go b/apis/rcs/create_rcs.go new file mode 100644 index 0000000..fa755e6 --- /dev/null +++ b/apis/rcs/create_rcs.go @@ -0,0 +1,36 @@ +package rcs + +import ( + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type CreateRcsRequest struct { + AddDiskSize int `json:"add_disk_size"` // 额外硬盘容量GB + PlanID int `json:"plan_id"` // 套餐ID + Duration int `json:"duration"` // 创建时长(月) + OsID int `json:"os_id"` // 系统ID + WithEipNum int `json:"with_eip_num"` // 创建IP数量 + WithEipFlags string `json:"with_eip_flags"` // 是否开启高防,us_ddosip -> 美国高防,nb_ddosip -> 宁波高防 + WithEipType string `json:"with_eip_type"` // ipv4(默认)/ipv6 + WithCouponID int `json:"with_coupon_id"` // 优惠券ID + Try bool `json:"try"` // 是否为试用 + NodeUUID string `json:"node_uuid"` // 指定节点(管理员可用,用户不可用) + AppVars []struct { + AppID int `json:"app_id"` + Vars any `json:"vars,omitempty"` + } `json:"app_vars"` // 预装应用 + Zone string `json:"zone"` // 内网可用区 +} + +type CreateRcsResponse struct { + Code int `json:"code"` + Data RcsRecord `json:"data"` +} + +func (s *RcsService) CreateRcs(req *CreateRcsRequest) (*CreateRcsResponse, error) { + path := "/product/rcs" + + var resp CreateRcsResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/edisk.go b/apis/rcs/edisk.go new file mode 100644 index 0000000..ef6f36e --- /dev/null +++ b/apis/rcs/edisk.go @@ -0,0 +1,36 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type RcsManagesElasticCloudDisksRequest struct { + Actions []struct { + Type string `json:"type"` // 操作类型: expand: 扩容, create: 创建 + Action any `json:"action"` // 操作参数, RcsManagesElasticCloudDisksExpand或RcsManagesElasticCloudDisksCreate + } `json:"actions"` +} + +type RcsManagesElasticCloudDisksExpand struct { + EdiskID int `json:"edisk_id"` // 弹性云盘ID + SizeInGb int `json:"size_in_gb"` // 操作容量 + Backup bool `json:"backup"` // 支持备份 +} + +type RcsManagesElasticCloudDisksCreate struct { + SizeInGb int `json:"size_in_gb"` // 操作容量 + DiskType string `json:"disk_type"` // 磁盘类型(ssd/hdd) + Backup bool `json:"backup"` // 支持备份 + Tag string `json:"tag"` // 标签 +} + +func (s *RcsService) RcsManagesElasticCloudDisks(id int, req *RcsManagesElasticCloudDisksRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/edisk", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/eip.go b/apis/rcs/eip.go new file mode 100644 index 0000000..cec8f30 --- /dev/null +++ b/apis/rcs/eip.go @@ -0,0 +1,61 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type SetRcsEipDescriptionRequest struct { + IP string `json:"ip"` + Description string `json:"description"` +} + +type CreateAndBindIpToRcsRequest struct { + WithFlags string `json:"with_flags"` // IP特征(可选): 应该是高防: us_ddosip -> 美国高防,nb_ddosip -> 宁波高防 + WithIPNum int `json:"with_ip_num"` // IP数量 + WithIPType string `json:"with_ip_type"` // ipv4/ipv6 +} + +type ChangeRcsIPRequest struct { + DisableOldIPReason string `json:"disable_old_ip_reason"` // 可选 + IP string `json:"ip"` // IP地址 + ToIP string `json:"to_ip"` // 可选 +} + +type DisCardRcsIPRequest struct { + IP string `json:"ip"` +} + +func (s *RcsService) SetRcsEipDescription(id int, ip, desc string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/eip/description", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, SetRcsEipDescriptionRequest{IP: ip, Description: desc}, &resp) + return &resp, err +} + +func (s *RcsService) CreateAndBindElasticIpToRcs(id int, req *CreateAndBindIpToRcsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/eip", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +func (s *RcsService) ChangeRcsIP(id int, req *ChangeRcsIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/eip/change", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +func (s *RcsService) DisCardRcsIP(id int, req DisCardRcsIPRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/eip/discard", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/firewall.go b/apis/rcs/firewall.go new file mode 100644 index 0000000..8a1b5bd --- /dev/null +++ b/apis/rcs/firewall.go @@ -0,0 +1,86 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRcsFirewallRulesRequest struct { + Options common.StandQueryParameters `json:"options"` +} + +type GetRcsFirewallRulesResponse struct { + Code int `json:"code"` + Data RcsFirewallRuleList `json:"data"` +} + +type RcsFirewallRuleList struct { + TotalRecords int `json:"TotalRecords"` + Records []RcsFirewallRule `json:"Records"` +} + +type RcsFirewallRule struct { + ID int `json:"ID"` + VID int `json:"v_id"` + IsEnable bool `json:"is_enable"` + Pos int `json:"pos"` + SourceAddress string `json:"source_address"` + DestPort string `json:"dest_port"` + SourcePort string `json:"source_port"` + Protocol string `json:"protocol"` + Action string `json:"action"` + Description string `json:"description"` +} + +type SetRcsFirewallRuleRequest struct { + Action string `json:"action"` // 动作,accept/drop,接受或者丢弃 + Description string `json:"description"` // 备注(可选) + DestPort string `json:"dest_port"` // 代表本机的目的端口,可以用-来链接,空白代表所有端口(可选) + ID int `json:"id"` // 规则ID(可选) + IsEnable bool `json:"is_enable"` // 是否启用该规则(可选) + Protocol string `json:"protocol"` // 协议,udp/tcp/icmp,空白代表所有(可选) + SourceAddress string `json:"source_address"` // 代表来源的地址,可以用-链接范围,或者用逗号来分割多个地址,可以使用网络,CIDR格式,空则代表所有地址(可选) + SourcePort string `json:"source_port"` // 一般不填(防反射)(可选) +} + +type MobileRcsFirewallRulePriorityRequest struct { + NewPos int `json:"newPos"` +} + +func (s *RcsService) GetRcsFirewallRules(id int, req *GetRcsFirewallRulesRequest) (*GetRcsFirewallRulesResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/firewall/rule", id) + + var resp GetRcsFirewallRulesResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +func (s *RcsService) SetRcsFirewallRule(id int, req *SetRcsFirewallRuleRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/firewall/rule", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +func (s *RcsService) DeleteRcsFirewallRule(id, ruleID int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/firewall/rule/%d", id, ruleID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_DELETE, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) MobileRcsFirewallRulePriority(id, ruleID int, req MobileRcsFirewallRulePriorityRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/firewall/rule/%d/pos", id, ruleID) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_PUT, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/get_rcs_detail.go b/apis/rcs/get_rcs_detail.go new file mode 100644 index 0000000..39dcf89 --- /dev/null +++ b/apis/rcs/get_rcs_detail.go @@ -0,0 +1,124 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRcsDetailResponse struct { + Code int `json:"code"` + Data RcsDetail `json:"data"` +} + +type RcsDetail struct { + Data RcsRecord `json:"Data"` + UpgradeablePlans []UpgradeablePlan `json:"UpgradeablePlans"` + RBSList []RBSItem `json:"RBSList"` + NatList []any `json:"NatList"` + EDiskList []EDiskItem `json:"EDiskList"` + EIPList []EIPItem `json:"EIPList"` + RenewPointPrice RenewPointPrice `json:"RenewPointPrice"` + FastInstallAppTask []any `json:"FastInstallAppTask"` + VNets []any `json:"VNets"` +} + +type UpgradeablePlan struct { + ID int `json:"id"` + Region string `json:"region"` + Subtype string `json:"subtype"` + PlanName string `json:"plan_name"` + Machine string `json:"machine"` + ChargeType string `json:"charge_type"` + Chinese string `json:"chinese"` + IsFree bool `json:"is_free"` + PointRenewPrice any `json:"point_renew_price"` + IsSelling bool `json:"is_selling"` + Price int `json:"price"` + TrafficBaseGb int `json:"traffic_base_gb"` + TrafficPrice any `json:"traffic_price"` + CPU int `json:"cpu"` + Memory int `json:"memory"` + NetIn int `json:"net_in"` + NetOut int `json:"net_out"` + IPPrices any `json:"ip_prices"` + IPSelling any `json:"ip_selling"` + AutoRestock int `json:"auto_restock"` + AvailableStock int `json:"available_stock"` + GpuMemorySize int `json:"gpu_memory_size"` + DgpuDevType string `json:"dgpu_dev_type"` + WebbarConfig any `json:"webbar_config"` + NoBackup bool `json:"no_backup"` + DiskPrice DiskPrice `json:"disk_price"` +} + +type RBSItem struct { + ID int `json:"ID"` + UID int `json:"UID"` + ProductID int `json:"ProductID"` + NodeUUID string `json:"NodeUUID"` + Node Node `json:"Node"` + Label string `json:"Label"` + FileName string `json:"FileName"` + PackSize int64 `json:"PackSize"` + CreateTime int `json:"CreateTime"` + FinishTime int `json:"FinishTime"` + Retry int `json:"Retry"` + AdditionalInfo RBSAdditionalInfo `json:"AdditionalInfo"` + Status string `json:"Status"` +} + +type RBSAdditionalInfo struct { + Osid int `json:"OSID"` + OSName string `json:"OSName"` + OSBaseDiskSize int `json:"OSBaseDiskSize"` + OSDataDiskSize int `json:"OSDataDiskSize"` + Slots map[string]RBSSlot `json:"Slots"` +} + +type RBSSlot struct { + DiskType string `json:"DiskType"` + Backup bool `json:"Backup"` + Size int `json:"Size"` +} + +type EDiskItem struct { + ID int `json:"ID"` + Slot int `json:"Slot"` + UID int `json:"UID"` + DiskType string `json:"DiskType"` + Tag string `json:"Tag"` + OSName string `json:"OSName"` + Vid int `json:"VID"` + Size int `json:"Size"` + Backup bool `json:"Backup"` +} + +type EIPItem struct { + ID int `json:"ID"` + IPRegion string `json:"IpRegion"` + Region string `json:"Region"` + Type string `json:"Type"` + IP string `json:"IP"` + Gateway string `json:"Gateway"` + Block string `json:"Block"` + UID int `json:"UID"` + Vid int `json:"VID"` + CreateDate int `json:"CreateDate"` + Flags string `json:"Flags"` + VlanID int `json:"VlanID"` + Description string `json:"Description"` +} + +type RenewPointPrice struct { + Num7 int `json:"7"` + Num31 int `json:"31"` +} + +func (s *RcsService) GetRcsDetail(id int) (*GetRcsDetailResponse, error) { + path := fmt.Sprintf("/product/rcs/%d", id) + + var resp GetRcsDetailResponse + err := s.client.Do(constant.HTTPMethod_GET, path, nil, nil, &resp) + return &resp, err +} diff --git a/apis/rcs/get_rcs_list.go b/apis/rcs/get_rcs_list.go index 331e9ff..ce6879b 100644 --- a/apis/rcs/get_rcs_list.go +++ b/apis/rcs/get_rcs_list.go @@ -47,9 +47,9 @@ type UsageData struct { UsedMem int `json:"UsedMem"` Disks DiskUsageData `json:"Disks"` DiskRead int `json:"DiskRead"` - DiskWrite int `json:"DiskWrite"` + DiskWrite float64 `json:"DiskWrite"` NetOut float64 `json:"NetOut"` - NetIn int `json:"NetIn"` + NetIn float64 `json:"NetIn"` SmartHealth any `json:"SmartHealth"` SmartTemp int `json:"SmartTemp"` UpdateTime int `json:"UpdateTime"` diff --git a/apis/rcs/lifecycle.go b/apis/rcs/lifecycle.go new file mode 100644 index 0000000..492231c --- /dev/null +++ b/apis/rcs/lifecycle.go @@ -0,0 +1,64 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type ResetRcsPasswordRequest struct { + Password string `json:"password"` // 新密码,留空则自动生成 +} + +type SetRcsTagRequest struct { + TagName string `json:"tag_name"` +} + +func (s *RcsService) FreeRcs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/free", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) RebootRcs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/reboot", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) ResetRcsPassword(id int, newPass string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/reset-password", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, ResetRcsPasswordRequest{Password: newPass}, &resp) + return &resp, err +} + +func (s *RcsService) StartRcs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/start", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) StopRcs(id int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/stop", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, nil, &resp) + return &resp, err +} + +func (s *RcsService) SetRcsTag(id int, tag string) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/tag", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, SetRcsTagRequest{TagName: tag}, &resp) + return &resp, err +} diff --git a/apis/rcs/monitor.go b/apis/rcs/monitor.go new file mode 100644 index 0000000..b05ab54 --- /dev/null +++ b/apis/rcs/monitor.go @@ -0,0 +1,36 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRcsMonitorDataRequest struct { + StartDate int `json:"start_date"` // 开始时间(时间戳) + EndDate int `json:"end_date"` // 结束时间(时间戳) +} + +type GetRcsMonitorDataResponse struct { + Code int `json:"code"` + Data RcsMonitorData `json:"data"` +} + +// RcsMonitorData 监控数据, Columns 与 Values 一一对应 +type RcsMonitorData struct { + Columns []string `json:"Columns"` + Values [][]float64 `json:"Values"` +} + +func (s *RcsService) GetRcsMonitorData(id int, req *GetRcsMonitorDataRequest) (*GetRcsMonitorDataResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/monitor", id) + + var resp GetRcsMonitorDataResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/rcs/nat.go b/apis/rcs/nat.go new file mode 100644 index 0000000..26386c3 --- /dev/null +++ b/apis/rcs/nat.go @@ -0,0 +1,39 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type AddRcsNatPortMappingRequest struct { + PortIn int `json:"port_in"` // >= 1 <= 65535 + PortOut int `json:"port_out"` // >= 10000 <= 60000 + PortType string `json:"port_type"` // tcp/udp/tcp_udp + Tag string `json:"tag"` // 可选 +} + +type DeleteRcsNatPortMappingRequest struct { + NatID int `json:"nat_id"` +} + +func (s *RcsService) AddRcsNatPortMapping(id int, req *AddRcsNatPortMappingRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/nat", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +func (s *RcsService) DeleteRcsNatPortMapping(id int, req *DeleteRcsNatPortMappingRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/nat", id) + + var resp common.BasicOperationResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + err = s.client.Do(constant.HTTPMethod_DELETE, path, querys, nil, &resp) + return &resp, err +} diff --git a/apis/rcs/renew.go b/apis/rcs/renew.go new file mode 100644 index 0000000..deb4be6 --- /dev/null +++ b/apis/rcs/renew.go @@ -0,0 +1,82 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type GetRcsRenewPriceRequest struct { + ProductID int `json:"product_id"` + Duration int `json:"duration"` + WithCouponID int `json:"with_coupon_id"` +} + +type GetRcsRenewPriceResponse struct { + Code int `json:"code"` + Data RcsRenewPrice `json:"data"` +} + +type RcsRenewPrice struct { + Detail RcsRenewPriceDetail `json:"detail"` + Price float64 `json:"price"` +} + +type RcsRenewPriceDetail struct { + Price float64 `json:"price"` + AgentPrice float64 `json:"agent_price"` + StockPrice float64 `json:"stock_price"` + DefaultPrice int `json:"default_price"` + CouponValue int `json:"coupon_value"` + SaleReward int `json:"sale_reward"` + AgentReward int `json:"agent_reward"` + AgentID int `json:"agent_id"` + IgnoreAgent bool `json:"ignore_agent"` + PerScene RcsRenewPerScene `json:"per_scene"` +} + +type RcsRenewPerScene struct { + Eip int `json:"eip"` + Renew float64 `json:"renew"` // 配置价格 + RenewEip float64 `json:"renew_eip"` // IP价格 +} + +type RenewRcsRequest struct { + Duration int `json:"duration"` // 续费时长(月) + WithCouponID int `json:"with_coupon_id"` // 优惠券ID +} + +type EnableRcsAutoRenewRequest struct { + AutoRenewOption bool `json:"auto_renew_option"` +} + +func (s *RcsService) GetRcsRenewPrice(req *GetRcsRenewPriceRequest) (*GetRcsRenewPriceResponse, error) { + path := "/product/rcs/price" + + var resp GetRcsRenewPriceResponse + querys, err := common.MarshalQueryParams(req) + if err != nil { + return nil, err + } + querys["scene"] = "renew" + querys["is_old"] = "true" + err = s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +func (s *RcsService) RenewRcs(id int, req RenewRcsRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/renew", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} + +func (s *RcsService) EnableRcsAutoRenew(id int, req EnableRcsAutoRenewRequest) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/renew/option", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, req, &resp) + return &resp, err +} diff --git a/apis/rcs/traffic.go b/apis/rcs/traffic.go new file mode 100644 index 0000000..c88b6c1 --- /dev/null +++ b/apis/rcs/traffic.go @@ -0,0 +1,33 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type ChargeRcsTraficRequest struct { + TrafficInGb int `json:"traffic_in_gb"` // 充多少G +} + +type LimitRcsTrafficRequest struct { + DayTrafficInGb int `json:"day_traffic_in_gb"` // 日流量阈值(G) + TrafficLimit int `json:"traffic_limit"` // 限制带宽(M) +} + +func (s *RcsService) ChargeRcsTrafic(id, count int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/traffic/charge", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, ChargeRcsTraficRequest{TrafficInGb: count}, &resp) + return &resp, err +} + +func (s *RcsService) LimitRcsTrafic(id, threshold, limit int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/traffic/limit", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, LimitRcsTrafficRequest{DayTrafficInGb: threshold, TrafficLimit: limit}, &resp) + return &resp, err +} diff --git a/apis/rcs/upgrade.go b/apis/rcs/upgrade.go new file mode 100644 index 0000000..58049cb --- /dev/null +++ b/apis/rcs/upgrade.go @@ -0,0 +1,21 @@ +package rcs + +import ( + "fmt" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +type UpgradeRcsRequest struct { + DestPlan int `json:"dest_plan"` // 升级到的套餐ID + WithCouponID int `json:"with_coupon_id"` // 优惠券ID,默认为0 +} + +func (s *RcsService) UpgradeRcs(id, plan, coupon int) (*common.BasicOperationResponse, error) { + path := fmt.Sprintf("/product/rcs/%d/upgrade", id) + + var resp common.BasicOperationResponse + err := s.client.Do(constant.HTTPMethod_POST, path, nil, UpgradeRcsRequest{DestPlan: plan, WithCouponID: coupon}, &resp) + return &resp, err +} diff --git a/apis/rcs/vnc.go b/apis/rcs/vnc.go new file mode 100644 index 0000000..f8d088b --- /dev/null +++ b/apis/rcs/vnc.go @@ -0,0 +1,36 @@ +package rcs + +import ( + "fmt" + "net/url" + + "github.com/XingfenD/rainyun_api_go_sdk/apis/common" + "github.com/XingfenD/rainyun_api_go_sdk/constant" +) + +// GetRcsVnc 连接VNC +// +// consoleType: 控制台类型,可选值: novnc,xtermjs +func (s *RcsService) GetRcsVnc(id int, consoleType string) (*common.VncConnectionInfo, error) { + path := fmt.Sprintf("/product/rcs/%d/vnc", id) + + var resp common.VncConnectionInfo + querys := map[string]string{"console_type": consoleType} + err := s.client.Do(constant.HTTPMethod_GET, path, querys, nil, &resp) + return &resp, err +} + +// GetRcsPveAddress 获取RCS对应的PVE地址 +func (s *RcsService) GetRcsPveAddress(id int) (string, error) { + v, err := s.GetRcsVnc(id, "novnc") + if err != nil { + return "", err + } + + parsedURL, err := url.Parse(v.Data.RequestURL) + if err != nil { + return "", err + } + + return parsedURL.Hostname(), nil +} diff --git a/constant/method.go b/constant/method.go index 2a7a2ab..9a0afe2 100644 --- a/constant/method.go +++ b/constant/method.go @@ -7,4 +7,5 @@ const ( HTTPMethod_POST HTTPMethod = "POST" HTTPMethod_DELETE HTTPMethod = "DELETE" HTTPMethod_PUT HTTPMethod = "PUT" + HTTPMethod_PATCH HTTPMethod = "PATCH" ) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index c0aade5..ff0b6f2 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,14 @@ All notable changes to this template should be documented in this file. The format loosely follows Keep a Changelog and can be adapted to the team's habits. 本文档参考了 Keep a Changelog 的思路,也可以根据团队习惯调整。 +## [0.1.0] - 2026-08-05 + +### Added / 新增 + +- 从 `rainyun-go-sdk` 迁移 RCS 全部 35 个接口(列表/详情/创建/备份/防火墙/监控/NAT/续费/升降级等),响应结构体嵌套已拆分复用(`RcsRecord`、`Node`、`Plan`、`OsInfo`、`UsageData` 等)。 +- 新增 `apis/common` 基础类型:`BasicOperationResponse`、`VncConnectionInfo`。 +- `constant` 新增 `HTTPMethod_PATCH`。 + ## [0.0.0] - 2026-08-02 ### Notes / 说明