Merge branch 'main-v2' into lite
This commit is contained in:
@@ -10,8 +10,6 @@ import (
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
libConfig "be.ems/lib/config"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -21,11 +19,10 @@ var (
|
||||
)
|
||||
|
||||
// 程序配置
|
||||
var conf *viper.Viper
|
||||
var conf *viper.Viper = viper.New()
|
||||
|
||||
// 初始化程序配置
|
||||
func InitConfig(configDir *embed.FS) {
|
||||
conf = viper.New()
|
||||
initFlag()
|
||||
initViper(configDir)
|
||||
}
|
||||
@@ -97,16 +94,14 @@ func initViper(configDir *embed.FS) {
|
||||
// 外部文件配置
|
||||
externalConfig := conf.GetString("config")
|
||||
if externalConfig != "" {
|
||||
// readExternalConfig(externalConfig)
|
||||
// 处理旧配置,存在相同的配置项处理
|
||||
configInMerge(externalConfig)
|
||||
readExternalConfig(externalConfig)
|
||||
}
|
||||
|
||||
// 记录程序开始运行的时间点
|
||||
conf.Set("runTime", time.Now())
|
||||
}
|
||||
|
||||
// readExternalConfig 读取外部文件配置(放弃旧的配置序列化时候才用)
|
||||
// readExternalConfig 读取外部文件配置
|
||||
func readExternalConfig(configPaht string) {
|
||||
f, err := os.Open(configPaht)
|
||||
if err != nil {
|
||||
@@ -121,38 +116,6 @@ func readExternalConfig(configPaht string) {
|
||||
}
|
||||
}
|
||||
|
||||
// 配置文件读取进行内部参数合并
|
||||
func configInMerge(configFile string) {
|
||||
// 指定配置文件读取序列化
|
||||
libConfig.ReadConfig(configFile)
|
||||
uriPrefix := libConfig.GetYamlConfig().OMC.UriPrefix
|
||||
if uriPrefix != "" {
|
||||
libConfig.UriPrefix = uriPrefix
|
||||
}
|
||||
if libConfig.GetYamlConfig().TestConfig.Enabled {
|
||||
libConfig.ReadTestConfigYaml(libConfig.GetYamlConfig().TestConfig.File)
|
||||
}
|
||||
|
||||
// 配置文件读取
|
||||
var v = viper.New()
|
||||
// 设置配置文件路径
|
||||
v.SetConfigFile(configFile)
|
||||
v.SetConfigType("yaml")
|
||||
// 读取配置文件
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
fmt.Printf("failure to read configuration file: %v \n", err)
|
||||
return
|
||||
}
|
||||
// 合并外层lib和features使用配置
|
||||
for key, value := range v.AllSettings() {
|
||||
// 跳过配置
|
||||
if key == "testconfig" || key == "logger" {
|
||||
continue
|
||||
}
|
||||
conf.Set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// Env 获取运行服务环境
|
||||
// local prod
|
||||
func Env() string {
|
||||
|
||||
30
src/framework/config/expand.go
Normal file
30
src/framework/config/expand.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// SedReplace 替换文件内容,文件来自外部文件配置config传入
|
||||
//
|
||||
// sed 's/port: [0-9]\+ # trace port/port: 6964 # trace port/' /usr/local/etc/omc/omc.yaml
|
||||
func SedReplace(pattern, replacement string) error {
|
||||
// 外部文件配置
|
||||
externalConfig := conf.GetString("config")
|
||||
if externalConfig == "" {
|
||||
return fmt.Errorf("config file path not found")
|
||||
}
|
||||
// 读取文件内容
|
||||
data, err := os.ReadFile(externalConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 定义正则表达式
|
||||
re := regexp.MustCompile(pattern)
|
||||
// 使用正则替换,将匹配到的部分替换为新的内容
|
||||
replacedData := re.ReplaceAll(data, []byte(replacement))
|
||||
// 写回文件
|
||||
return os.WriteFile(externalConfig, replacedData, 0644)
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
package constants
|
||||
|
||||
// 告警 alarmCode 常量
|
||||
const (
|
||||
// ALARM_EVENT_REBOOT 事件-网元重启
|
||||
ALARM_EVENT_REBOOT = 9000
|
||||
// ALARM_STATE_CHECK 告警-状态检查
|
||||
ALARM_STATE_CHECK = 10000
|
||||
// ALARM_RAM_CPU_CHECK 告警-内存/CPU/磁盘检查
|
||||
ALARM_CMD_CHECK = 10001
|
||||
// ALARM_LICENSE_CHECK 告警-网元License到期检查
|
||||
ALARM_LICENSE_CHECK = 10002
|
||||
ALARM_EVENT_REBOOT = 9000 // 告警Code-事件-网元重启
|
||||
ALARM_STATE_CHECK = 10000 // 告警Code-状态检查
|
||||
ALARM_CMD_CHECK = 10001 // 告警Code-内存/CPU/磁盘检查
|
||||
ALARM_LICENSE_CHECK = 10002 // 告警Code-网元License到期检查
|
||||
)
|
||||
|
||||
const (
|
||||
ALARM_ACK_STATE_NOT_ACK = "NotAck" // 告警确认状态-未确认
|
||||
ALARM_ACK_STATE_ACK = "Ack" // 告警确认状态-已确认
|
||||
)
|
||||
|
||||
const (
|
||||
ALARM_CLEAR_TYPE_NOT_CLEAR = "NotClear" // 告警清除状态-未清除
|
||||
ALARM_CLEAR_TYPE_AUTO_CLEAR = "AutoClear" // 告警清除状态-自动清除
|
||||
ALARM_CLEAR_TYPE_MANUAL_CLEAR = "ManualClear" // 告警清除状态-手动清除
|
||||
)
|
||||
|
||||
@@ -103,6 +103,10 @@ func processSQLFile(db *gorm.DB, filePath string) {
|
||||
} else if strings.Contains(errorStr, "duplicate key") {
|
||||
// 忽略重复索引错误
|
||||
// Error 1061 (42000): Duplicate key name 'key_name'
|
||||
} else if strings.Contains(errorStr, "duplicate entry") {
|
||||
// 忽略重复记录错误
|
||||
// Error 1062 (23000): Duplicate entry 'value' for key 'key_name'
|
||||
log.Println(err.Error())
|
||||
} else if strings.Contains(errorStr, "unknown column") {
|
||||
// 忽略未知字段错误
|
||||
// Error 1054 (42S22): Unknown column 'field_name' in 'table'
|
||||
@@ -110,6 +114,10 @@ func processSQLFile(db *gorm.DB, filePath string) {
|
||||
// 忽略删除字段或索引错误
|
||||
// Error 1091 (42000): Can't DROP COLUMN `field_name`; check that it exists
|
||||
// Error 1091 (42000): Can't DROP 'idx_ne_type_id'; check that column/key exists
|
||||
} else if strings.Contains(errorStr, "doesn't match") {
|
||||
// 忽略列数不匹配错误
|
||||
// Error 1136 (21S01): Column count doesn't match value count at row 1
|
||||
log.Println(err.Error())
|
||||
} else {
|
||||
// 其他错误终止程序
|
||||
log.Fatalln(errorStr)
|
||||
|
||||
@@ -2,7 +2,6 @@ package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -134,8 +133,15 @@ func OperateLog(options Options) gin.HandlerFunc {
|
||||
contentDisposition := c.Writer.Header().Get("Content-Disposition")
|
||||
contentType := c.Writer.Header().Get("Content-Type")
|
||||
content := contentType + contentDisposition
|
||||
msg := fmt.Sprintf(`{"status":"%d","size":%d,"content-type":"%s"}`, status, c.Writer.Size(), content)
|
||||
operaLog.OperaMsg = msg
|
||||
msgByte, err := json.Marshal(map[string]any{
|
||||
"status": status,
|
||||
"size": c.Writer.Size(),
|
||||
"content-type": content,
|
||||
})
|
||||
if err != nil {
|
||||
operaLog.OperaMsg = ""
|
||||
}
|
||||
operaLog.OperaMsg = string(msgByte)
|
||||
}
|
||||
|
||||
// 日志记录时间
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConnTCP 连接TCP客户端
|
||||
type ConnTCP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
|
||||
DialTimeOut time.Duration `json:"dialTimeOut"` // 连接超时断开
|
||||
|
||||
Client *net.Conn `json:"client"`
|
||||
LastResult string `json:"lastResult"` // 记最后一次发送消息的结果
|
||||
}
|
||||
|
||||
// New 创建TCP客户端
|
||||
func (c *ConnTCP) New() (*ConnTCP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "tcp"
|
||||
if strings.Contains(c.Addr, ":") {
|
||||
proto = "tcp6"
|
||||
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
||||
}
|
||||
address := net.JoinHostPort(c.Addr, fmt.Sprint(c.Port))
|
||||
|
||||
// 默认等待5s
|
||||
if c.DialTimeOut == 0 {
|
||||
c.DialTimeOut = 5 * time.Second
|
||||
}
|
||||
|
||||
// 连接到服务端
|
||||
client, err := net.DialTimeout(proto, address, c.DialTimeOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Client = &client
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close 关闭当前TCP客户端
|
||||
func (c *ConnTCP) Close() {
|
||||
if c.Client != nil {
|
||||
(*c.Client).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Send 发送消息
|
||||
func (c *ConnTCP) Send(msg []byte, timer time.Duration) (string, error) {
|
||||
if c.Client == nil {
|
||||
return "", fmt.Errorf("tcp client not connected")
|
||||
}
|
||||
conn := *c.Client
|
||||
|
||||
// 写入信息
|
||||
if len(msg) > 0 {
|
||||
if _, err := conn.Write(msg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
defer buf.Reset()
|
||||
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-time.After(timer):
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, fmt.Errorf("timeout")
|
||||
default:
|
||||
// 读取命令消息
|
||||
n, err := conn.Read(tmp)
|
||||
if n == 0 || err != nil {
|
||||
tmp = nil
|
||||
break
|
||||
}
|
||||
|
||||
tmpStr := string(tmp[:n])
|
||||
buf.WriteString(tmpStr)
|
||||
|
||||
// 是否有终止符
|
||||
if strings.HasSuffix(tmpStr, ">") || strings.HasSuffix(tmpStr, "> ") || strings.HasSuffix(tmpStr, "# ") {
|
||||
tmp = nil
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"be.ems/src/framework/logger"
|
||||
)
|
||||
|
||||
// SocketTCP TCP服务端
|
||||
type SocketTCP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
Listener *net.TCPListener `json:"listener"`
|
||||
StopChan chan struct{} `json:"stop"` // 停止信号
|
||||
}
|
||||
|
||||
// New 创建TCP服务端
|
||||
func (s *SocketTCP) New() (*SocketTCP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "tcp"
|
||||
if strings.Contains(s.Addr, ":") {
|
||||
proto = "tcp6"
|
||||
s.Addr = fmt.Sprintf("[%s]", s.Addr)
|
||||
}
|
||||
address := fmt.Sprintf("%s:%d", s.Addr, s.Port)
|
||||
|
||||
// 解析 TCP 地址
|
||||
tcpAddr, err := net.ResolveTCPAddr(proto, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 监听 TCP 地址
|
||||
listener, err := net.ListenTCP(proto, tcpAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Listener = listener
|
||||
s.StopChan = make(chan struct{}, 1)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Close 关闭当前TCP服务端
|
||||
func (s *SocketTCP) Close() {
|
||||
if s.Listener != nil {
|
||||
s.StopChan <- struct{}{}
|
||||
(*s.Listener).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve 处理消息
|
||||
func (s *SocketTCP) Resolve(callback func(conn *net.Conn, err error)) {
|
||||
if s.Listener == nil {
|
||||
callback(nil, fmt.Errorf("tcp service not created"))
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
callback(nil, fmt.Errorf("tcp service panic err"))
|
||||
}
|
||||
}()
|
||||
|
||||
listener := *s.Listener
|
||||
for {
|
||||
select {
|
||||
case <-s.StopChan:
|
||||
callback(nil, fmt.Errorf("udp service stop"))
|
||||
return
|
||||
default:
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
logger.Errorf("Error accepting connection: %v ", err)
|
||||
continue
|
||||
}
|
||||
defer conn.Close()
|
||||
callback(&conn, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ConnUDP 连接UDP客户端
|
||||
type ConnUDP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
|
||||
DialTimeOut time.Duration `json:"dialTimeOut"` // 连接超时断开
|
||||
|
||||
Client *net.Conn `json:"client"`
|
||||
LastResult string `json:"lastResult"` // 记最后一次发送消息的结果
|
||||
}
|
||||
|
||||
// New 创建UDP客户端
|
||||
func (c *ConnUDP) New() (*ConnUDP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "udp"
|
||||
if strings.Contains(c.Addr, ":") {
|
||||
proto = "udp6"
|
||||
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
||||
}
|
||||
address := net.JoinHostPort(c.Addr, fmt.Sprint(c.Port))
|
||||
|
||||
// 默认等待5s
|
||||
if c.DialTimeOut == 0 {
|
||||
c.DialTimeOut = 5 * time.Second
|
||||
}
|
||||
|
||||
// 连接到服务端
|
||||
client, err := net.DialTimeout(proto, address, c.DialTimeOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.Client = &client
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Close 关闭当前UDP客户端
|
||||
func (c *ConnUDP) Close() {
|
||||
if c.Client != nil {
|
||||
(*c.Client).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Send 发送消息
|
||||
func (c *ConnUDP) Send(msg []byte, ms int) (string, error) {
|
||||
if c.Client == nil {
|
||||
return "", fmt.Errorf("udp client not connected")
|
||||
}
|
||||
conn := *c.Client
|
||||
|
||||
// 写入信息
|
||||
if len(msg) > 0 {
|
||||
if _, err := conn.Write(msg); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
defer buf.Reset()
|
||||
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Duration(time.Duration(ms).Milliseconds())):
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, fmt.Errorf("timeout")
|
||||
default:
|
||||
// 读取命令消息
|
||||
n, err := conn.Read(tmp)
|
||||
if n == 0 || err != nil {
|
||||
tmp = nil
|
||||
break
|
||||
}
|
||||
|
||||
tmpStr := string(tmp[:n])
|
||||
buf.WriteString(tmpStr)
|
||||
|
||||
// 是否有终止符
|
||||
if strings.HasSuffix(tmpStr, ">") || strings.HasSuffix(tmpStr, "> ") || strings.HasSuffix(tmpStr, "# ") {
|
||||
tmp = nil
|
||||
c.LastResult = buf.String()
|
||||
return c.LastResult, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package socket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SocketUDP UDP服务端
|
||||
type SocketUDP struct {
|
||||
Addr string `json:"addr"` // 主机地址
|
||||
Port int64 `json:"port"` // 端口
|
||||
Conn *net.UDPConn `json:"conn"`
|
||||
StopChan chan struct{} `json:"stop"` // 停止信号
|
||||
}
|
||||
|
||||
// New 创建UDP服务端
|
||||
func (s *SocketUDP) New() (*SocketUDP, error) {
|
||||
// IPV6地址协议
|
||||
proto := "udp"
|
||||
if strings.Contains(s.Addr, ":") {
|
||||
proto = "udp6"
|
||||
s.Addr = fmt.Sprintf("[%s]", s.Addr)
|
||||
}
|
||||
address := fmt.Sprintf("%s:%d", s.Addr, s.Port)
|
||||
|
||||
// 解析 UDP 地址
|
||||
udpAddr, err := net.ResolveUDPAddr(proto, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 监听 UDP 地址
|
||||
conn, err := net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Conn = conn
|
||||
s.StopChan = make(chan struct{}, 1)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// CloseService 关闭当前UDP服务端
|
||||
func (s *SocketUDP) Close() {
|
||||
if s.Conn != nil {
|
||||
s.StopChan <- struct{}{}
|
||||
(*s.Conn).Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve 处理消息
|
||||
func (s *SocketUDP) Resolve(callback func(*net.UDPConn, error)) {
|
||||
if s.Conn == nil {
|
||||
callback(nil, fmt.Errorf("udp service not created"))
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
callback(nil, fmt.Errorf("udp service panic err"))
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-s.StopChan:
|
||||
callback(nil, fmt.Errorf("udp service not created"))
|
||||
return
|
||||
default:
|
||||
callback(s.Conn, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,14 @@ func (c *ConnTelnet) NewClient() (*ConnTelnet, error) {
|
||||
}
|
||||
|
||||
// 进行登录
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.User + "\r\n"))
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.Password + "\r\n"))
|
||||
if c.User != "" {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.User + "\r\n"))
|
||||
}
|
||||
if c.Password != "" {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
client.Write([]byte(c.Password + "\r\n"))
|
||||
}
|
||||
// fmt.Fprintln(client, c.User)
|
||||
// fmt.Fprintln(client, c.Password)
|
||||
|
||||
@@ -103,6 +107,19 @@ func (c *ConnTelnet) RunCMD(cmd string) (string, error) {
|
||||
return c.LastResult, nil
|
||||
}
|
||||
|
||||
// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
|
||||
func (s *ConnTelnet) WindowChange(h, w int) error {
|
||||
if s.Client == nil {
|
||||
return fmt.Errorf("client is nil to content write failed")
|
||||
}
|
||||
conn := *s.Client
|
||||
|
||||
// 需要确保接收方理解并正确处理发送窗口大小设置命令
|
||||
conn.Write([]byte{255, 251, 31})
|
||||
conn.Write([]byte{255, 250, 31, byte(w >> 8), byte(w & 0xFF), byte(h >> 8), byte(h & 0xFF), 255, 240})
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewClient 创建Telnet客户端会话对象
|
||||
func (c *ConnTelnet) NewClientSession(cols, rows int) (*TelnetClientSession, error) {
|
||||
if c.Client == nil {
|
||||
|
||||
@@ -54,9 +54,9 @@ func ParseDateToStr(date any, formatStr string) string {
|
||||
if v == 0 {
|
||||
return ""
|
||||
}
|
||||
if v > 9999999999 {
|
||||
if v > 1e12 {
|
||||
t = time.UnixMilli(v)
|
||||
} else if v > 999999999 {
|
||||
} else if v > 1e9 {
|
||||
t = time.Unix(v, 0)
|
||||
} else {
|
||||
logger.Infof("utils ParseDateToStr err %v", "Invalid timestamp")
|
||||
|
||||
44
src/framework/utils/expr/expr.go
Normal file
44
src/framework/utils/expr/expr.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/expr-lang/expr"
|
||||
)
|
||||
|
||||
// Eval 计算表达式返回结果
|
||||
func Eval(exprStr string, env map[string]any) (any, error) {
|
||||
return expr.Eval(exprStr, env)
|
||||
}
|
||||
|
||||
// ParseExprEnv 解析表达式环境变量
|
||||
// 比如 "('SMF.03'/'SMF.04')*100"
|
||||
// 变量传入"SMF.03": 3
|
||||
func ParseExprEnv(exprStr string, env map[string]any) (string, map[string]any) {
|
||||
// 使用正则表达式匹配带单引号的变量名
|
||||
re := regexp.MustCompile(`'([^']+)'`)
|
||||
tempEnv := make(map[string]any)
|
||||
tempExpr := exprStr
|
||||
varCount := 0
|
||||
matches := re.FindAllStringSubmatch(exprStr, -1)
|
||||
for _, match := range matches {
|
||||
paramName := match[1]
|
||||
tempVarName := fmt.Sprintf("var%d", varCount)
|
||||
tempEnv[tempVarName] = env[paramName]
|
||||
tempExpr = strings.Replace(tempExpr, match[0], tempVarName, 1)
|
||||
varCount++
|
||||
}
|
||||
|
||||
// 合并临时环境变量和原环境变量
|
||||
combinedEnv := make(map[string]any)
|
||||
for k, v := range env {
|
||||
combinedEnv[k] = v
|
||||
}
|
||||
for k, v := range tempEnv {
|
||||
combinedEnv[k] = v
|
||||
}
|
||||
|
||||
return tempExpr, combinedEnv
|
||||
}
|
||||
@@ -19,7 +19,7 @@ func ValidUsername(username string) bool {
|
||||
if username == "" {
|
||||
return false
|
||||
}
|
||||
pattern := `^[a-zA-Z][a-z0-9A-Z]{5,}`
|
||||
pattern := `^.{4,}$` //`^[a-zA-Z][a-z0-9A-Z]{5,}`
|
||||
match, err := regexp.MatchString(pattern, username)
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user