-
Notifications
You must be signed in to change notification settings - Fork 114
/
Copy pathlint-alloy.sh
executable file
·147 lines (128 loc) · 4.96 KB
/
lint-alloy.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env bash
PARENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${PARENT_DIR}/scripts/includes/utils.sh"
source "${PARENT_DIR}/scripts/includes/logging.sh"
usage() {
echo "USAGE: lint-configs.sh [--public-preview] output.alloy [output2.alloy...]"
echo ""
echo "Uses Grafana Alloy to lint the generated configuration"
echo " --public-preview - Switch to the public-preview stability level"
}
# check to see if alloy is installed
if [[ "$(command -v alloy || true)" = "" ]]; then
emergency "alloy is required if running lint locally, see: (https://grafana.com/docs/alloy/latest/) or run: brew install grafana-alloy";
fi
# determine whether or not the script is called directly or sourced
(return 0 2>/dev/null) && sourced=1 || sourced=0
# Initialize a flag variable
FORMAT="console"
STABILITY_LEVEL=generally-available
# Loop through all arguments
for arg in "$@"
do
if [[ "${arg}" == "--format=checkstyle" ]]; then
# Set the flag to true if the specific argument is found
FORMAT="checkstyle"
break
fi
done
if [[ "${FORMAT}" == "console" ]]; then
# output the heading
heading "Kubernetes Monitoring Helm" "Performing Alloy Lint"
fi
statusCode=0
checkstyle='<?xml version="1.0" encoding="utf-8"?><checkstyle version="4.3">'
# Inject a component that utilizes Kubernetes discovery, so we know that the config will fail in a predictable way.
k8sDiscovery='discovery.kubernetes "lint_config_component" { role = "nodes" }'
for file in "$@";
do
if grep "${file}" -e "remotecfg {" >/dev/null; then
STABILITY_LEVEL=public-preview
fi
if grep "${file}" -e "livedebugging {" >/dev/null; then
STABILITY_LEVEL=experimental
fi
# if the file doesn't exist skip it
if [[ ! -f "${file}" ]]; then
continue
fi
# add file to checkstyle output
checkstyle="${checkstyle}<file name=\"${file}\">"
fmt_output=$(alloy fmt "${file}" 2>&1)
fmtCode="$?"
fmt_output=$(echo "${fmt_output}" | grep -v "Error: encountered errors during formatting")
# Attempt to run with the config file.
run_code=0
run_output=""
file_is_empty=$(grep -cve '^\s*$' "${file}" || true)
# make sure the file is not empty, otherwise alloy will actually run and not exit
if [[ "${file_is_empty}" != 0 ]]; then
run_output=$(alloy run --stability.level "${STABILITY_LEVEL}" <(cat "${file}"; echo "${k8sDiscovery}") 2>&1)
# A "successful" attempt will fail because we're not running in Kubernetes
if ! echo "${run_output}" | grep "KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT must be defined" >/dev/null; then
run_code=1
fi
fi
# if the current code is 0, output the file name for logging purposes
if [[ "${fmtCode}" == 0 ]] && [[ "${run_code}" == 0 ]]; then
# output to console only if the format is console
if [[ "${FORMAT}" == "console" ]]; then
echo -e "\\x1b[32m${file}\\x1b[0m: no issues found"
fi
checkstyle="${checkstyle}</file>"
else
# output to console only if the format is console
if [[ "${FORMAT}" == "console" ]]; then
echo -e "\\x1b[31m${file}\\x1b[0m: issues found"
fi
# output alloy fmt errors
if [[ "${fmtCode}" != 0 ]]; then
# loop each found issue
while IFS= read -r row; do
# Process each line here
line=$(echo "${row}" | awk -F ':' '{print $2}')
column=$(echo "${row}" | awk -F ':' '{print $3}')
error=$(echo "${row}" | cut -d':' -f4- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | sed -e 's/"/\"/g' | xargs || true)
checkstyle="${checkstyle}<error line=\"${line}\" column=\"${column}\" severity=\"error\" message=\"${error}\" source=\"alloy\"/>"
# output to console only if the format is console
if [[ "${FORMAT}" == "console" ]]; then
echo " - ${row}"
fi
done <<< "${fmt_output}"
fi
# output alloy run errors
if [[ "${run_code}" != 0 ]]; then
# loop each found issue
while IFS= read -r row; do
if [[ "${row}" =~ "Error: " ]]; then
# Process each line here
line=$(echo "${row}" | awk -F ':' '{print $2}')
column=$(echo "${row}" | awk -F ':' '{print $3}')
error=$(echo "${row}" | cut -d':' -f5- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | sed -e 's/"/\"/g' | xargs || true)
checkstyle="${checkstyle}<error line=\"${line}\" column=\"${column}\" severity=\"error\" message=\"${error}\" source=\"alloy\"/>"
# output to console only if the format is console
if [[ "${FORMAT}" == "console" ]]; then
echo " - ${row}"
fi
fi
done <<< "${run_output}"
fi
checkstyle="${checkstyle}</file>"
if [[ "${statusCode}" == 0 ]]; then
statusCode=1
fi
fi
done
checkstyle="${checkstyle}</checkstyle>"
if [[ "${FORMAT}" == "checkstyle" ]]; then
echo -n "${checkstyle}"
else
echo ""
echo ""
fi
# if the script was called by another, send a valid exit code
if [[ "${sourced}" == "1" ]]; then
return "${statusCode}"
else
exit "${statusCode}"
fi