|
#!/usr/bin/env bash |
|
|
|
set -e |
|
|
|
# Set your grafana specific usage data to be able to continue |
|
function usage_envvar { |
|
|
|
echo " |
|
## Set your grafana specific usage data to be able to continue |
|
## Below are examples |
|
|
|
export GF_JSON_GF_HOST='https://your.accessible.grafana.host' |
|
|
|
# Read https://grafana.com/docs/grafana/latest/http_api/auth/#create-api-token |
|
export GF_JSON_GF_API_KEY='yoUrGraFAnaAPIKEyyoUrGraFAnaAPIKEyyoUrGraFAnaAPIKEy=' |
|
|
|
# Read https://grafana.com/docs/grafana/latest/http_api/dashboard/#get-dashboard-by-uid |
|
export GF_JSON_DASHBOARD_UID='daSHBoARdUiD' |
|
|
|
## These are optional |
|
|
|
# Where you would want to sink the dashboard json file |
|
export GF_JSON_SINK_PATH='./my-sinked-dashboard.json' |
|
|
|
# Keys to ignore |
|
export GF_JSON_IGNORE_LIST='id uid version iteration' |
|
|
|
# to ease the first pull |
|
export GF_JSON_DEFAULT_TEMPLATE='{"id": null, "uid": null, "iteration": 0, "version": 1}' |
|
" |
|
|
|
} |
|
|
|
### end of setting bespoke data |
|
|
|
# fail fast in case conditions are not good |
|
|
|
if test -z "${GF_JSON_GF_HOST}"; then |
|
echo '$GF_JSON_GF_HOST not found, printing hint below.' |
|
usage_envvar |
|
exit 1 |
|
fi |
|
|
|
if test -z "${GF_JSON_GF_API_KEY}"; then |
|
echo '$GF_JSON_GF_API_KEY not found, printing hint below.' |
|
usage_envvar |
|
exit 1 |
|
fi |
|
|
|
if test -z "${GF_JSON_DASHBOARD_UID}"; then |
|
echo '$GF_JSON_DASHBOARD_UID not found, printing hint below.' |
|
usage_envvar |
|
exit 1 |
|
fi |
|
|
|
if test -z "$(command -v jq)"; then |
|
echo 'you will need `jq` to continue' |
|
exit 1 |
|
fi |
|
|
|
|
|
# prepare constants/variables |
|
|
|
api_pull="${GF_JSON_GF_HOST}/api/dashboards/uid/${GF_JSON_DASHBOARD_UID}" |
|
api_push="${GF_JSON_GF_HOST}/api/dashboards/db" |
|
|
|
sink_path="./my-sinked-dashboard.json" |
|
sink_path="${GF_JSON_SINK_PATH:-${sink_path}}" |
|
|
|
download="curl -s -H \"Authorization: Bearer ${GF_JSON_GF_API_KEY}\" ${api_pull} | jq -c '.dashboard'" |
|
|
|
upload="curl -H \"Authorization: Bearer ${GF_JSON_GF_API_KEY}\" \ |
|
-H \"Content-Type: application/json\" \ |
|
-H \"Accept: application/json\" \ |
|
--request POST --data-binary \"@/dev/stdin\" \ |
|
${api_push}" |
|
|
|
# set sensible default list of keys to ignore |
|
# currently this works for both pull and push |
|
ignore_list='id uid version iteration' |
|
ignore_list="${GF_JSON_IGNORE_LIST:-${ignore_list}}" |
|
|
|
# set sensible default value per key in case the initial pull didn't happen yet |
|
default_template='{"id": null, "uid": null, "iteration": 0, "version": 1}' |
|
default_template="${GF_JSON_DEFAULT_TEMPLATE:-${default_template}}" |
|
|
|
|
|
function sanitize { |
|
json_source="${1}" |
|
json_target="${2}" |
|
|
|
## skip error checking until I figure out how to handle errors from subshell properly |
|
## and just focus on making this function hard to error on the usage level |
|
## since its just an internal function anyway |
|
# if test -z "$(command -v jq)"; then |
|
# echo 'you will need `jq` to continue' |
|
# return 1 |
|
# fi |
|
# if test -z "${json_source}"; then |
|
# echo 'you need to provide $GF_JSON_SOURCE' |
|
# return 1 |
|
# fi |
|
# if test -z "${json_target}"; then |
|
# echo 'you need to provide $GF_JSON_TARGET' |
|
# exit 1 |
|
# fi |
|
|
|
result="${json_source}" |
|
|
|
# keep values listed in $ignore_list while updating the rest |
|
for ignore in $ignore_list; do |
|
val="$(echo -n "${json_target}" | jq ".${ignore}")" |
|
result="$(echo -n "${result}" | jq ".${ignore} = $val")" |
|
done |
|
|
|
echo -n "${result}" |
|
} |
|
|
|
|
|
# `pull` respects its own data listed in $GF_JSON_IGNORE_LIST |
|
# from a file at $sink_path unless the file didn't exist yet |
|
function pull { |
|
json_source="$(eval ${download})" |
|
json_target="$(cat ${sink_path} || echo "${default_template}" | jq -c)" |
|
sanitize "${json_source}" "${json_target}" > ${sink_path} |
|
echo "sinked to ${sink_path}" |
|
} |
|
|
|
# `push` does oppoiste of what pull does |
|
# it doesn't support the initial push without $GF_JSON_DASHBOARD_UID on purpose |
|
# for initial push, follow https://grafana.com/docs/grafana/latest/dashboards/export-import/#import-dashboard |
|
# and `export GF_JSON_DASHBOARD_UID='daSHBoARdUiD'` from just created dashboard |
|
function push { |
|
json_source="$(cat ${sink_path} | jq -c)" |
|
json_target="$(eval ${download})" |
|
sanitize "${json_source}" "${json_target}" | jq -c '{"dashboard": .}' | eval "${upload}" |
|
} |
|
|
|
exec_name="$(basename ${0})" |
|
|
|
if test "${exec_name}" == "gfdjr"; then |
|
pull |
|
elif test "${exec_name}" == "gfdjs"; then |
|
push |
|
else |
|
echo 'binary(simlink) name should be either `gfdjr` (to pull) or `gfdjs` (to push)' |
|
fi |
|
|