1
2 package monutil
3
4 import (
5 "bufio"
6 "errors"
7 "fmt"
8 "io/fs"
9 "log"
10 "os"
11 "os/exec"
12 "path/filepath"
13 "regexp"
14 "runtime"
15 "strconv"
16 "strings"
17
18 gptext "github.com/jedib0t/go-pretty/v6/text"
19 )
20
21 const (
22 foremanRegex = `ret-edge-(dev|stage|prod)\d-foreman(-\w+|)`
23 )
24
25
26
27
28
29 func FileExists(filePath string) bool {
30 if _, err := os.Stat(filePath); err != nil && os.IsNotExist(err) {
31 return false
32 }
33 return true
34 }
35
36
37 func IsDirectory(path string) bool {
38 fileInfo, err := os.Stat(path)
39 if err != nil {
40 return false
41 }
42 return fileInfo.IsDir()
43 }
44
45
46 func FilterString(filter string, str string) string {
47 r := regexp.MustCompile(filter)
48 var submatches []string
49 matches := r.FindAllStringSubmatch(str, -1)
50 for _, v := range matches {
51 submatches = append(submatches, strings.Join(v, ""))
52 }
53 return strings.Join(submatches, "")
54 }
55
56
57 func ReconcileFileNames(names []string) []string {
58 var fileNames []string
59 for _, n := range names {
60 if !InStrList(n, fileNames) {
61 fileNames = append(fileNames, n)
62 continue
63 }
64
65
66 iter := getNextIter(fileNames, n+`_(Duplicate_Name_([\d]+)).json`)
67 fileNames = append(fileNames, n+"_(Duplicate_Name_"+strconv.Itoa(iter)+").json")
68 }
69
70 return fileNames
71 }
72
73
74 func DiffStrSlice(s1 []string, s2 []string) []string {
75 var diff []string
76 if InSlice(s1, s2) {
77 return diff
78 }
79
80 for _, v := range s2 {
81 if !InStrList(v, s1) {
82 diff = append(diff, v)
83 }
84 }
85 return diff
86 }
87
88
89 func RemoveStrSlice(s1 []string, s2 []string) []string {
90 remSlice := s1
91 for i := 0; i < len(s2); i++ {
92 remSlice = RemoveString(s2[i], remSlice)
93 }
94 return remSlice
95 }
96
97
98 func RemoveString(str string, slice []string) []string {
99 if !InStrList(str, slice) {
100 return slice
101 }
102
103 var newSlice []string
104 for i := 0; i < len(slice); i++ {
105 if slice[i] != str {
106 newSlice = append(newSlice, slice[i])
107 }
108 }
109
110 return newSlice
111 }
112
113
114 func InStrList(s string, l []string) bool {
115 for i := 0; i < len(l); i++ {
116 if l[i] == s {
117 return true
118 }
119 }
120 return false
121 }
122
123
124 func InIntList(s int, l []int) bool {
125 for i := 0; i < len(l); i++ {
126 if l[i] == s {
127 return true
128 }
129 }
130 return false
131 }
132
133
134
135 func getNextIter(list []string, filter string) int {
136 var iter []int
137 for _, l := range list {
138 r, _ := regexp.Compile(l + filter)
139 match := r.FindStringSubmatch(l)
140 if len(match) != 2 {
141 continue
142 }
143 mi, _ := strconv.Atoi(match[1])
144 iter = append(iter, mi)
145 }
146
147
148 var newIter = 1
149 for i := 0; i < len(iter); i++ {
150 if InIntList(newIter, iter) {
151 newIter++
152 }
153 }
154
155 return newIter
156 }
157
158
159 func InSlice(s1 []string, s2 []string) bool {
160
161 if len(s1) < len(s2) {
162 return false
163 }
164
165
166 if len(s2) == 0 && !(len(s1) == 0) {
167 return false
168 }
169
170
171 for _, v := range s2 {
172 if !InStrList(v, s1) {
173 return false
174 }
175 }
176 return true
177 }
178
179
180 func IsForeman(p string) bool {
181 r := regexp.MustCompile(foremanRegex)
182 return r.MatchString(p)
183 }
184
185
186 func IsList(s string) bool {
187 return len(strings.Split(s, ",")) > 1
188 }
189
190
191 func CompareStrSlice(a1 []string, a2 []string) []string {
192 return append(DiffStrSlice(a1, a2), DiffStrSlice(a2, a1)...)
193 }
194
195
196 func RegexNamedMatches(regex *regexp.Regexp, str string) map[string]string {
197 match := regex.FindStringSubmatch(str)
198
199 results := map[string]string{}
200 for i, name := range match {
201 results[regex.SubexpNames()[i]] = name
202 }
203 return results
204 }
205
206
207 func SliceToMap(s []string) map[string]string {
208 m := make(map[string]string)
209 for i := 0; i < len(s); i++ {
210 m[s[i]] = ""
211 }
212 return m
213 }
214
215
216 func MapSlice(strSlice []string) *map[string][]string {
217 strMap := make(map[string][]string)
218 for i := 0; i < len(strSlice); i++ {
219 strMap[strSlice[i]] = []string{}
220 }
221 return &strMap
222 }
223
224
225 func Keys(m map[string]string) []string {
226 var keys []string
227 for k := range m {
228 keys = append(keys, k)
229 }
230 return keys
231 }
232
233
234
235
236 func parsePrompt(s string) (bool, error) {
237 switch strings.ToLower(s) {
238 case "y":
239 return true, nil
240 case "n":
241 return false, nil
242 case "c":
243 return false, errors.New("cancel")
244 }
245 return false, errors.New("invalid keypress response")
246 }
247
248
249 func PromptYesNoCancel(s string) bool {
250 reader := bufio.NewReader(os.Stdin)
251 yes := White("[") + Magenta("Y") + White("es/")
252 no := Magenta("N") + White("o/")
253 cancel := Magenta("C") + White("ancel] : ")
254 fmt.Printf("%s %s%s%s", White(s), yes, no, cancel)
255
256 b := make([]byte, 1)
257 _, err := reader.Read(b)
258 if err != nil {
259 log.Fatal(err)
260 }
261
262 r, err := parsePrompt(string(b[0]))
263 if err != nil {
264 defer os.Exit(0)
265 }
266 return r
267 }
268
269 func runCmd(name string, arg ...string) {
270 cmd := exec.Command(name, arg...)
271 cmd.Stdout = os.Stdout
272 if err := cmd.Run(); err != nil {
273 fmt.Println(err.Error())
274 }
275 }
276
277
278 func ListFiles(rootPath string, fileSuffix string) ([]string, error) {
279 var files []string
280
281 if err := filepath.WalkDir(rootPath, func(path string, d fs.DirEntry, err error) error {
282 if err != nil {
283 return err
284 }
285
286 if !d.IsDir() && strings.HasSuffix(path, fileSuffix) {
287 files = append(files, path)
288 }
289 return nil
290 }); err != nil {
291 return nil, err
292 }
293 return files, nil
294 }
295
296
297 func ClearTerminal() {
298 switch runtime.GOOS {
299 case "darwin":
300 runCmd("clear")
301 case "linux":
302 runCmd("clear")
303 case "windows":
304 runCmd("cmd", "/c", "cls")
305 default:
306 runCmd("clear")
307 }
308 }
309
310 func Bold(v interface{}) string {
311 return gptext.Bold.Sprint(v)
312 }
313
314 func Italic(v interface{}) string {
315 return gptext.Italic.Sprint(v)
316 }
317
318 func Underline(v interface{}) string {
319 return gptext.Underline.Sprint(v)
320 }
321
322 func Red(v interface{}) string {
323 return gptext.FgHiRed.Sprint(v)
324 }
325
326 func Blue(v interface{}) string {
327 return gptext.FgBlue.Sprint(v)
328 }
329
330 func Green(v interface{}) string {
331 return gptext.FgHiGreen.Sprint(v)
332 }
333
334 func Yellow(v interface{}) string {
335 return gptext.FgHiYellow.Sprint(v)
336 }
337
338 func Cyan(v interface{}) string {
339 return gptext.FgHiCyan.Sprint(v)
340 }
341
342 func White(v interface{}) string {
343 return gptext.FgHiWhite.Sprint(v)
344 }
345
346 func Magenta(v interface{}) string {
347 return gptext.FgHiMagenta.Sprint(v)
348 }
349
350
351
352
353
354
355
356
357
358
359
360
361
362 func StringToMap(str string) map[string]string {
363 labelsMap := make(map[string]string)
364 splitString := regexp.MustCompile(`[\\,]+`).Split(str, -1)
365
366 for i := 0; i < len(splitString); i++ {
367 splitString[i] = strings.TrimSpace(splitString[i])
368 }
369
370 for i := 0; i < len(splitString); i++ {
371 if strings.Contains(splitString[i], ":") {
372 substr := regexp.MustCompile(`[\\:]+`).Split(splitString[i], -1)
373 labelsMap[substr[0]] = substr[1]
374 continue
375 }
376 labelsMap[splitString[i]] = ""
377 }
378 return labelsMap
379 }
380
381
382 func ContainsDuplicates(s []string) bool {
383 var l []string
384 for i := 0; i < len(s); i++ {
385 if InStrList(s[i], l) {
386 return true
387 }
388 l = append(l, s[i])
389 }
390 return false
391 }
392
View as plain text