| /* |
| * 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) |
| } |