api/internal/utils/utils.go (168 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package utils
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net"
"os"
"sort"
"strconv"
"strings"
"github.com/sony/sonyflake"
"github.com/yuin/gopher-lua/parse"
)
var _sf *sonyflake.Sonyflake
func init() {
saltStr, ok := os.LookupEnv("FLAKE_SALT")
var salt uint16
if ok {
i, err := strconv.ParseUint(saltStr, 10, 16)
if err != nil {
panic(err)
}
salt = uint16(i)
}
ips, err := getLocalIPs()
if err != nil {
panic(err)
}
_sf = sonyflake.NewSonyflake(sonyflake.Settings{
MachineID: func() (u uint16, e error) {
return sumIPs(ips) + salt, nil
},
})
if _sf == nil {
panic("sonyflake init failed")
}
}
func sumIPs(ips []net.IP) uint16 {
total := 0
for _, ip := range ips {
for i := range ip {
total += int(ip[i])
}
}
return uint16(total)
}
func getLocalIPs() ([]net.IP, error) {
var ips []net.IP
addrs, err := net.InterfaceAddrs()
if err != nil {
return ips, err
}
for _, a := range addrs {
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() && ipNet.IP.To4() != nil {
ips = append(ips, ipNet.IP)
}
}
return ips, nil
}
func GetFlakeUid() uint64 {
uid, err := _sf.NextID()
if err != nil {
panic("get sony flake uid failed:" + err.Error())
}
return uid
}
func GetFlakeUidStr() string {
return strconv.FormatUint(GetFlakeUid(), 10)
}
func InterfaceToString(val interface{}) string {
if val == nil {
return ""
}
str := fmt.Sprintf("%v", val)
return str
}
// Note: json.Marshal and json.Unmarshal may cause the precision loss
func ObjectClone(origin, copy interface{}) error {
byt, err := json.Marshal(origin)
if err != nil {
return err
}
err = json.Unmarshal(byt, copy)
return err
}
func GenLabelMap(label string) (map[string]struct{}, error) {
var err = errors.New("malformed label")
mp := make(map[string]struct{})
if label == "" {
return mp, nil
}
labels := strings.Split(label, ",")
for _, l := range labels {
kv := strings.Split(l, ":")
if len(kv) == 2 {
if kv[0] == "" || kv[1] == "" {
return nil, err
}
// Because the labels may contain the same key, like this: label=version:v1,version:v2
// we need to combine them as a map's key
mp[l] = struct{}{}
} else if len(kv) == 1 {
if kv[0] == "" {
return nil, err
}
mp[kv[0]] = struct{}{}
} else {
return nil, err
}
}
return mp, nil
}
func LabelContains(labels map[string]string, reqLabels map[string]struct{}) bool {
if len(reqLabels) == 0 {
return true
}
for k, v := range labels {
// first check the key
if _, exist := reqLabels[k]; exist {
return true
}
// second check the key:value
if _, exist := reqLabels[k+":"+v]; exist {
return true
}
}
return false
}
// ValidateLuaCode validates lua syntax for input code, return nil
// if passed, otherwise a non-nil error will be returned
func ValidateLuaCode(code string) error {
_, err := parse.Parse(strings.NewReader(code), "<string>")
return err
}
func StringSliceContains(a, b []string) bool {
if (a == nil) != (b == nil) {
return false
}
for i := range a {
for j := range b {
if a[i] == b[j] {
return true
}
}
}
return false
}
//
func StringSliceEqual(a, b []string) bool {
if (a == nil) != (b == nil) {
return false
}
if len(a) != len(b) {
return false
}
sort.Strings(a)
sort.Strings(b)
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
// value compare
func ValueEqual(a interface{}, b interface{}) bool {
aBytes, err := json.Marshal(a)
if err != nil {
return false
}
bBytes, err := json.Marshal(b)
if err != nil {
return false
}
return bytes.Equal(aBytes, bBytes)
}