remove debug string methods,
simplify PCI devices
This commit is contained in:
parent
73a53d4d47
commit
4269867661
49
app/app.go
49
app/app.go
@ -5,12 +5,14 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/luthermonson/go-proxmox"
|
"github.com/luthermonson/go-proxmox"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APIVersion string = "0.0.1"
|
const APIVersion string = "0.0.2"
|
||||||
|
|
||||||
var client ProxmoxClient
|
var client ProxmoxClient
|
||||||
|
|
||||||
@ -26,18 +28,12 @@ func Run() {
|
|||||||
token := fmt.Sprintf(`%s@%s!%s`, config.PVE.Token.USER, config.PVE.Token.REALM, config.PVE.Token.ID)
|
token := fmt.Sprintf(`%s@%s!%s`, config.PVE.Token.USER, config.PVE.Token.REALM, config.PVE.Token.ID)
|
||||||
client = NewClient(token, config.PVE.Token.Secret)
|
client = NewClient(token, config.PVE.Token.Secret)
|
||||||
|
|
||||||
//router := gin.Default()
|
router := gin.Default()
|
||||||
|
|
||||||
start := time.Now()
|
|
||||||
cluster := Cluster{}
|
cluster := Cluster{}
|
||||||
cluster.Init(client)
|
cluster.Init(client)
|
||||||
cluster.Rebuild()
|
cluster.Rebuild()
|
||||||
elapsed := time.Since(start)
|
|
||||||
|
|
||||||
fmt.Println(cluster)
|
|
||||||
fmt.Println(elapsed)
|
|
||||||
|
|
||||||
/*
|
|
||||||
router.GET("/version", func(c *gin.Context) {
|
router.GET("/version", func(c *gin.Context) {
|
||||||
PVEVersion, err := client.Version()
|
PVEVersion, err := client.Version()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,14 +44,39 @@ func Run() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.GET("/nodes/:node", func(c *gin.Context) {
|
router.GET("/nodes/:node", func(c *gin.Context) {
|
||||||
Node, err := client.Node(c.Param("node"))
|
node := c.Param("node")
|
||||||
if err != nil {
|
Host, ok := cluster.Hosts[node]
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
if !ok {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("%s not found in cluster", node)})
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
c.JSON(http.StatusOK, gin.H{"node": Node})
|
c.JSON(http.StatusOK, gin.H{"node": Host})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.GET("/nodes/:node/instances/:instance", func(c *gin.Context) {
|
||||||
|
host := c.Param("node")
|
||||||
|
vmid, err := strconv.ParseUint(c.Param("instance"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("%s could not be converted to vmid (uint)", c.Param("instance"))})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Node, ok := cluster.Hosts[host]
|
||||||
|
if !ok {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("vmid %s not found in cluster", host)})
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
Instance, ok := Node.Instances[uint(vmid)]
|
||||||
|
if !ok {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("%d not found in %s", vmid, host)})
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
c.JSON(http.StatusOK, gin.H{"instance": Instance})
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Run("0.0.0.0:" + strconv.Itoa(config.ListenPort))
|
router.Run("0.0.0.0:" + strconv.Itoa(config.ListenPort))
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
118
app/model.go
118
app/model.go
@ -9,7 +9,6 @@ import (
|
|||||||
type Cluster struct {
|
type Cluster struct {
|
||||||
pve ProxmoxClient
|
pve ProxmoxClient
|
||||||
Hosts map[string]*Host
|
Hosts map[string]*Host
|
||||||
//Instance map[uint]*Instance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cluster *Cluster) Init(pve ProxmoxClient) {
|
func (cluster *Cluster) Init(pve ProxmoxClient) {
|
||||||
@ -77,7 +76,7 @@ func (host *Host) RebuildVM(vmid uint) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
host.Instance[vmid] = &instance
|
host.Instances[vmid] = &instance
|
||||||
|
|
||||||
for volid := range instance.configDisks {
|
for volid := range instance.configDisks {
|
||||||
instance.RebuildVolume(host, volid)
|
instance.RebuildVolume(host, volid)
|
||||||
@ -100,7 +99,7 @@ func (host *Host) RebuildCT(vmid uint) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
host.Instance[vmid] = &instance
|
host.Instances[vmid] = &instance
|
||||||
|
|
||||||
for volid := range instance.configDisks {
|
for volid := range instance.configDisks {
|
||||||
instance.RebuildVolume(host, volid)
|
instance.RebuildVolume(host, volid)
|
||||||
@ -121,7 +120,7 @@ func (instance *Instance) RebuildVolume(host *Host, volid string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.Volume[volid] = &volume
|
instance.Volumes[volid] = &volume
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -138,7 +137,7 @@ func (instance *Instance) RebuildNet(netid string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.Net[uint(idnum)] = &netinfo
|
instance.Nets[uint(idnum)] = &netinfo
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -157,113 +156,20 @@ func (instance *Instance) RebuildDevice(host Host, deviceid string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if DeviceBusIDIsSuperDevice(hostDeviceBusID) {
|
if DeviceBusIDIsSuperDevice(hostDeviceBusID) {
|
||||||
hostSuperDevice := host.Hardware[hostDeviceBusID]
|
devices := []*Device{}
|
||||||
subDevices := []*HostDevice{}
|
for k, v := range host.Devices {
|
||||||
for _, v := range hostSuperDevice.Devices {
|
if DeviceBusIDIsSubDevice(k, hostDeviceBusID) {
|
||||||
v.Reserved = true
|
v.Reserved = true
|
||||||
subDevices = append(subDevices, v)
|
devices = append(devices, v)
|
||||||
}
|
}
|
||||||
instance.Device[uint(instanceDeviceBusID)] = &InstanceDevice{
|
|
||||||
Device: subDevices,
|
|
||||||
PCIE: strings.Contains(instanceDevice, "pcie=1"),
|
|
||||||
}
|
}
|
||||||
|
instance.Devices[uint(instanceDeviceBusID)] = devices
|
||||||
} else {
|
} else {
|
||||||
_, hostSubdeviceBusID, err := SplitDeviceBusID(hostDeviceBusID)
|
devices := []*Device{}
|
||||||
if err != nil {
|
v := host.Devices[hostDeviceBusID]
|
||||||
return err
|
|
||||||
}
|
|
||||||
v := host.Hardware[hostDeviceBusID].Devices[hostSubdeviceBusID]
|
|
||||||
v.Reserved = true
|
v.Reserved = true
|
||||||
instance.Device[uint(instanceDeviceBusID)] = &InstanceDevice{
|
instance.Devices[uint(instanceDeviceBusID)] = devices
|
||||||
Device: []*HostDevice{v},
|
|
||||||
PCIE: strings.Contains(instanceDevice, "pcie=1"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cluster Cluster) String() string {
|
|
||||||
r := ""
|
|
||||||
for _, host := range cluster.Hosts {
|
|
||||||
r += host.String()
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (host Host) String() string {
|
|
||||||
r := fmt.Sprintf("%s\n\tCores:\t%s\n\tMemory:\t%s\n\tSwap:\t%s\n", host.Name, host.Cores, host.Memory, host.Swap)
|
|
||||||
|
|
||||||
r += "\tHardware:\n"
|
|
||||||
|
|
||||||
for _, superdevice := range host.Hardware {
|
|
||||||
r += fmt.Sprintf("%s\n", superdevice)
|
|
||||||
}
|
|
||||||
|
|
||||||
r += "\tInstances:\n"
|
|
||||||
|
|
||||||
for vmid, vm := range host.Instance {
|
|
||||||
r += fmt.Sprintf("\t\t%d: %s\n", vmid, vm)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Resource) String() string {
|
|
||||||
return fmt.Sprintf("Totl: %d, Rsrv: %d, Free: %d", r.Total, r.Reserved, r.Free)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (superdevice HostSuperDevice) String() string {
|
|
||||||
s := fmt.Sprintf("\t\t%s: %s %s -> ", superdevice.BusID, superdevice.VendorName, superdevice.DeviceName)
|
|
||||||
numunused := 0
|
|
||||||
for _, device := range superdevice.Devices {
|
|
||||||
if device.Reserved {
|
|
||||||
s += fmt.Sprintf("%s:(Rsrv %t, %s %s: %s %s)", device.SubID, device.Reserved, superdevice.VendorName, device.SubVendorName, superdevice.DeviceName, device.SubDeviceName)
|
|
||||||
} else {
|
|
||||||
numunused++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += fmt.Sprintf("+%d unreserved subdevices", numunused)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i Instance) String() string {
|
|
||||||
if i.Type == VM {
|
|
||||||
r := fmt.Sprintf("VM, Name: %s, Proctype: %s, Cores: %d, Memory: %d\n", i.Name, i.Proctype, i.Cores, i.Memory)
|
|
||||||
for k, v := range i.Volume {
|
|
||||||
r += fmt.Sprintf("\t\t\t%s: %s\n", k, v)
|
|
||||||
}
|
|
||||||
for k, v := range i.Net {
|
|
||||||
r += fmt.Sprintf("\t\t\tnet%d: %s\n", k, v)
|
|
||||||
}
|
|
||||||
for k, v := range i.Device {
|
|
||||||
r += fmt.Sprintf("\t\t\thostpci%d: %s\n", k, v)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
} else {
|
|
||||||
r := fmt.Sprintf("CT, Name: %s, Cores: %d, Memory: %d, Swap: %d\n", i.Name, i.Cores, i.Memory, i.Swap)
|
|
||||||
for k, v := range i.Volume {
|
|
||||||
r += fmt.Sprintf("\t\t\t%s: %s\n", k, v)
|
|
||||||
}
|
|
||||||
for k, v := range i.Net {
|
|
||||||
r += fmt.Sprintf("\t\t\tnet%d: %s\n", k, v)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v Volume) String() string {
|
|
||||||
return fmt.Sprintf("id: %s, format: %s, size: %d", v.Volid, v.Format, v.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n Net) String() string {
|
|
||||||
return fmt.Sprintf("rate: %d, vlan: %d", n.Rate, n.VLAN)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d InstanceDevice) String() string {
|
|
||||||
r := ""
|
|
||||||
for _, v := range d.Device {
|
|
||||||
r += fmt.Sprintf("%s:%s ", v.SubVendorName, v.SubDeviceName)
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
@ -15,14 +15,6 @@ type ProxmoxClient struct {
|
|||||||
client *proxmox.Client
|
client *proxmox.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
type PVEDevice struct {
|
|
||||||
BusID string `json:"id"`
|
|
||||||
DeviceName string `json:"device_name"`
|
|
||||||
VendorName string `json:"vendor_name"`
|
|
||||||
SubsystemDeviceName string `json:"subsystem_device_name"`
|
|
||||||
SubsystemVendorName string `json:"subsystem_vendor_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewClient(token string, secret string) ProxmoxClient {
|
func NewClient(token string, secret string) ProxmoxClient {
|
||||||
HTTPClient := http.Client{
|
HTTPClient := http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
@ -67,44 +59,22 @@ func (pve ProxmoxClient) Nodes() ([]string, error) {
|
|||||||
// Gets a Node's resources but does not recursively expand instances
|
// Gets a Node's resources but does not recursively expand instances
|
||||||
func (pve ProxmoxClient) Node(nodeName string) (Host, error) {
|
func (pve ProxmoxClient) Node(nodeName string) (Host, error) {
|
||||||
host := Host{}
|
host := Host{}
|
||||||
host.Hardware = make(map[string]*HostSuperDevice)
|
host.Devices = make(map[string]*Device)
|
||||||
host.Instance = make(map[uint]*Instance)
|
host.Instances = make(map[uint]*Instance)
|
||||||
|
|
||||||
node, err := pve.client.Node(context.Background(), nodeName)
|
node, err := pve.client.Node(context.Background(), nodeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return host, err
|
return host, err
|
||||||
}
|
}
|
||||||
|
|
||||||
devices := []PVEDevice{}
|
devices := []Device{}
|
||||||
err = pve.client.Get(context.Background(), fmt.Sprintf("/nodes/%s/hardware/pci", nodeName), &devices)
|
err = pve.client.Get(context.Background(), fmt.Sprintf("/nodes/%s/hardware/pci", nodeName), &devices)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return host, err
|
return host, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// map supersystem devices to each contained subsystem
|
|
||||||
// eg 0000:00:05 -> [0000:00:05.0, 0000:00:05.1, 0000:00:05.2, 0000:00:05.3, ...]
|
|
||||||
for _, device := range devices {
|
for _, device := range devices {
|
||||||
SupersystemID, SubsystemID, err := SplitDeviceBusID(device.BusID)
|
host.Devices[device.BusID] = &device
|
||||||
if err != nil {
|
|
||||||
return host, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if host.Hardware[SupersystemID] == nil {
|
|
||||||
host.Hardware[SupersystemID] = &HostSuperDevice{
|
|
||||||
BusID: SupersystemID,
|
|
||||||
DeviceName: device.DeviceName,
|
|
||||||
VendorName: device.VendorName,
|
|
||||||
Devices: make(map[string]*HostDevice),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !DeviceBusIDIsSuperDevice(device.BusID) {
|
|
||||||
host.Hardware[SupersystemID].Devices[SubsystemID] = &HostDevice{
|
|
||||||
SubID: SubsystemID,
|
|
||||||
SubDeviceName: device.SubsystemDeviceName,
|
|
||||||
SubVendorName: device.SubsystemVendorName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
host.Name = node.Name
|
host.Name = node.Name
|
||||||
@ -149,9 +119,9 @@ func (host Host) VirtualMachine(VMID uint) (Instance, error) {
|
|||||||
instance.Proctype = vm.VirtualMachineConfig.CPU
|
instance.Proctype = vm.VirtualMachineConfig.CPU
|
||||||
instance.Cores = uint64(vm.VirtualMachineConfig.Cores)
|
instance.Cores = uint64(vm.VirtualMachineConfig.Cores)
|
||||||
instance.Memory = uint64(vm.VirtualMachineConfig.Memory) * MiB
|
instance.Memory = uint64(vm.VirtualMachineConfig.Memory) * MiB
|
||||||
instance.Volume = make(map[string]*Volume)
|
instance.Volumes = make(map[string]*Volume)
|
||||||
instance.Net = make(map[uint]*Net)
|
instance.Nets = make(map[uint]*Net)
|
||||||
instance.Device = make(map[uint]*InstanceDevice)
|
instance.Devices = make(map[uint][]*Device)
|
||||||
|
|
||||||
return instance, nil
|
return instance, nil
|
||||||
}
|
}
|
||||||
@ -197,8 +167,8 @@ func (host Host) Container(VMID uint) (Instance, error) {
|
|||||||
instance.Cores = uint64(ct.ContainerConfig.Cores)
|
instance.Cores = uint64(ct.ContainerConfig.Cores)
|
||||||
instance.Memory = uint64(ct.ContainerConfig.Memory) * MiB
|
instance.Memory = uint64(ct.ContainerConfig.Memory) * MiB
|
||||||
instance.Swap = uint64(ct.ContainerConfig.Swap) * MiB
|
instance.Swap = uint64(ct.ContainerConfig.Swap) * MiB
|
||||||
instance.Volume = make(map[string]*Volume)
|
instance.Volumes = make(map[string]*Volume)
|
||||||
instance.Net = make(map[uint]*Net)
|
instance.Nets = make(map[uint]*Net)
|
||||||
|
|
||||||
return instance, nil
|
return instance, nil
|
||||||
}
|
}
|
||||||
|
38
app/types.go
38
app/types.go
@ -13,16 +13,16 @@ type Host struct {
|
|||||||
Cores Resource
|
Cores Resource
|
||||||
Memory Resource
|
Memory Resource
|
||||||
Swap Resource
|
Swap Resource
|
||||||
Hardware map[string]*HostSuperDevice
|
Devices map[string]*Device
|
||||||
Instance map[uint]*Instance
|
Instances map[uint]*Instance
|
||||||
node *proxmox.Node
|
node *proxmox.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstanceType bool
|
type InstanceType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VM InstanceType = true
|
VM InstanceType = "VM"
|
||||||
CT InstanceType = false
|
CT InstanceType = "CT"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
@ -32,9 +32,9 @@ type Instance struct {
|
|||||||
Cores uint64
|
Cores uint64
|
||||||
Memory uint64
|
Memory uint64
|
||||||
Swap uint64
|
Swap uint64
|
||||||
Volume map[string]*Volume
|
Volumes map[string]*Volume
|
||||||
Net map[uint]*Net
|
Nets map[uint]*Net
|
||||||
Device map[uint]*InstanceDevice
|
Devices map[uint][]*Device
|
||||||
config interface{}
|
config interface{}
|
||||||
configDisks map[string]string
|
configDisks map[string]string
|
||||||
configNets map[string]string
|
configNets map[string]string
|
||||||
@ -54,21 +54,11 @@ type Net struct {
|
|||||||
VLAN uint64
|
VLAN uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstanceDevice struct {
|
type Device struct {
|
||||||
Device []*HostDevice
|
BusID string `json:"id"`
|
||||||
PCIE bool
|
DeviceName string `json:"device_name"`
|
||||||
}
|
VendorName string `json:"vendor_name"`
|
||||||
|
SubsystemDeviceName string `json:"subsystem_device_name"`
|
||||||
type HostSuperDevice struct {
|
SubsystemVendorName string `json:"subsystem_vendor_name"`
|
||||||
BusID string
|
|
||||||
DeviceName string
|
|
||||||
VendorName string
|
|
||||||
Devices map[string]*HostDevice
|
|
||||||
}
|
|
||||||
|
|
||||||
type HostDevice struct {
|
|
||||||
SubID string
|
|
||||||
SubDeviceName string
|
|
||||||
SubVendorName string
|
|
||||||
Reserved bool
|
Reserved bool
|
||||||
}
|
}
|
||||||
|
22
app/utils.go
22
app/utils.go
@ -2,7 +2,6 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -38,20 +37,17 @@ func GetConfig(configPath string) Config {
|
|||||||
// returns if a device pcie bus id is a super device or subsystem device
|
// returns if a device pcie bus id is a super device or subsystem device
|
||||||
//
|
//
|
||||||
// subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy
|
// subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy
|
||||||
|
//
|
||||||
|
// returns true if BusID has format xxxx:yy
|
||||||
func DeviceBusIDIsSuperDevice(BusID string) bool {
|
func DeviceBusIDIsSuperDevice(BusID string) bool {
|
||||||
return !strings.ContainsRune(BusID, '.')
|
return !strings.ContainsRune(BusID, '.')
|
||||||
}
|
}
|
||||||
|
|
||||||
// splits a device pcie bus id into super device and subsystem device IDs if possible
|
// returns if a device pcie bus id is a subdevice of specified super device
|
||||||
func SplitDeviceBusID(BusID string) (string, string, error) {
|
//
|
||||||
if DeviceBusIDIsSuperDevice(BusID) {
|
// subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy
|
||||||
return BusID, "", nil
|
//
|
||||||
} else {
|
// returns true if BusID has prefix SuperDeviceBusID and SuperDeviceBusID is a Super Device
|
||||||
x := strings.Split(BusID, ".")
|
func DeviceBusIDIsSubDevice(BusID string, SuperDeviceBusID string) bool {
|
||||||
if len(x) != 2 {
|
return DeviceBusIDIsSuperDevice(SuperDeviceBusID) && strings.HasPrefix(BusID, SuperDeviceBusID)
|
||||||
return "", "", fmt.Errorf("BusID: %s contained more than one '.'", BusID)
|
|
||||||
} else {
|
|
||||||
return x[0], x[1], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
26
go.mod
26
go.mod
@ -8,11 +8,37 @@ require github.com/luthermonson/go-proxmox v0.2.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/buger/goterm v1.0.4 // indirect
|
github.com/buger/goterm v1.0.4 // indirect
|
||||||
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
github.com/diskfs/go-diskfs v1.4.2 // indirect
|
github.com/diskfs/go-diskfs v1.4.2 // indirect
|
||||||
github.com/djherbis/times v1.6.0 // indirect
|
github.com/djherbis/times v1.6.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/gin-gonic/gin v1.10.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/jinzhu/copier v0.4.0 // indirect
|
github.com/jinzhu/copier v0.4.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/magefile/mage v1.15.0 // indirect
|
github.com/magefile/mage v1.15.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/stretchr/testify v1.9.0 // indirect
|
github.com/stretchr/testify v1.9.0 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
|
golang.org/x/crypto v0.23.0 // indirect
|
||||||
|
golang.org/x/net v0.25.0 // indirect
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
|
golang.org/x/text v0.15.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user