...
1
4 package utils
5
6 import (
7 "fmt"
8 "math/rand"
9 "os"
10 "sync"
11 "syscall"
12 "time"
13 "unsafe"
14
15 "github.com/dustin/go-humanize"
16 "golang.conradwood.net/go-easyops/errors/shared"
17
18 _ "golang.conradwood.net/apis/autodeployer"
19 _ "golang.conradwood.net/apis/deploymonkey"
20 _ "golang.conradwood.net/apis/grafanadata"
21
22
23 _ "golang.yacloud.eu/apis/fscache"
24 _ "golang.yacloud.eu/apis/unixipc"
25 )
26
27 var (
28 randlock sync.Mutex
29 randsrc = rand.New(rand.NewSource(time.Now().UnixNano()))
30 )
31
32
33 func RandomInt(max int64) int {
34 randlock.Lock()
35 t := randsrc.Int63n(max)
36 randlock.Unlock()
37 return int(t)
38 }
39
40 func RandomString(n int) string {
41 const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
42 const (
43 letterIdxBits = 6
44 letterIdxMask = 1<<letterIdxBits - 1
45 letterIdxMax = 63 / letterIdxBits
46
47 )
48
49 b := make([]byte, n)
50
51 randlock.Lock()
52 defer randlock.Unlock()
53 for i, cache, remain := n-1, randsrc.Int63(), letterIdxMax; i >= 0; {
54 if remain == 0 {
55 cache, remain = randsrc.Int63(), letterIdxMax
56 }
57 if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
58 b[i] = letterBytes[idx]
59 i--
60 }
61 cache >>= letterIdxBits
62 remain--
63 }
64
65 return string(b)
66 }
67
68
69 func Bail(txt string, err error) {
70 if err == nil {
71 return
72 }
73 fmt.Printf("%s: %s\n", txt, shared.ErrorStringWithStackTrace(err))
74 os.Exit(10)
75 }
76
77
78 func IsLettersOnly(txt string) bool {
79 return IsOnlyChars(txt, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
80 }
81
82
83 func IsOnlyChars(txt string, valid string) bool {
84 for _, x := range txt {
85 b := false
86 for _, y := range valid {
87 if x == y {
88 b = true
89 }
90 }
91 if !b {
92 return false
93 }
94 }
95 return true
96 }
97
98
99 func RandomStall(minutes int) {
100 if minutes == 0 {
101 return
102 }
103 randlock.Lock()
104 t := randsrc.Int63n(int64(minutes * 60))
105 randlock.Unlock()
106 time.Sleep(time.Duration(t) * time.Second)
107 }
108
109 func MinInt(x, y int) int {
110 if x < y {
111 return x
112 }
113 return y
114 }
115
116 func MaxInt(x, y int) int {
117 if x > y {
118 return x
119 }
120 return y
121 }
122
123 func MinInt32(x, y int32) int32 {
124 if x < y {
125 return x
126 }
127 return y
128 }
129
130 func MaxInt32(x, y int32) int32 {
131 if x > y {
132 return x
133 }
134 return y
135 }
136
137 func MinInt64(x, y int64) int64 {
138 if x < y {
139 return x
140 }
141 return y
142 }
143
144 func MaxInt64(x, y int64) int64 {
145 if x > y {
146 return x
147 }
148 return y
149 }
150
151 func PrettyNumber(number uint64) string {
152 return humanize.Bytes(number)
153 }
154
155 type TerminalDimensions struct {
156 width int
157 height int
158 }
159
160 func (td *TerminalDimensions) Columns() int {
161 return td.width
162 }
163 func (td *TerminalDimensions) Rows() int {
164 return td.height
165 }
166
167
168 func TerminalSize() (*TerminalDimensions, error) {
169 type winsize struct {
170 Row uint16
171 Col uint16
172 Xpixel uint16
173 Ypixel uint16
174 }
175
176 ws := &winsize{}
177 retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
178 uintptr(syscall.Stdout),
179 uintptr(syscall.TIOCGWINSZ),
180 uintptr(unsafe.Pointer(ws)))
181
182 if int(retCode) == -1 {
183 return nil, fmt.Errorf("failed to get terminalsize: %d", errno)
184 }
185 ts := &TerminalDimensions{
186 width: int(ws.Col),
187 height: int(ws.Row),
188 }
189 return ts, nil
190 }
191
View as plain text