初始提交:OCI 面板后端(含 GenAI 网关一期)
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"oci-portal/internal/oci"
|
||||
)
|
||||
|
||||
func (h *ociConfigHandler) availabilityDomains(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
ads, err := h.svc.AvailabilityDomains(c.Request.Context(), id, c.Query("region"))
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, ads)
|
||||
}
|
||||
|
||||
// ---- 实例 ----
|
||||
|
||||
type createInstanceRequest struct {
|
||||
Region string `json:"region"`
|
||||
CompartmentID string `json:"compartmentId"` // 为空时建在租户根
|
||||
AvailabilityDomain string `json:"availabilityDomain"` // 为空时默认使用第一个可用域
|
||||
DisplayName string `json:"displayName" binding:"required"`
|
||||
Shape string `json:"shape" binding:"required"`
|
||||
Count int `json:"count"` // 批量创建数量,缺省 1,上限 10
|
||||
Ocpus float32 `json:"ocpus"`
|
||||
MemoryInGBs float32 `json:"memoryInGBs"`
|
||||
ImageID string `json:"imageId"`
|
||||
BootVolumeID string `json:"bootVolumeId"`
|
||||
BootVolumeSizeGBs int64 `json:"bootVolumeSizeGBs"`
|
||||
BootVolumeVpusPerGB int64 `json:"bootVolumeVpusPerGB"`
|
||||
SubnetID string `json:"subnetId"` // 为空时自动创建 VCN 与子网
|
||||
AssignPublicIP bool `json:"assignPublicIp"`
|
||||
AssignIpv6 bool `json:"assignIpv6"`
|
||||
SSHPublicKey string `json:"sshPublicKey"`
|
||||
RootPassword string `json:"rootPassword"`
|
||||
GenerateRootPassword bool `json:"generateRootPassword"` // 服务端生成随机 root 密码并写入 TAG RootPassword
|
||||
UserData string `json:"userData"`
|
||||
}
|
||||
|
||||
type updateInstanceRequest struct {
|
||||
Region string `json:"region"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Shape string `json:"shape"` // 更换 shape,运行中实例会自动重启
|
||||
Ocpus float32 `json:"ocpus"`
|
||||
MemoryInGBs float32 `json:"memoryInGBs"`
|
||||
}
|
||||
|
||||
type instanceActionRequest struct {
|
||||
Region string `json:"region"`
|
||||
Action string `json:"action" binding:"required"`
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) listInstances(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
instances, err := h.svc.Instances(c.Request.Context(), id, c.Query("region"), c.Query("compartmentId"))
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, instances)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) createInstance(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req createInstanceRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
count := req.Count
|
||||
if count == 0 {
|
||||
count = 1
|
||||
}
|
||||
instances, failures, err := h.svc.CreateInstances(c.Request.Context(), id, oci.CreateInstanceInput{
|
||||
Region: req.Region,
|
||||
CompartmentID: req.CompartmentID,
|
||||
AvailabilityDomain: req.AvailabilityDomain,
|
||||
DisplayName: req.DisplayName,
|
||||
Shape: req.Shape,
|
||||
Ocpus: req.Ocpus,
|
||||
MemoryInGBs: req.MemoryInGBs,
|
||||
ImageID: req.ImageID,
|
||||
BootVolumeID: req.BootVolumeID,
|
||||
BootVolumeSizeGBs: req.BootVolumeSizeGBs,
|
||||
BootVolumeVpusPerGB: req.BootVolumeVpusPerGB,
|
||||
SubnetID: req.SubnetID,
|
||||
AssignPublicIP: req.AssignPublicIP,
|
||||
AssignIpv6: req.AssignIpv6,
|
||||
SSHPublicKey: req.SSHPublicKey,
|
||||
RootPassword: req.RootPassword,
|
||||
GenerateRootPassword: req.GenerateRootPassword,
|
||||
UserData: req.UserData,
|
||||
}, count)
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
// 全部失败视为执行失败,部分成功仍返回 201 并附带逐台失败信息
|
||||
status := http.StatusCreated
|
||||
if len(instances) == 0 && len(failures) > 0 {
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
// nil 切片会序列化为 null,显式空数组免去前端判空
|
||||
if instances == nil {
|
||||
instances = []oci.Instance{}
|
||||
}
|
||||
if failures == nil {
|
||||
failures = []string{}
|
||||
}
|
||||
c.JSON(status, gin.H{"instances": instances, "errors": failures})
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) getInstance(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
instance, err := h.svc.Instance(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"))
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, instance)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) updateInstance(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req updateInstanceRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
instance, err := h.svc.UpdateInstance(c.Request.Context(), id, c.Param("instanceId"), oci.UpdateInstanceInput{
|
||||
Region: req.Region,
|
||||
DisplayName: req.DisplayName,
|
||||
Shape: req.Shape,
|
||||
Ocpus: req.Ocpus,
|
||||
MemoryInGBs: req.MemoryInGBs,
|
||||
})
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, instance)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) terminateInstance(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
preserve := c.Query("preserveBootVolume") == "true"
|
||||
if err := h.svc.TerminateInstance(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"), preserve); err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) instanceAction(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req instanceActionRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
instance, err := h.svc.InstanceAction(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.Action)
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, instance)
|
||||
}
|
||||
|
||||
// ---- 引导卷 ----
|
||||
|
||||
type updateBootVolumeRequest struct {
|
||||
Region string `json:"region"`
|
||||
DisplayName string `json:"displayName"`
|
||||
SizeInGBs int64 `json:"sizeInGBs"`
|
||||
VpusPerGB int64 `json:"vpusPerGB"`
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) listBootVolumes(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
volumes, err := h.svc.BootVolumes(c.Request.Context(), id, c.Query("region"), c.Query("availabilityDomain"), c.Query("compartmentId"))
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, volumes)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) getBootVolume(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
volume, err := h.svc.BootVolume(c.Request.Context(), id, c.Query("region"), c.Param("bootVolumeId"))
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, volume)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) updateBootVolume(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var req updateBootVolumeRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
volume, err := h.svc.UpdateBootVolume(c.Request.Context(), id, c.Param("bootVolumeId"), oci.UpdateBootVolumeInput{
|
||||
Region: req.Region,
|
||||
DisplayName: req.DisplayName,
|
||||
SizeInGBs: req.SizeInGBs,
|
||||
VpusPerGB: req.VpusPerGB,
|
||||
})
|
||||
if err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, volume)
|
||||
}
|
||||
|
||||
func (h *ociConfigHandler) deleteBootVolume(c *gin.Context) {
|
||||
id, ok := pathID(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if err := h.svc.DeleteBootVolume(c.Request.Context(), id, c.Query("region"), c.Param("bootVolumeId")); err != nil {
|
||||
respondError(c, err)
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
Reference in New Issue
Block a user