The little things give you away... A collection of various small helper stuff
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

180 lignes
5.3 KiB

  1. #!/bin/bash
  2. columns=("JOBID" "URL" "USER" "PIPENICK" "QUEUED" "STARTED" "LAST ACTIVE") # Duplicated in Python code!
  3. function valid_column {
  4. local candidate="$1"
  5. local column
  6. for column in "${columns[@]}"
  7. do
  8. [[ "${candidate}" == "${column}" ]] && return 0
  9. done
  10. return 1
  11. }
  12. sortcolumns=()
  13. filter=
  14. nocolours=
  15. notable=
  16. while [[ $# -gt 0 ]]
  17. do
  18. if [[ "$1" == "--help" || "$1" == "-h" ]]
  19. then
  20. echo "Usage: archivebot-jobs [options]" >&2
  21. echo "Prints a table of current AB jobs" >&2
  22. echo "Options:" >&2
  23. echo " --help, -h Show this message and exit." >&2
  24. echo " --sort COLUMN, -s Sort the table by a column. This can be used multiple times to refine the sorting." >&2
  25. echo " --filter FILTER, -f Filter the table for rows where a COLUMN has a certain VALUE. If specified multiple times, only the last value is used." >&2
  26. echo " The FILTER has this format: COLUMN{=|<|>|^|$}VALUE" >&2
  27. echo " = means the value must be exactly as specified; < and > mean it must be less/greater than the specified; ^ and $ mean it must start/end with the specified." >&2
  28. echo " --no-colours, --no-colors Don't colourise the last activity column if it's been a while." >&2
  29. echo " --no-table Raw output without feeding through column(1); columns are separated by tabs." >&2
  30. echo "The COLUMNs are the names of each column, printed in capital letters in the first line of the output." >&2
  31. exit 0
  32. elif [[ "$1" == "--sort" || "$1" == "-s" ]]
  33. then
  34. sortcolumns+=("$2")
  35. shift
  36. elif [[ "$1" == "--filter" || "$1" == "-f" ]]
  37. then
  38. filter="$2"
  39. shift
  40. elif [[ "$1" == "--no-colours" || "$1" == "--no-colors" ]]
  41. then
  42. nocolours=1
  43. elif [[ "$1" == "--no-table" ]]
  44. then
  45. notable=1
  46. else
  47. echo "Unknown option: $1" >&2
  48. exit 1
  49. fi
  50. shift
  51. done
  52. # Validate sortcolumns and filter
  53. if [[ "${filter}" ]]
  54. then
  55. if [[ "${filter}" == *$'\n'* ]]
  56. then
  57. echo "Invalid filter: newlines not allowed" >&2
  58. exit 1
  59. fi
  60. if [[ ! ( "${filter}" == *'='* || "${filter}" == *'<'* || "${filter}" == *'>'* || "${filter}" == *'^'* || "${filter}" == *'$'* ) ]]
  61. then
  62. echo "Invalid filter: ${filter}" >&2
  63. exit 1
  64. fi
  65. column="${filter%%[=<>^$]*}"
  66. if ! valid_column "${column^^}"
  67. then
  68. echo "Invalid filter column: ${column}" >&2
  69. exit 1
  70. fi
  71. fi
  72. if [[ ${#sortcolumns[@]} -gt 0 ]]
  73. then
  74. for column in "${sortcolumns[@]}"
  75. do
  76. if ! valid_column "${column^^}"
  77. then
  78. echo "Invalid sort column: ${column}" >&2
  79. exit 1
  80. fi
  81. done
  82. else
  83. # Default sort order
  84. sortcolumns+=("JOBID")
  85. fi
  86. if [[ "${notable}" ]]
  87. then
  88. column=("cat")
  89. else
  90. column=("column" "-t" $'-s\t')
  91. fi
  92. jobdata="$(curl -s -H "Accept: application/json" "http://dashboard.at.ninjawedding.org/logs/recent?count=1" 2>/dev/null)"
  93. pipelinedata="$(curl -s -H "Accept: application/json" "http://dashboard.at.ninjawedding.org/pipelines" 2>/dev/null)"
  94. if [[ -z "${jobdata}" || -z "${pipelinedata}" ]]
  95. then
  96. echo "Error retrieving job or pipeline data" >&2
  97. exit 1
  98. fi
  99. { echo "${jobdata}"; echo "${pipelinedata}"; echo "${filter}"; } | python3 -c \
  100. '
  101. if True: # For sensible indentation
  102. import json
  103. import sys
  104. import time
  105. def time_ago(diff):
  106. if diff <= 0:
  107. return "now"
  108. elif diff < 60:
  109. return "<1 min ago"
  110. elif diff < 86400:
  111. return (f"{diff // 3600:.0f}h " if diff >= 3600 else "") + f"{(diff % 3600) // 60:.0f}mn ago"
  112. else:
  113. return f"{diff // 86400:.0f}d {(diff % 86400) // 3600:.0f}h ago"
  114. def coloured_time_ago(diff):
  115. if diff >= 300:
  116. return "\x1b[0;31m" + time_ago(diff) + "\x1b[0m"
  117. else:
  118. return time_ago(diff)
  119. jobdata = json.loads(sys.stdin.readline())
  120. pipelinedata = json.loads(sys.stdin.readline())
  121. filter = sys.stdin.readline().strip()
  122. pipelines = {p["id"]: p["nickname"] for p in pipelinedata["pipelines"]}
  123. columns = ("JOBID", "URL", "USER", "PIPENICK", "QUEUED", "STARTED", "LAST ACTIVE") # Duplicated in Bash code!
  124. jobs = []
  125. currentTime = time.time()
  126. for j in jobdata:
  127. jobs.append([
  128. j["job_data"]["ident"],
  129. j["job_data"]["url"],
  130. j["job_data"]["started_by"],
  131. pipelines[j["job_data"]["pipeline_id"]] if j["job_data"]["pipeline_id"] in pipelines else "unknown",
  132. currentTime - j["job_data"]["queued_at"],
  133. currentTime - j["job_data"]["started_at"],
  134. currentTime - j["ts"],
  135. ])
  136. # Filter
  137. if filter:
  138. import re
  139. match = re.match(r"^(?P<column>[A-Za-z ]+)(?P<op>[=<>^$])(?P<value>.*)$", filter)
  140. filterDict = match.groupdict()
  141. filterDict["column"] = filterDict["column"].upper()
  142. assert filterDict["column"] in columns
  143. columnIdx = columns.index(filterDict["column"])
  144. compFunc = {
  145. "=": lambda a, b: a == b,
  146. "<": lambda a, b: a < b,
  147. ">": lambda a, b: a > b,
  148. "^": lambda a, b: a.startswith(b),
  149. "$": lambda a, b: a.endswith(b),
  150. }[filterDict["op"]]
  151. jobs = [job for job in jobs if compFunc(job[columnIdx], filterDict["value"])]
  152. # Sort
  153. sortColumns = ('"$(printf "'%s', " "${sortcolumns[@]}")"')
  154. assert all(column.upper() in columns for column in sortColumns)
  155. sortColumnIdxs = tuple(columns.index(column.upper()) for column in sortColumns)
  156. jobs = sorted(jobs, key = lambda job: tuple(job[columnIdx] for columnIdx in sortColumnIdxs))
  157. # Print
  158. print("\t".join(columns))
  159. for job in jobs:
  160. job[4] = time_ago(job[4])
  161. job[5] = time_ago(job[5])
  162. job[6] = (coloured_time_ago if not "'${nocolours}'" else time_ago)(job[6])
  163. print("\t".join(job))
  164. ' | "${column[@]}"