mirror of
https://github.com/MengMengCode/CLICD.git
synced 2026-08-05 05:36:07 +08:00
152 lines
4.0 KiB
Go
152 lines
4.0 KiB
Go
package api
|
|
|
|
import (
|
|
"net/http"
|
|
"sort"
|
|
"strconv"
|
|
|
|
"clicd/internal/config"
|
|
"clicd/internal/lxc"
|
|
)
|
|
|
|
type routeCapacity struct {
|
|
Used int `json:"used"`
|
|
Remaining string `json:"remaining"`
|
|
Total string `json:"total"`
|
|
}
|
|
|
|
type nat4Route struct {
|
|
ContainerID int `json:"container_id"`
|
|
ContainerName string `json:"container_name"`
|
|
LXCName string `json:"lxc_name"`
|
|
Status string `json:"status"`
|
|
IP string `json:"ip"`
|
|
HostPort int `json:"host_port"`
|
|
ContainerPort int `json:"container_port"`
|
|
Protocol string `json:"protocol"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
type ipv6Route struct {
|
|
ContainerID int `json:"container_id"`
|
|
ContainerName string `json:"container_name"`
|
|
LXCName string `json:"lxc_name"`
|
|
Status string `json:"status"`
|
|
Address string `json:"address"`
|
|
PrefixLen int `json:"prefix_len"`
|
|
Interface string `json:"interface"`
|
|
}
|
|
|
|
type routingResponse struct {
|
|
NAT4 routeCapacity `json:"nat4"`
|
|
IPv6 routeCapacity `json:"ipv6"`
|
|
NAT4Mappings []nat4Route `json:"nat4_mappings"`
|
|
IPv6Assignments []ipv6Route `json:"ipv6_assignments"`
|
|
IPv6Prefixes []lxc.IPv6PrefixInfo `json:"ipv6_prefixes"`
|
|
}
|
|
|
|
func HandleRouting(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
jsonResponse(w, http.StatusMethodNotAllowed, APIResponse{Success: false, Message: "Method not allowed"})
|
|
return
|
|
}
|
|
|
|
nat4Mappings := make([]nat4Route, 0)
|
|
usedPorts := map[int]bool{}
|
|
ipv6Assignments := make([]ipv6Route, 0)
|
|
|
|
const nat4StartPort = 20000
|
|
const nat4EndPort = 65535
|
|
|
|
for _, c := range config.AppConfig.Containers {
|
|
for _, pm := range c.PortMappings {
|
|
if pm.HostPort >= nat4StartPort && pm.HostPort <= nat4EndPort {
|
|
usedPorts[pm.HostPort] = true
|
|
}
|
|
nat4Mappings = append(nat4Mappings, nat4Route{
|
|
ContainerID: c.ID,
|
|
ContainerName: c.Name,
|
|
LXCName: c.LxcName(),
|
|
Status: c.Status,
|
|
IP: c.IP,
|
|
HostPort: pm.HostPort,
|
|
ContainerPort: pm.ContainerPort,
|
|
Protocol: pm.Protocol,
|
|
Description: pm.Description,
|
|
})
|
|
}
|
|
if c.IPv6 != "" {
|
|
ipv6Assignments = append(ipv6Assignments, ipv6Route{
|
|
ContainerID: c.ID,
|
|
ContainerName: c.Name,
|
|
LXCName: c.LxcName(),
|
|
Status: c.Status,
|
|
Address: c.IPv6,
|
|
PrefixLen: c.IPv6PrefixLen,
|
|
Interface: c.IPv6Interface,
|
|
})
|
|
}
|
|
}
|
|
sort.SliceStable(nat4Mappings, func(i, j int) bool {
|
|
if nat4Mappings[i].HostPort == nat4Mappings[j].HostPort {
|
|
return nat4Mappings[i].ContainerName < nat4Mappings[j].ContainerName
|
|
}
|
|
return nat4Mappings[i].HostPort < nat4Mappings[j].HostPort
|
|
})
|
|
sort.SliceStable(ipv6Assignments, func(i, j int) bool {
|
|
return ipv6Assignments[i].Address < ipv6Assignments[j].Address
|
|
})
|
|
|
|
const totalNAT4Ports = nat4EndPort - nat4StartPort + 1
|
|
nat4Used := len(usedPorts)
|
|
nat4Remaining := totalNAT4Ports - nat4Used
|
|
if nat4Remaining < 0 {
|
|
nat4Remaining = 0
|
|
}
|
|
|
|
prefixes := lxc.DetectPublicIPv6Prefixes()
|
|
ipv6Total := "0"
|
|
ipv6Remaining := "0"
|
|
if len(prefixes) > 0 {
|
|
ipv6Total = lxc.IPv6PrefixCapacity(prefixes[0].PrefixLen)
|
|
ipv6Remaining = subtractCapacity(ipv6Total, len(ipv6Assignments))
|
|
}
|
|
|
|
jsonResponse(w, http.StatusOK, APIResponse{
|
|
Success: true,
|
|
Data: routingResponse{
|
|
NAT4: routeCapacity{
|
|
Used: nat4Used,
|
|
Remaining: strconv.Itoa(nat4Remaining),
|
|
Total: strconv.Itoa(totalNAT4Ports),
|
|
},
|
|
IPv6: routeCapacity{
|
|
Used: len(ipv6Assignments),
|
|
Remaining: ipv6Remaining,
|
|
Total: ipv6Total,
|
|
},
|
|
NAT4Mappings: nat4Mappings,
|
|
IPv6Assignments: ipv6Assignments,
|
|
IPv6Prefixes: prefixes,
|
|
},
|
|
})
|
|
}
|
|
|
|
func subtractCapacity(total string, used int) string {
|
|
if total == "" || total == "0" {
|
|
return "0"
|
|
}
|
|
if total == "large" {
|
|
return "large"
|
|
}
|
|
parsed, err := strconv.ParseInt(total, 10, 64)
|
|
if err != nil {
|
|
return total
|
|
}
|
|
remaining := parsed - int64(used)
|
|
if remaining < 0 {
|
|
remaining = 0
|
|
}
|
|
return strconv.FormatInt(remaining, 10)
|
|
}
|