/cmd/shield/utils.go

https://github.com/starkandwayne/shield · Go · 269 lines · 230 code · 39 blank · 0 comment · 60 complexity · b1b26e777eb00e19e11a7c7acbf2fbdc MD5 · raw file

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/json"
  6. "os"
  7. "regexp"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "unicode"
  12. fmt "github.com/jhunt/go-ansi"
  13. "github.com/mattn/go-isatty"
  14. "golang.org/x/crypto/ssh/terminal"
  15. )
  16. func fail(rc int, m string, args ...interface{}) {
  17. fmt.Fprintf(os.Stderr, m, args...)
  18. os.Exit(rc)
  19. }
  20. func bail(err error) {
  21. if err != nil {
  22. if opts.JSON {
  23. fmt.Fprintf(os.Stderr, "%s\n", asJSON(struct {
  24. Error string `json:"error"`
  25. }{
  26. Error: err.Error(),
  27. }))
  28. os.Exit(1)
  29. }
  30. fmt.Fprintf(os.Stderr, "@R{!!! %s}\n", err)
  31. os.Exit(1)
  32. }
  33. }
  34. func bailon(pre string, err error) {
  35. if err != nil {
  36. bail(fmt.Errorf("%s: %s\n", pre, err))
  37. }
  38. }
  39. func required(ok bool, msg string) {
  40. if !ok {
  41. fmt.Fprintf(os.Stderr, "@Y{%s}\n", msg)
  42. os.Exit(3)
  43. }
  44. }
  45. func confirm(yes bool, msg string, args ...interface{}) bool {
  46. if yes {
  47. return true
  48. }
  49. switch prompt(msg+" [y/N] ", args...) {
  50. case "y", "Y", "yes":
  51. return true
  52. default:
  53. return false
  54. }
  55. }
  56. func prompt(label string, args ...interface{}) string {
  57. fmt.Fprintf(os.Stderr, label, args...)
  58. s, _ := bufio.NewReader(os.Stdin).ReadString('\n')
  59. return strings.TrimSuffix(s, "\n")
  60. }
  61. func secureprompt(label string, args ...interface{}) string {
  62. if !isatty.IsTerminal(os.Stdin.Fd()) {
  63. s, _ := bufio.NewReader(os.Stdin).ReadString('\n')
  64. return strings.TrimSuffix(s, "\n")
  65. }
  66. fmt.Fprintf(os.Stderr, label, args...)
  67. b, _ := terminal.ReadPassword(int(os.Stdin.Fd()))
  68. fmt.Fprintf(os.Stderr, "\n")
  69. return string(b)
  70. }
  71. func asJSON(x interface{}) string {
  72. var raw []byte
  73. if s, ok := x.(string); ok {
  74. raw = []byte(s)
  75. } else if b, ok := x.([]byte); ok {
  76. raw = b
  77. } else {
  78. b, err := json.Marshal(x)
  79. if err != nil {
  80. return ""
  81. }
  82. raw = b
  83. }
  84. tmp := bytes.Buffer{}
  85. if json.Indent(&tmp, raw, "", " ") != nil {
  86. return string(raw)
  87. }
  88. return tmp.String()
  89. }
  90. func dataConfig(data []string) (map[string]interface{}, error) {
  91. conf := make(map[string]interface{})
  92. for _, datum := range data {
  93. p := strings.SplitN(datum, "=", 2)
  94. if len(p) < 2 {
  95. return nil, fmt.Errorf("invalid --data item '%s' (should be key=value format)\n")
  96. }
  97. conf[p[0]] = p[1]
  98. }
  99. return conf, nil
  100. }
  101. func strftime(t int64) string {
  102. f := os.Getenv("SHIELD_DATE_FORMAT")
  103. if f == "" {
  104. f = "2006-01-02 15:04:05-0700"
  105. }
  106. return time.Unix(t, 0).Format(f)
  107. }
  108. func strptime(t string) int64 {
  109. f := os.Getenv("SHIELD_DATE_FORMAT")
  110. if f == "" {
  111. f = "2006-01-02 15:04:05-0700"
  112. }
  113. u, err := time.Parse(f, t)
  114. if err != nil {
  115. bail(err)
  116. }
  117. return u.Unix()
  118. }
  119. func strftimenil(t int64, ifnil string) string {
  120. if t == 0 {
  121. return ifnil
  122. }
  123. return strftime(t)
  124. }
  125. func parseBytes(in string) (int64, error) {
  126. if in == "" {
  127. return 0, nil
  128. }
  129. re := regexp.MustCompile(`(?i)(\d+(?:\.\d+)?)\s?([kmgt])?b?`)
  130. m := re.FindStringSubmatch(in)
  131. if m == nil {
  132. return 0, fmt.Errorf("Invalid size spec '%s' (try something like '100M' or '1.5gb')", in)
  133. }
  134. f, err := strconv.ParseFloat(m[1], 64)
  135. if err != nil {
  136. return 0, fmt.Errorf("Invalid size spec '%s' (%s)", in, err)
  137. }
  138. switch m[2] {
  139. case "":
  140. return int64(f), nil
  141. case "k", "K":
  142. return (int64)(f * 1024), nil
  143. case "m", "M":
  144. return (int64)(f * 1024 * 1024), nil
  145. case "g", "G":
  146. return (int64)(f * 1024 * 1024 * 1024), nil
  147. case "t", "T":
  148. return (int64)(f * 1024 * 1024 * 1024 * 1024), nil
  149. }
  150. return 0, fmt.Errorf("Invalid size spec '%s'", in)
  151. }
  152. func formatBytes(in int64) string {
  153. if in < 1024 {
  154. return fmt.Sprintf("%db", in)
  155. }
  156. if in < 1024*1024 {
  157. return fmt.Sprintf("%0.1fK", float64(in)/1024.0)
  158. }
  159. if in < 1024*1024*1024 {
  160. return fmt.Sprintf("%0.1fM", float64(in)/1024.0/1024.0)
  161. }
  162. if in < 1024*1024*1024*1024 {
  163. return fmt.Sprintf("%0.1fG", float64(in)/1024.0/1024.0/1024.0)
  164. }
  165. return fmt.Sprintf("%0.1fT", float64(in)/1024.0/1024.0/1024.0/1024.0)
  166. }
  167. func uuid8(s string) string {
  168. if len(s) < 8 {
  169. return s
  170. }
  171. return s[0:8]
  172. }
  173. func uuid8full(s string, full bool) string {
  174. if full {
  175. return s
  176. }
  177. return uuid8(s)
  178. }
  179. func wrap(s string, lim uint) string {
  180. init := make([]byte, 0, len(s))
  181. buf := bytes.NewBuffer(init)
  182. var current uint
  183. var wordBuf, spaceBuf bytes.Buffer
  184. for _, char := range s {
  185. if char == '\n' {
  186. if wordBuf.Len() == 0 {
  187. if current+uint(spaceBuf.Len()) > lim {
  188. current = 0
  189. } else {
  190. current += uint(spaceBuf.Len())
  191. spaceBuf.WriteTo(buf)
  192. }
  193. spaceBuf.Reset()
  194. } else {
  195. current += uint(spaceBuf.Len() + wordBuf.Len())
  196. spaceBuf.WriteTo(buf)
  197. spaceBuf.Reset()
  198. wordBuf.WriteTo(buf)
  199. wordBuf.Reset()
  200. }
  201. buf.WriteRune(char)
  202. current = 0
  203. } else if unicode.IsSpace(char) {
  204. if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
  205. current += uint(spaceBuf.Len() + wordBuf.Len())
  206. spaceBuf.WriteTo(buf)
  207. spaceBuf.Reset()
  208. wordBuf.WriteTo(buf)
  209. wordBuf.Reset()
  210. }
  211. spaceBuf.WriteRune(char)
  212. } else {
  213. wordBuf.WriteRune(char)
  214. if current+uint(spaceBuf.Len()+wordBuf.Len()) > lim && uint(wordBuf.Len()) < lim {
  215. buf.WriteRune('\n')
  216. current = 0
  217. spaceBuf.Reset()
  218. }
  219. }
  220. }
  221. if wordBuf.Len() == 0 {
  222. if current+uint(spaceBuf.Len()) <= lim {
  223. spaceBuf.WriteTo(buf)
  224. }
  225. } else {
  226. spaceBuf.WriteTo(buf)
  227. wordBuf.WriteTo(buf)
  228. }
  229. return buf.String()
  230. }