Merge Go frontend (apiserver + xcecli) into meson build

This commit is contained in:
Rongsong Shen 2026-04-14 11:20:17 +08:00
parent 43dc12a36c
commit c9dc8c4676
205 changed files with 30793 additions and 328 deletions

View file

@ -0,0 +1,287 @@
package utils
import (
"errors"
"fmt"
"os"
"os/exec"
"sort"
"strconv"
"strings"
"time"
logger "xcecli/config"
"go.uber.org/zap"
)
// ParseInt parses a string to an integer
func ParseInt(s string) (int, error) {
return strconv.Atoi(s)
}
// ParseTim parse time string
// support input format:
// - "15:04" - only hour and minute, use current year, month and day
// - "01-02 15:04" - month and day with hour and minute, use current year
// - "03 15:04" - day with hour and minute, use current year and month
// - "2006-01-02 15:04" - full year, month and day with hour and minute
// output format: "2006-01-02 15:04"
func ParseTime(timeStr string) (string, error) {
// standard output format
outputFormat := "2006-01-02 15:04 CST"
// try formats
formats := []string{
"2006-01-02 15:04:05", // full format, strictest
"2006-01-02 15:04", // full format, strictest
"01-02 15:04", // month and day with hour and minute, use current year
"02 15:04", // day with hour and minute, use current year and month
"15:04", // only hour and minute, use current year, month and day
}
// get current time, for filling missing fields
now := time.Now()
// try each format
for _, format := range formats {
parsedTime, err := time.Parse(format, timeStr)
if err == nil {
// parse successfully, fill missing fields according to the format
resultTime := time.Date(
now.Year(),
now.Month(),
now.Day(),
parsedTime.Hour(),
parsedTime.Minute(),
0, 0, time.Local,
)
// adjust year, month and day according to the format
switch format {
case "2006-01-02 15:04:05":
// full format, use parsed year, month and day
resultTime = time.Date(
parsedTime.Year(),
parsedTime.Month(),
parsedTime.Day(),
parsedTime.Hour(),
parsedTime.Minute(),
parsedTime.Second(), 0, time.Local,
)
case "2006-01-02 15:04":
// full format, use parsed year, month and day
resultTime = time.Date(
parsedTime.Year(),
parsedTime.Month(),
parsedTime.Day(),
parsedTime.Hour(),
parsedTime.Minute(),
0, 0, time.Local,
)
case "01-02 15:04":
// month and day with hour and minute format, use current year and parsed month and day
resultTime = time.Date(
now.Year(),
parsedTime.Month(),
parsedTime.Day(),
parsedTime.Hour(),
parsedTime.Minute(),
0, 0, time.Local,
)
case "02 15:04":
// day with hour and minute format, use current year and month and parsed day
resultTime = time.Date(
now.Year(),
now.Month(),
parsedTime.Day(),
parsedTime.Hour(),
parsedTime.Minute(),
0, 0, time.Local,
)
case "15:04":
// hour and minute format, use current year, month and day
// already set, no need to change
}
// return standard format time string
return resultTime.Format(outputFormat), nil
}
}
// all formats failed
//return "", fmt.Errorf("invalid time format. Expected formats: HH:MM, DD HH:MM, MM-DD HH:MM, or YYYY-MM-DD HH:MM")
return "", errors.New("the time format can be [HH:MM, DD HH:MM, MM-DD HH:MM, YYYY-MM-DD HH:MM]")
}
// SystemLimits
type SystemLimits struct {
CPULimit int // CPU time limit (seconds)
FileLimit int // file descriptor limit
DataLimit int // data segment limit
StackLimit int // stack size limit
CoreLimit int // core file size limit
ProcessLimit int // process limit
ThreadLimit int // thread limit
MemLimit int // virtual memory limit
SwapLimit int // swap limit
}
// NewSystemLimits create a new SystemLimits instance
func NewSystemLimits() *SystemLimits {
return &SystemLimits{}
}
// define the command mapping
var limitCommands = map[string]string{
"cpu_limit": "ulimit -t",
"file_limit": "ulimit -n",
"data_limit": "ulimit -d",
"stack_limit": "ulimit -s",
"core_limit": "ulimit -c",
"process_limit": "ulimit -u",
"thread_limit": "cat /proc/sys/vm/max_map_count",
"mem_limit": "ulimit -v",
"swap_limit": "ulimit -l",
}
// getLimitValue get the value of the specified limit
func getLimitValue(key string) (int, error) {
cmd, ok := limitCommands[key]
if !ok {
return 0, nil
}
output, err := exec.Command("sh", "-c", cmd).Output()
fmt.Println("getLimitValue", key, string(output))
logger.Debug("getLimitValue", zap.String("key", key), zap.String("output", string(output)))
if err != nil {
return 0, err
}
value := strings.TrimSpace(string(output))
if value == "unlimited" {
return 0, nil
}
return strconv.Atoi(value)
}
// GetCPULimit get the CPU time limit
func (sl *SystemLimits) GetCPULimit() (int, error) {
if sl.CPULimit == 0 {
val, err := getLimitValue("cpu_limit")
if err != nil {
return 0, err
}
sl.CPULimit = val
}
return sl.CPULimit, nil
}
// GetFileLimit get the file descriptor limit
func (sl *SystemLimits) GetFileLimit() (int, error) {
if sl.FileLimit == 0 {
val, err := getLimitValue("file_limit")
if err != nil {
return 0, err
}
sl.FileLimit = val
}
return sl.FileLimit, nil
}
// GetDataLimit get the data segment limit
func (sl *SystemLimits) GetDataLimit() (int, error) {
if sl.DataLimit == 0 {
val, err := getLimitValue("data_limit")
if err != nil {
return 0, err
}
sl.DataLimit = val
}
return sl.DataLimit, nil
}
// GetStackLimit get the stack size limit
func (sl *SystemLimits) GetStackLimit() (int, error) {
if sl.StackLimit == 0 {
val, err := getLimitValue("stack_limit")
if err != nil {
return 0, err
}
sl.StackLimit = val
}
return sl.StackLimit, nil
}
// GetCoreLimit get the core file size limit
func (sl *SystemLimits) GetCoreLimit() (int, error) {
if sl.CoreLimit == 0 {
val, err := getLimitValue("core_limit")
if err != nil {
return 0, err
}
sl.CoreLimit = val
}
return sl.CoreLimit, nil
}
// GetProcessLimit get the process limit
func (sl *SystemLimits) GetProcessLimit() (int, error) {
if sl.ProcessLimit == 0 {
val, err := getLimitValue("process_limit")
if err != nil {
return 0, err
}
sl.ProcessLimit = val
}
return sl.ProcessLimit, nil
}
// GetThreadLimit get the thread limit
func (sl *SystemLimits) GetThreadLimit() (int, error) {
if sl.ThreadLimit == 0 {
val, err := getLimitValue("thread_limit")
if err != nil {
return 0, err
}
sl.ThreadLimit = val
}
return sl.ThreadLimit, nil
}
// GetMemLimit get the virtual memory limit
func (sl *SystemLimits) GetMemLimit() (int, error) {
if sl.MemLimit == 0 {
val, err := getLimitValue("mem_limit")
if err != nil {
return 0, err
}
sl.MemLimit = val
}
return sl.MemLimit, nil
}
// GetSwapLimit get the swap limit
func (sl *SystemLimits) GetSwapLimit() (int, error) {
if sl.SwapLimit == 0 {
val, err := getLimitValue("swap_limit")
if err != nil {
return 0, err
}
sl.SwapLimit = val
}
return sl.SwapLimit, nil
}
// GetSystemEnv get the system environment variables
// return format: ["VAR1=value1", "VAR2=value2", ...]
func GetSystemEnv() []string {
// get all environment variables
envVars := os.Environ()
// sort the environment variables to ensure the consistency of the output
sort.Strings(envVars)
return envVars
}