Compare commits
43 Commits
release-11
...
release-11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9840d56957 | ||
|
|
ecc4799abc | ||
|
|
17012180c7 | ||
|
|
742c101ba4 | ||
|
|
0968388f88 | ||
|
|
6a5aeba21c | ||
|
|
39d9542f7f | ||
|
|
3965e68c8d | ||
|
|
da025b1bd3 | ||
|
|
7db056f19b | ||
|
|
74c59a7ab3 | ||
|
|
a0819a1f33 | ||
|
|
09cfd78a21 | ||
|
|
65fd818f9e | ||
|
|
56cf32e5eb | ||
|
|
dd1d25e21d | ||
|
|
ed33d8c6de | ||
|
|
b014f56c1c | ||
|
|
c6652ff5e1 | ||
|
|
29bba2362b | ||
|
|
db61b04c40 | ||
|
|
b500645bfe | ||
|
|
422b1ef402 | ||
|
|
1833377202 | ||
|
|
86e3ac0021 | ||
|
|
ba1d98e1d8 | ||
|
|
d0df683dd5 | ||
|
|
2e16baaa96 | ||
|
|
c4b8303799 | ||
|
|
35b3075d06 | ||
|
|
c7307f997d | ||
|
|
ce8db62c7b | ||
|
|
c9170b1435 | ||
|
|
f61a60f54b | ||
|
|
7621bd81b1 | ||
|
|
32e5641d57 | ||
|
|
8e6a4a89cc | ||
|
|
ba97691498 | ||
|
|
9282416f04 | ||
|
|
5d7c632d09 | ||
|
|
46e36d9cf9 | ||
|
|
e3a857e995 | ||
|
|
e763dc131a |
290
.drone.yml
290
.drone.yml
@@ -71,18 +71,10 @@ steps:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
image: alpine:3.20.3
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.22.7-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- go install github.com/bazelbuild/buildtools/buildifier@latest
|
||||
- buildifier --lint=warn -mode=check -r .
|
||||
depends_on:
|
||||
- compile-build-cmd
|
||||
depends_on: []
|
||||
image: golang:1.22.7-alpine
|
||||
name: lint-starlark
|
||||
trigger:
|
||||
@@ -547,7 +539,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -986,7 +978,7 @@ steps:
|
||||
name: clone-enterprise
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -1261,13 +1253,6 @@ platform:
|
||||
os: linux
|
||||
services: []
|
||||
steps:
|
||||
- commands:
|
||||
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
|
||||
depends_on: []
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
image: golang:1.22.7-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- apt-get update -yq && apt-get install shellcheck
|
||||
- shellcheck -e SC1071 -e SC2162 scripts/**/*.sh
|
||||
@@ -1955,7 +1940,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2491,7 +2476,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -2696,7 +2681,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: windows-init
|
||||
@@ -3123,7 +3108,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3368,7 +3353,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3400,31 +3385,32 @@ steps:
|
||||
- |2-
|
||||
|
||||
bash -c '
|
||||
IMAGE_TAG=$(echo "$${TAG}" | sed -e "s/+/-/g")
|
||||
debug=
|
||||
if [[ -n $${DRY_RUN} ]]; then debug=echo; fi
|
||||
docker login -u $${DOCKER_USER} -p $${DOCKER_PASSWORD}
|
||||
|
||||
# Push the grafana-image-tags images
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-armv7
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-ubuntu-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-ubuntu-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-ubuntu-armv7
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-armv7
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-armv7
|
||||
|
||||
# Create the grafana manifests
|
||||
$$debug docker manifest create grafana/grafana:${TAG} grafana/grafana-image-tags:$${TAG}-amd64 grafana/grafana-image-tags:$${TAG}-arm64 grafana/grafana-image-tags:$${TAG}-armv7
|
||||
$$debug docker manifest create grafana/grafana:$${IMAGE_TAG} grafana/grafana-image-tags:$${IMAGE_TAG}-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-armv7
|
||||
|
||||
$$debug docker manifest create grafana/grafana:${TAG}-ubuntu grafana/grafana-image-tags:$${TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${TAG}-ubuntu-armv7
|
||||
$$debug docker manifest create grafana/grafana:$${IMAGE_TAG}-ubuntu grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-armv7
|
||||
|
||||
# Push the grafana manifests
|
||||
$$debug docker manifest push grafana/grafana:$${TAG}
|
||||
$$debug docker manifest push grafana/grafana:$${TAG}-ubuntu
|
||||
$$debug docker manifest push grafana/grafana:$${IMAGE_TAG}
|
||||
$$debug docker manifest push grafana/grafana:$${IMAGE_TAG}-ubuntu
|
||||
|
||||
# if LATEST is set, then also create & push latest
|
||||
if [[ -n $${LATEST} ]]; then
|
||||
$$debug docker manifest create grafana/grafana:latest grafana/grafana-image-tags:$${TAG}-amd64 grafana/grafana-image-tags:$${TAG}-arm64 grafana/grafana-image-tags:$${TAG}-armv7
|
||||
$$debug docker manifest create grafana/grafana:latest-ubuntu grafana/grafana-image-tags:$${TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${TAG}-ubuntu-armv7
|
||||
$$debug docker manifest create grafana/grafana:latest grafana/grafana-image-tags:$${IMAGE_TAG}-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-armv7
|
||||
$$debug docker manifest create grafana/grafana:latest-ubuntu grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-armv7
|
||||
|
||||
$$debug docker manifest push grafana/grafana:latest
|
||||
$$debug docker manifest push grafana/grafana:latest-ubuntu
|
||||
@@ -3499,7 +3485,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -3531,31 +3517,32 @@ steps:
|
||||
- |2-
|
||||
|
||||
bash -c '
|
||||
IMAGE_TAG=$(echo "$${TAG}" | sed -e "s/+/-/g")
|
||||
debug=
|
||||
if [[ -n $${DRY_RUN} ]]; then debug=echo; fi
|
||||
docker login -u $${DOCKER_USER} -p $${DOCKER_PASSWORD}
|
||||
|
||||
# Push the grafana-image-tags images
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-armv7
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-ubuntu-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-ubuntu-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${TAG}-ubuntu-armv7
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-armv7
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-amd64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-arm64
|
||||
$$debug docker push grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-armv7
|
||||
|
||||
# Create the grafana manifests
|
||||
$$debug docker manifest create grafana/grafana:${TAG} grafana/grafana-image-tags:$${TAG}-amd64 grafana/grafana-image-tags:$${TAG}-arm64 grafana/grafana-image-tags:$${TAG}-armv7
|
||||
$$debug docker manifest create grafana/grafana:$${IMAGE_TAG} grafana/grafana-image-tags:$${IMAGE_TAG}-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-armv7
|
||||
|
||||
$$debug docker manifest create grafana/grafana:${TAG}-ubuntu grafana/grafana-image-tags:$${TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${TAG}-ubuntu-armv7
|
||||
$$debug docker manifest create grafana/grafana:$${IMAGE_TAG}-ubuntu grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-armv7
|
||||
|
||||
# Push the grafana manifests
|
||||
$$debug docker manifest push grafana/grafana:$${TAG}
|
||||
$$debug docker manifest push grafana/grafana:$${TAG}-ubuntu
|
||||
$$debug docker manifest push grafana/grafana:$${IMAGE_TAG}
|
||||
$$debug docker manifest push grafana/grafana:$${IMAGE_TAG}-ubuntu
|
||||
|
||||
# if LATEST is set, then also create & push latest
|
||||
if [[ -n $${LATEST} ]]; then
|
||||
$$debug docker manifest create grafana/grafana:latest grafana/grafana-image-tags:$${TAG}-amd64 grafana/grafana-image-tags:$${TAG}-arm64 grafana/grafana-image-tags:$${TAG}-armv7
|
||||
$$debug docker manifest create grafana/grafana:latest-ubuntu grafana/grafana-image-tags:$${TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${TAG}-ubuntu-armv7
|
||||
$$debug docker manifest create grafana/grafana:latest grafana/grafana-image-tags:$${IMAGE_TAG}-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-armv7
|
||||
$$debug docker manifest create grafana/grafana:latest-ubuntu grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-amd64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-arm64 grafana/grafana-image-tags:$${IMAGE_TAG}-ubuntu-armv7
|
||||
|
||||
$$debug docker manifest push grafana/grafana:latest
|
||||
$$debug docker manifest push grafana/grafana:latest-ubuntu
|
||||
@@ -3647,7 +3634,8 @@ steps:
|
||||
image: golang:1.22.7-alpine
|
||||
name: compile-build-cmd
|
||||
- commands:
|
||||
- ./bin/build artifacts packages --tag $${DRONE_TAG} --src-bucket $${PRERELEASE_BUCKET}
|
||||
- ./bin/build artifacts packages --artifacts-editions=oss --tag $${DRONE_TAG} --src-bucket
|
||||
$${PRERELEASE_BUCKET}
|
||||
depends_on:
|
||||
- compile-build-cmd
|
||||
environment:
|
||||
@@ -3657,19 +3645,6 @@ steps:
|
||||
from_secret: prerelease_bucket
|
||||
image: grafana/grafana-ci-deploy:1.3.3
|
||||
name: publish-artifacts
|
||||
- commands:
|
||||
- ./bin/build artifacts static-assets --tag ${DRONE_TAG} --static-asset-editions=grafana-oss
|
||||
depends_on:
|
||||
- compile-build-cmd
|
||||
environment:
|
||||
GCP_KEY:
|
||||
from_secret: gcp_grafanauploads_base64
|
||||
PRERELEASE_BUCKET:
|
||||
from_secret: prerelease_bucket
|
||||
STATIC_ASSET_EDITIONS:
|
||||
from_secret: static_asset_editions
|
||||
image: grafana/grafana-ci-deploy:1.3.3
|
||||
name: publish-static-assets
|
||||
- commands:
|
||||
- ./bin/build artifacts storybook --tag ${DRONE_TAG}
|
||||
depends_on:
|
||||
@@ -3689,7 +3664,6 @@ steps:
|
||||
-f latest=$${LATEST} --repo=grafana/grafana release-pr.yml
|
||||
depends_on:
|
||||
- publish-artifacts
|
||||
- publish-static-assets
|
||||
environment:
|
||||
GH_CLI_URL: https://github.com/cli/cli/releases/download/v2.50.0/gh_2.50.0_linux_amd64.tar.gz
|
||||
GITHUB_TOKEN:
|
||||
@@ -3821,6 +3795,7 @@ platform:
|
||||
services: []
|
||||
steps:
|
||||
- commands:
|
||||
- export version=$(echo ${TAG} | sed -e "s/+security-/-/g")
|
||||
- 'echo "Step 1: Updating package lists..."'
|
||||
- apt-get update >/dev/null 2>&1
|
||||
- 'echo "Step 2: Installing prerequisites..."'
|
||||
@@ -3836,7 +3811,7 @@ steps:
|
||||
- 'echo "Step 5: Installing Grafana..."'
|
||||
- for i in $(seq 1 60); do
|
||||
- ' if apt-get update >/dev/null 2>&1 && DEBIAN_FRONTEND=noninteractive apt-get
|
||||
install -yq grafana=${TAG} >/dev/null 2>&1; then'
|
||||
install -yq grafana=$version >/dev/null 2>&1; then'
|
||||
- ' echo "Command succeeded on attempt $i"'
|
||||
- ' break'
|
||||
- ' else'
|
||||
@@ -3850,10 +3825,10 @@ steps:
|
||||
- ' fi'
|
||||
- done
|
||||
- 'echo "Step 6: Verifying Grafana installation..."'
|
||||
- 'if dpkg -s grafana | grep -q "Version: ${TAG}"; then'
|
||||
- ' echo "Successfully verified Grafana version ${TAG}"'
|
||||
- 'if dpkg -s grafana | grep -q "Version: $version"; then'
|
||||
- ' echo "Successfully verified Grafana version $version"'
|
||||
- else
|
||||
- ' echo "Failed to verify Grafana version ${TAG}"'
|
||||
- ' echo "Failed to verify Grafana version $version"'
|
||||
- ' exit 1'
|
||||
- fi
|
||||
- echo "Verification complete."
|
||||
@@ -3881,11 +3856,12 @@ steps:
|
||||
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
|
||||
' > /etc/yum.repos.d/grafana.repo
|
||||
- 'echo "Step 5: Checking RPM repository..."'
|
||||
- dnf list available grafana-${TAG}
|
||||
- export version=$(echo "${TAG}" | sed -e "s/+security-/^security_/g")
|
||||
- dnf list available grafana-$version
|
||||
- if [ $? -eq 0 ]; then
|
||||
- ' echo "Grafana package found in repository. Installing from repo..."'
|
||||
- for i in $(seq 1 60); do
|
||||
- ' if dnf install -y --nogpgcheck grafana-${TAG} >/dev/null 2>&1; then'
|
||||
- ' if dnf install -y --nogpgcheck grafana-$version >/dev/null 2>&1; then'
|
||||
- ' echo "Command succeeded on attempt $i"'
|
||||
- ' break'
|
||||
- ' else'
|
||||
@@ -3902,16 +3878,16 @@ steps:
|
||||
- ' rpm --import https://rpm.grafana.com/gpg.key'
|
||||
- ' rpm -qa gpg-pubkey* | xargs rpm -qi | grep -i grafana'
|
||||
- else
|
||||
- ' echo "Grafana package version ${TAG} not found in repository."'
|
||||
- ' echo "Grafana package version $version not found in repository."'
|
||||
- ' dnf repolist'
|
||||
- ' dnf list available grafana*'
|
||||
- ' exit 1'
|
||||
- fi
|
||||
- 'echo "Step 6: Verifying Grafana installation..."'
|
||||
- if rpm -q grafana | grep -q "${TAG}"; then
|
||||
- ' echo "Successfully verified Grafana version ${TAG}"'
|
||||
- if rpm -q grafana | grep -q "$verison"; then
|
||||
- ' echo "Successfully verified Grafana version $version"'
|
||||
- else
|
||||
- ' echo "Failed to verify Grafana version ${TAG}"'
|
||||
- ' echo "Failed to verify Grafana version $version"'
|
||||
- ' exit 1'
|
||||
- fi
|
||||
- echo "Verification complete."
|
||||
@@ -3998,6 +3974,7 @@ steps:
|
||||
from_secret: packages_service_account
|
||||
target_bucket: grafana-packages
|
||||
- commands:
|
||||
- export version=$(echo ${TAG} | sed -e "s/+security-/-/g")
|
||||
- 'echo "Step 1: Updating package lists..."'
|
||||
- apt-get update >/dev/null 2>&1
|
||||
- 'echo "Step 2: Installing prerequisites..."'
|
||||
@@ -4013,7 +3990,7 @@ steps:
|
||||
- 'echo "Step 5: Installing Grafana..."'
|
||||
- for i in $(seq 1 60); do
|
||||
- ' if apt-get update >/dev/null 2>&1 && DEBIAN_FRONTEND=noninteractive apt-get
|
||||
install -yq grafana=${TAG} >/dev/null 2>&1; then'
|
||||
install -yq grafana=$version >/dev/null 2>&1; then'
|
||||
- ' echo "Command succeeded on attempt $i"'
|
||||
- ' break'
|
||||
- ' else'
|
||||
@@ -4027,10 +4004,10 @@ steps:
|
||||
- ' fi'
|
||||
- done
|
||||
- 'echo "Step 6: Verifying Grafana installation..."'
|
||||
- 'if dpkg -s grafana | grep -q "Version: ${TAG}"; then'
|
||||
- ' echo "Successfully verified Grafana version ${TAG}"'
|
||||
- 'if dpkg -s grafana | grep -q "Version: $version"; then'
|
||||
- ' echo "Successfully verified Grafana version $version"'
|
||||
- else
|
||||
- ' echo "Failed to verify Grafana version ${TAG}"'
|
||||
- ' echo "Failed to verify Grafana version $version"'
|
||||
- ' exit 1'
|
||||
- fi
|
||||
- echo "Verification complete."
|
||||
@@ -4059,11 +4036,12 @@ steps:
|
||||
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
|
||||
' > /etc/yum.repos.d/grafana.repo
|
||||
- 'echo "Step 5: Checking RPM repository..."'
|
||||
- dnf list available grafana-${TAG}
|
||||
- export version=$(echo "${TAG}" | sed -e "s/+security-/^security_/g")
|
||||
- dnf list available grafana-$version
|
||||
- if [ $? -eq 0 ]; then
|
||||
- ' echo "Grafana package found in repository. Installing from repo..."'
|
||||
- for i in $(seq 1 60); do
|
||||
- ' if dnf install -y --nogpgcheck grafana-${TAG} >/dev/null 2>&1; then'
|
||||
- ' if dnf install -y --nogpgcheck grafana-$version >/dev/null 2>&1; then'
|
||||
- ' echo "Command succeeded on attempt $i"'
|
||||
- ' break'
|
||||
- ' else'
|
||||
@@ -4080,16 +4058,16 @@ steps:
|
||||
- ' rpm --import https://rpm.grafana.com/gpg.key'
|
||||
- ' rpm -qa gpg-pubkey* | xargs rpm -qi | grep -i grafana'
|
||||
- else
|
||||
- ' echo "Grafana package version ${TAG} not found in repository."'
|
||||
- ' echo "Grafana package version $version not found in repository."'
|
||||
- ' dnf repolist'
|
||||
- ' dnf list available grafana*'
|
||||
- ' exit 1'
|
||||
- fi
|
||||
- 'echo "Step 6: Verifying Grafana installation..."'
|
||||
- if rpm -q grafana | grep -q "${TAG}"; then
|
||||
- ' echo "Successfully verified Grafana version ${TAG}"'
|
||||
- if rpm -q grafana | grep -q "$verison"; then
|
||||
- ' echo "Successfully verified Grafana version $version"'
|
||||
- else
|
||||
- ' echo "Failed to verify Grafana version ${TAG}"'
|
||||
- ' echo "Failed to verify Grafana version $version"'
|
||||
- ' exit 1'
|
||||
- fi
|
||||
- echo "Verification complete."
|
||||
@@ -4255,142 +4233,6 @@ volumes:
|
||||
clone:
|
||||
retries: 3
|
||||
depends_on: []
|
||||
environment:
|
||||
EDITION: oss
|
||||
image_pull_secrets:
|
||||
- gcr
|
||||
- gar
|
||||
kind: pipeline
|
||||
name: release-test-frontend
|
||||
node:
|
||||
type: no-parallel
|
||||
platform:
|
||||
arch: amd64
|
||||
os: linux
|
||||
services: []
|
||||
steps:
|
||||
- commands:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
image: alpine:3.20.3
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- yarn install --immutable || yarn install --immutable
|
||||
depends_on: []
|
||||
image: node:20.9.0-alpine
|
||||
name: yarn-install
|
||||
- commands:
|
||||
- apk add --update git bash
|
||||
- yarn betterer ci
|
||||
depends_on:
|
||||
- yarn-install
|
||||
image: node:20.9.0-alpine
|
||||
name: betterer-frontend
|
||||
- commands:
|
||||
- yarn run ci:test-frontend
|
||||
depends_on:
|
||||
- yarn-install
|
||||
environment:
|
||||
TEST_MAX_WORKERS: 50%
|
||||
image: node:20.9.0-alpine
|
||||
name: test-frontend
|
||||
trigger:
|
||||
event:
|
||||
exclude:
|
||||
- promote
|
||||
ref:
|
||||
exclude:
|
||||
- refs/tags/*-cloud*
|
||||
include:
|
||||
- refs/tags/v*
|
||||
type: docker
|
||||
volumes:
|
||||
- host:
|
||||
path: /var/run/docker.sock
|
||||
name: docker
|
||||
---
|
||||
clone:
|
||||
retries: 3
|
||||
depends_on: []
|
||||
environment:
|
||||
EDITION: oss
|
||||
image_pull_secrets:
|
||||
- gcr
|
||||
- gar
|
||||
kind: pipeline
|
||||
name: release-test-backend
|
||||
node:
|
||||
type: no-parallel
|
||||
platform:
|
||||
arch: amd64
|
||||
os: linux
|
||||
services: []
|
||||
steps:
|
||||
- commands:
|
||||
- echo $DRONE_RUNNER_NAME
|
||||
image: alpine:3.20.3
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- '# It is required that code generated from Thema/CUE be committed and in sync
|
||||
with its inputs.'
|
||||
- '# The following command will fail if running code generators produces any diff
|
||||
in output.'
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-cue
|
||||
depends_on: []
|
||||
image: golang:1.22.7-alpine
|
||||
name: verify-gen-cue
|
||||
- commands:
|
||||
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
|
||||
- '# The following command will fail if running code generators produces any diff
|
||||
in output.'
|
||||
- apk add --update make
|
||||
- CODEGEN_VERIFY=1 make gen-jsonnet
|
||||
depends_on: []
|
||||
image: golang:1.22.7-alpine
|
||||
name: verify-gen-jsonnet
|
||||
- commands:
|
||||
- apk add --update make
|
||||
- make gen-go
|
||||
depends_on:
|
||||
- verify-gen-cue
|
||||
image: golang:1.22.7-alpine
|
||||
name: wire-install
|
||||
- commands:
|
||||
- apk add --update build-base shared-mime-info shared-mime-info-lang
|
||||
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.22.7-alpine
|
||||
name: test-backend
|
||||
- commands:
|
||||
- apk add --update build-base
|
||||
- go test -count=1 -covermode=atomic -timeout=5m -run '^TestIntegration' $(find
|
||||
./pkg -type f -name '*_test.go' -exec grep -l '^func TestIntegration' '{}' '+'
|
||||
| grep -o '\(.*\)/' | sort -u)
|
||||
depends_on:
|
||||
- wire-install
|
||||
image: golang:1.22.7-alpine
|
||||
name: test-backend-integration
|
||||
trigger:
|
||||
event:
|
||||
exclude:
|
||||
- promote
|
||||
ref:
|
||||
exclude:
|
||||
- refs/tags/*-cloud*
|
||||
include:
|
||||
- refs/tags/v*
|
||||
type: docker
|
||||
volumes:
|
||||
- host:
|
||||
path: /var/run/docker.sock
|
||||
name: docker
|
||||
---
|
||||
clone:
|
||||
retries: 3
|
||||
depends_on:
|
||||
- release-test-backend
|
||||
- release-test-frontend
|
||||
image_pull_secrets:
|
||||
- gcr
|
||||
- gar
|
||||
@@ -4480,7 +4322,7 @@ steps:
|
||||
name: identify-runner
|
||||
- commands:
|
||||
- $$ProgressPreference = "SilentlyContinue"
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/windows/grabpl.exe
|
||||
- Invoke-WebRequest https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/windows/grabpl.exe
|
||||
-OutFile grabpl.exe
|
||||
image: grafana/ci-wix:0.1.1
|
||||
name: windows-init
|
||||
@@ -4571,9 +4413,7 @@ volumes:
|
||||
---
|
||||
clone:
|
||||
retries: 3
|
||||
depends_on:
|
||||
- release-test-backend
|
||||
- release-test-frontend
|
||||
depends_on: []
|
||||
image_pull_secrets:
|
||||
- gcr
|
||||
- gar
|
||||
@@ -5282,7 +5122,7 @@ services:
|
||||
steps:
|
||||
- commands:
|
||||
- mkdir -p bin
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.50/grabpl
|
||||
- curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.0.56/grabpl
|
||||
- chmod +x bin/grabpl
|
||||
image: byrnedo/alpine-curl:0.1.8
|
||||
name: grabpl
|
||||
@@ -6074,6 +5914,6 @@ kind: secret
|
||||
name: gcr_credentials
|
||||
---
|
||||
kind: signature
|
||||
hmac: ab287005f518892bdf24954884ca270dcb511027b53c220e13de6f080883116f
|
||||
hmac: 58b776458f032819ea9981e96a9cbfe6bcc66c74b407f7c54b020c7433462816
|
||||
|
||||
...
|
||||
|
||||
8
.github/CODEOWNERS
vendored
8
.github/CODEOWNERS
vendored
@@ -43,12 +43,12 @@
|
||||
/docs/sources/dashboards/ @imatwawana
|
||||
/docs/sources/datasources/ @jdbaldry
|
||||
/docs/sources/explore/ @grafana/explore-squad @lwandz13
|
||||
/docs/sources/fundamentals @chri2547
|
||||
/docs/sources/getting-started/ @chri2547
|
||||
/docs/sources/introduction/ @chri2547
|
||||
/docs/sources/fundamentals @irenerl24
|
||||
/docs/sources/getting-started/ @irenerl24
|
||||
/docs/sources/introduction/ @irenerl24
|
||||
/docs/sources/panels-visualizations/ @imatwawana
|
||||
/docs/sources/release-notes/ @Eve832 @GrafanaWriter
|
||||
/docs/sources/setup-grafana/ @chri2547
|
||||
/docs/sources/setup-grafana/ @irenerl24
|
||||
/docs/sources/upgrade-guide/ @imatwawana
|
||||
/docs/sources/whatsnew/ @imatwawana
|
||||
|
||||
|
||||
42
CHANGELOG.md
42
CHANGELOG.md
@@ -1,3 +1,44 @@
|
||||
<!-- 11.2.2+security-01 START -->
|
||||
|
||||
# 11.2.2+security-01 (2024-10-17)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **SQL Expressions**: Fixes CVE-2024-9264
|
||||
|
||||
<!-- 11.2.2+security-01 END -->
|
||||
<!-- 11.2.2 START -->
|
||||
|
||||
# 11.2.2 (2024-10-01)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Chore:** Bump Go to 1.22.7 [#93353](https://github.com/grafana/grafana/pull/93353), [@hairyhenderson](https://github.com/hairyhenderson)
|
||||
- **Chore:** Bump Go to 1.22.7 (Enterprise)
|
||||
- **Data sources:** Hide the datasource redirection banner for users who can't interact with data sources [#93103](https://github.com/grafana/grafana/pull/93103), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Alerting:** Fix preview of silences when label name contains spaces [#93051](https://github.com/grafana/grafana/pull/93051), [@tomratcliffe](https://github.com/tomratcliffe)
|
||||
- **Alerting:** Make query wrapper match up datasource UIDs if necessary [#93114](https://github.com/grafana/grafana/pull/93114), [@tomratcliffe](https://github.com/tomratcliffe)
|
||||
- **AzureMonitor:** Deduplicate resource picker rows [#93705](https://github.com/grafana/grafana/pull/93705), [@aangelisc](https://github.com/aangelisc)
|
||||
- **AzureMonitor:** Improve resource picker efficiency [#93440](https://github.com/grafana/grafana/pull/93440), [@aangelisc](https://github.com/aangelisc)
|
||||
- **AzureMonitor:** Remove Basic Logs retention warning [#93123](https://github.com/grafana/grafana/pull/93123), [@aangelisc](https://github.com/aangelisc)
|
||||
- **CloudWatch:** Fix segfault when migrating legacy queries [#93544](https://github.com/grafana/grafana/pull/93544), [@iwysiu](https://github.com/iwysiu)
|
||||
- **Correlations:** Limit access to correlations page to users who can access Explore [#93676](https://github.com/grafana/grafana/pull/93676), [@ifrost](https://github.com/ifrost)
|
||||
- **DashboardScene:** Fix broken error handling and error rendering [#93690](https://github.com/grafana/grafana/pull/93690), [@torkelo](https://github.com/torkelo)
|
||||
- **Plugins:** Avoid returning 404 for `AutoEnabled` apps [#93488](https://github.com/grafana/grafana/pull/93488), [@wbrowne](https://github.com/wbrowne)
|
||||
|
||||
<!-- 11.2.2 END -->
|
||||
<!-- 11.2.1+security-01 START -->
|
||||
|
||||
# 11.2.1+security-01 (2024-10-17)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **SQL Expressions**: Fixes CVE-2024-9264
|
||||
|
||||
<!-- 11.2.1+security-01 END -->
|
||||
<!-- 11.2.1 START -->
|
||||
|
||||
# 11.2.1 (2024-09-26)
|
||||
@@ -21,6 +62,7 @@
|
||||
- **Reporting:** Disable dashboardSceneSolo when rendering PDFs the old way (Enterprise)
|
||||
- **Templating:** Fix searching non-latin template variables [#92893](https://github.com/grafana/grafana/pull/92893), [@leeoniya](https://github.com/leeoniya)
|
||||
- **TutorialCard:** Fix link to tutorial not opening [#92647](https://github.com/grafana/grafana/pull/92647), [@eledobleefe](https://github.com/eledobleefe)
|
||||
- **Alerting:** Fixed CVE-2024-8118.
|
||||
|
||||
### Plugin development fixes & changes
|
||||
|
||||
|
||||
@@ -406,6 +406,9 @@ csrf_always_check = false
|
||||
# Comma-separated list of plugins ids that won't be loaded inside the frontend sandbox
|
||||
disable_frontend_sandbox_for_plugins = grafana-incident-app
|
||||
|
||||
# Comma-separated list of paths for POST/PUT URL in actions. Empty will allow anything that is not on the same origin
|
||||
actions_allow_post_url =
|
||||
|
||||
[security.encryption]
|
||||
# Defines the time-to-live (TTL) for decrypted data encryption keys stored in memory (cache).
|
||||
# Please note that small values may cause performance issues due to a high frequency decryption operations.
|
||||
@@ -1745,6 +1748,9 @@ ha_engine_address = "127.0.0.1:6379"
|
||||
# ha_engine_password allows setting an optional password to authenticate with the engine
|
||||
ha_engine_password = ""
|
||||
|
||||
# ha_prefix is a prefix for keys in the HA engine. It's used to separate keys for different Grafana instances.
|
||||
ha_prefix =
|
||||
|
||||
#################################### Grafana Image Renderer Plugin ##########################
|
||||
[plugin.grafana-image-renderer]
|
||||
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
|
||||
|
||||
@@ -411,6 +411,9 @@
|
||||
# Comma-separated list of plugins ids that won't be loaded inside the frontend sandbox
|
||||
;disable_frontend_sandbox_for_plugins =
|
||||
|
||||
# Comma-separated list of paths for POST/PUT URL in actions. Empty will allow anything that is not on the same origin
|
||||
;actions_allow_post_url =
|
||||
|
||||
[security.encryption]
|
||||
# Defines the time-to-live (TTL) for decrypted data encryption keys stored in memory (cache).
|
||||
# Please note that small values may cause performance issues due to a high frequency decryption operations.
|
||||
@@ -1705,6 +1708,9 @@ timeout = 30s
|
||||
# ha_engine_password allows setting an optional password to authenticate with the engine
|
||||
;ha_engine_password = ""
|
||||
|
||||
# ha_prefix is a prefix for keys in the HA engine. It's used to separate keys for different Grafana instances.
|
||||
;ha_prefix =
|
||||
|
||||
#################################### Grafana Image Renderer Plugin ##########################
|
||||
[plugin.grafana-image-renderer]
|
||||
# Instruct headless browser instance to use a default timezone when not provided by Grafana, e.g. when rendering panel image of alert.
|
||||
|
||||
@@ -36,6 +36,64 @@ Each template is evaluated whenever the alert rule is evaluated, and is evaluate
|
||||
Extra whitespace in label templates can break matches with notification policies.
|
||||
{{% /admonition %}}
|
||||
|
||||
## Variables
|
||||
|
||||
In Grafana templating, the `$` and `.` symbols are used to reference variables and their properties. You can reference variables directly in your alert rule definitions using the `$` symbol followed by the variable name. Similarly, you can access properties of variables using the dot (`.`) notation within alert rule definitions.
|
||||
|
||||
The following variables are available to you when templating labels and annotations:
|
||||
|
||||
### The labels variable
|
||||
|
||||
The `$labels` variable contains all labels from the query. For example, suppose you have a query that returns CPU usage for all of your servers, and you have an alert rule that fires when any of your servers have exceeded 80% CPU usage for the last 5 minutes. You want to add a summary annotation to the alert that tells you which server is experiencing high CPU usage. With the `$labels` variable you can write a template that prints a human-readable sentence such as:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes
|
||||
```
|
||||
|
||||
> If you are using a classic condition then `$labels` will not contain any labels from the query. Classic conditions discard these labels in order to enforce uni-dimensional behavior (at most one alert per alert rule). If you want to use labels from the query in your template then use the example [here](#print-all-labels-from-a-classic-condition).
|
||||
|
||||
### The value variable
|
||||
|
||||
The `$value` variable is a string containing the labels and values of all instant queries; threshold, reduce and math expressions, and classic conditions in the alert rule. It does not contain the results of range queries, as these can return anywhere from 10s to 10,000s of rows or metrics. If it did, for especially large queries a single alert could use 10s of MBs of memory and Grafana would run out of memory very quickly.
|
||||
|
||||
To print the `$value` variable in the summary you would write something like this:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ $value }}
|
||||
```
|
||||
|
||||
And would look something like this:
|
||||
|
||||
```
|
||||
CPU usage for instance1 has exceeded 80% for the last 5 minutes: [ var='A' labels={instance=instance1} value=81.234 ]
|
||||
```
|
||||
|
||||
Here `var='A'` refers to the instant query with Ref ID A, `labels={instance=instance1}` refers to the labels, and `value=81.234` refers to the average CPU usage over the last 5 minutes.
|
||||
|
||||
If you want to print just some of the string instead of the full string then use the `$values` variable. It contains the same information as `$value`, but in a structured table, and is much easier to use then writing a regular expression to match just the text you want.
|
||||
|
||||
### The values variable
|
||||
|
||||
The `$values` variable is a table containing the labels and floating point values of all instant queries and expressions, indexed by their Ref IDs.
|
||||
|
||||
To print the value of the instant query with Ref ID A:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ index $values "A" }}
|
||||
```
|
||||
|
||||
For example, given an alert with the labels `instance=server1` and an instant query with the value `81.2345`, this would print:
|
||||
|
||||
```
|
||||
CPU usage for instance1 has exceeded 80% for the last 5 minutes: 81.2345
|
||||
```
|
||||
|
||||
If the query in Ref ID A is a range query rather than an instant query then add a reduce expression with Ref ID B and replace `(index $values "A")` with `(index $values "B")`:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ index $values "B" }}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples attempt to show the most common use-cases we have seen for templates. You can use these examples verbatim, or adapt them as necessary for your use case. For more information on how to write text/template refer see [the beginner's guide to alert notification templates in Grafana](https://grafana.com/blog/2023/04/05/grafana-alerting-a-beginners-guide-to-templating-alert-notifications/).
|
||||
@@ -216,62 +274,6 @@ B2: 84.5678
|
||||
B3: 95.6789
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
The following variables are available to you when templating labels and annotations:
|
||||
|
||||
### The labels variable
|
||||
|
||||
The `$labels` variable contains all labels from the query. For example, suppose you have a query that returns CPU usage for all of your servers, and you have an alert rule that fires when any of your servers have exceeded 80% CPU usage for the last 5 minutes. You want to add a summary annotation to the alert that tells you which server is experiencing high CPU usage. With the `$labels` variable you can write a template that prints a human-readable sentence such as:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes
|
||||
```
|
||||
|
||||
> If you are using a classic condition then `$labels` will not contain any labels from the query. Classic conditions discard these labels in order to enforce uni-dimensional behavior (at most one alert per alert rule). If you want to use labels from the query in your template then use the example [here](#print-all-labels-from-a-classic-condition).
|
||||
|
||||
### The value variable
|
||||
|
||||
The `$value` variable is a string containing the labels and values of all instant queries; threshold, reduce and math expressions, and classic conditions in the alert rule. It does not contain the results of range queries, as these can return anywhere from 10s to 10,000s of rows or metrics. If it did, for especially large queries a single alert could use 10s of MBs of memory and Grafana would run out of memory very quickly.
|
||||
|
||||
To print the `$value` variable in the summary you would write something like this:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ $value }}
|
||||
```
|
||||
|
||||
And would look something like this:
|
||||
|
||||
```
|
||||
CPU usage for instance1 has exceeded 80% for the last 5 minutes: [ var='A' labels={instance=instance1} value=81.234 ]
|
||||
```
|
||||
|
||||
Here `var='A'` refers to the instant query with Ref ID A, `labels={instance=instance1}` refers to the labels, and `value=81.234` refers to the average CPU usage over the last 5 minutes.
|
||||
|
||||
If you want to print just some of the string instead of the full string then use the `$values` variable. It contains the same information as `$value`, but in a structured table, and is much easier to use then writing a regular expression to match just the text you want.
|
||||
|
||||
### The values variable
|
||||
|
||||
The `$values` variable is a table containing the labels and floating point values of all instant queries and expressions, indexed by their Ref IDs.
|
||||
|
||||
To print the value of the instant query with Ref ID A:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ index $values "A" }}
|
||||
```
|
||||
|
||||
For example, given an alert with the labels `instance=server1` and an instant query with the value `81.2345`, this would print:
|
||||
|
||||
```
|
||||
CPU usage for instance1 has exceeded 80% for the last 5 minutes: 81.2345
|
||||
```
|
||||
|
||||
If the query in Ref ID A is a range query rather than an instant query then add a reduce expression with Ref ID B and replace `(index $values "A")` with `(index $values "B")`:
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ index $values "B" }}
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
The following functions are available to you when templating labels and annotations:
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- ../../contact-points/message-templating/ # /docs/grafana/<GRAFANA_VERSION>/alerting/contact-points/message-templating/
|
||||
- ../../alert-rules/message-templating/ # /docs/grafana/<GRAFANA_VERSION>/alerting/alert-rules/message-templating/
|
||||
- ../../unified-alerting/message-templating/ # /docs/grafana/<GRAFANA_VERSION>/alerting/unified-alerting/message-templating/
|
||||
canonical: https://grafana.com/docs/grafana/latest/alerting/fundamentals/notifications/templates/
|
||||
description: Learn about templates
|
||||
keywords:
|
||||
- grafana
|
||||
- alerting
|
||||
- guide
|
||||
- contact point
|
||||
- templating
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
- oss
|
||||
title: Templates
|
||||
weight: 115
|
||||
refs:
|
||||
variables-label-annotation:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/alerting-rules/templating-labels-annotations/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/templating-labels-annotations/
|
||||
---
|
||||
|
||||
# Templates
|
||||
|
||||
Use templating to customize, format, and reuse alert notification messages. Create more flexible and informative alert notification messages by incorporating dynamic content, such as metric values, labels, and other contextual information.
|
||||
|
||||
In Grafana, there are two ways to template your alert notification messages:
|
||||
|
||||
1. Labels and annotations
|
||||
|
||||
- Template labels and annotations in alert rules.
|
||||
- Labels and annotations contain information about an alert.
|
||||
- Labels are used to differentiate an alert from all other alerts, while annotations are used to add additional information to an existing alert.
|
||||
|
||||
2. Notification templates
|
||||
|
||||
- Template notifications in contact points.
|
||||
- Add notification templates to contact points for reuse and consistent messaging in your notifications.
|
||||
- Use notification templates to change the title, message, and format of the message in your notifications.
|
||||
|
||||
This diagram illustrates the entire process of templating, from the creation of labels and annotations in alert rules or notification templates in contact points, to what they look like when exported and applied in your alert notification messages.
|
||||
|
||||
{{< figure src="/media/docs/alerting/grafana-templating-diagram-2.jpg" max-width="1200px" caption="How Templating works" >}}
|
||||
|
||||
In this diagram:
|
||||
|
||||
- **Monitored Application**: A web server, database, or any other service generating metrics. For example, it could be an NGINX server providing metrics about request rates, response times, and so on.
|
||||
- **Prometheus**: Prometheus collects metrics from the monitored application. For example, it might scrape metrics from the NGINX server, including labels like instance (the server hostname) and job (the service name).
|
||||
- **Grafana**: Grafana queries Prometheus to retrieve metrics data. For example, you might create an alert rule to monitor NGINX request rates over time, and template labels or annotations based on the instance label.
|
||||
- **Alertmanager**: Part of the Prometheus ecosystem, Alertmanager handles alert notifications. For example, if the request rate exceeds a certain threshold on a particular NGINX server, Alertmanager can send an alert notification to, for example, Slack or email, including the server name and the exceeded threshold (the instance label will be interpolated, and the actual server name will appear in the alert notification).
|
||||
- **Alert notification**: When an alert rule condition is met, Alertmanager sends a notification to various channels such as Slack, Grafana OnCall, etc. These notifications can include information from the labels associated with the alerting rule. For example, if an alert triggers due to high CPU usage on a specific server, the notification message can include details like server name (instance label), disk usage percentage, and the threshold that was exceeded.
|
||||
|
||||
## Labels and annotations
|
||||
|
||||
Labels and annotations contain information about an alert. Labels are used to differentiate an alert from all other alerts, while annotations are used to add additional information to an existing alert.
|
||||
|
||||
### Template labels
|
||||
|
||||
Label templates are applied in the alert rule itself (i.e. in the Configure labels and notifications section of an alert).
|
||||
|
||||
{{<admonition type="note">}}
|
||||
Think about templating labels when you need to improve or change how alerts are uniquely identified. This is especially helpful if the labels you get from your query aren't detailed enough. Keep in mind that it's better to keep long sentences for summaries and descriptions. Also, avoid using the query's value in labels because it may result in the creation of many alerts when you actually only need one.
|
||||
{{</admonition>}}
|
||||
|
||||
Templating can be applied by using variables and functions. These variables can represent dynamic values retrieved from your data queries.
|
||||
|
||||
{{<admonition type="note">}}
|
||||
In Grafana templating, the $ and . symbols are used to reference variables and their properties. You can reference variables directly in your alert rule definitions using the $ symbol followed by the variable name. Similarly, you can access properties of variables using the dot (.) notation within alert rule definitions.
|
||||
{{</admonition>}}
|
||||
|
||||
Here are some commonly used built-in [variables](ref:variables-label-annotation) to interact with the name and value of labels in Grafana alerting:
|
||||
|
||||
- The `$labels` variable, which contains all labels from the query.
|
||||
|
||||
For example, let's say you have an alert rule that triggers when the CPU usage exceeds a certain threshold. You want to create annotations that provide additional context when this alert is triggered, such as including the specific server that experienced the high CPU usage.
|
||||
|
||||
The host {{ index $labels "instance" }} has exceeded 80% CPU usage for the last 5 minutes
|
||||
|
||||
The outcome of this template would print:
|
||||
|
||||
The host instance 1 has exceeded 80% CPU usage for the last 5 minutes
|
||||
|
||||
- The `$value` variable, which is a string containing the labels and values of all instant queries; threshold, reduce and math expressions, and classic conditions in the alert rule.
|
||||
|
||||
In the context of the previous example, $value variable would write something like this:
|
||||
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ $value }}
|
||||
|
||||
The outcome of this template would print:
|
||||
|
||||
CPU usage for instance1 has exceeded 80% for the last 5 minutes: [ var='A' labels={instance=instance1} value=81.234 ]
|
||||
|
||||
- The `$values` variable is a table containing the labels and floating point values of all instant queries and expressions, indexed by their Ref IDs (i.e. the id that identifies the query or expression. By default the Red ID of the query is “A”).
|
||||
|
||||
Given an alert with the labels instance=server1 and an instant query with the value 81.2345, would write like this:
|
||||
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes: {{ index $values "A" }}
|
||||
|
||||
And it would print:
|
||||
|
||||
CPU usage for instance1 has exceeded 80% for the last 5 minutes: 81.2345
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
Extra whitespace in label templates can break matches with notification policies.
|
||||
{{% /admonition %}}
|
||||
|
||||
### Template annotations
|
||||
|
||||
Both labels and annotations have the same structure: a set of named values; however their intended uses are different. The purpose of annotations is to add additional information to existing alerts.
|
||||
|
||||
There are a number of suggested annotations in Grafana such as `description`, `summary`, `runbook_url`, `dashboardUId` and `panelId`. Like labels, annotations must have a name, and their value can contain a combination of text and template code that is evaluated when an alert is fired.
|
||||
|
||||
Here is an example of templating an annotation in the context of an alert rule. The text/template is added into the Add annotations section.
|
||||
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% for the last 5 minutes
|
||||
|
||||
The outcome of this template would print
|
||||
|
||||
CPU usage for Instance 1 has exceeded 80% for the last 5 minutes
|
||||
|
||||
### Template notifications
|
||||
|
||||
Notification templates represent the alternative approach to templating designed for reusing templates. Notifications are messages to inform users about events or conditions triggered by alerts. You can create reusable notification templates to customize the content and format of alert notifications. Variables, labels, or other context-specific details can be added to the templates to dynamically insert information like metric values.
|
||||
|
||||
Here is an example of a notification template:
|
||||
|
||||
```go
|
||||
{{ define "alerts.message" -}}
|
||||
{{ if .Alerts.Firing -}}
|
||||
{{ len .Alerts.Firing }} firing alert(s)
|
||||
{{ template "alerts.summarize" .Alerts.Firing }}
|
||||
{{- end }}
|
||||
{{- if .Alerts.Resolved -}}
|
||||
{{ len .Alerts.Resolved }} resolved alert(s)
|
||||
{{ template "alerts.summarize" .Alerts.Resolved }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "alerts.summarize" -}}
|
||||
{{ range . -}}
|
||||
- {{ index .Annotations "summary" }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
This is the message you would receive in your contact point:
|
||||
|
||||
1 firing alert(s)
|
||||
- The database server db1 has exceeded 75% of available disk space. Disk space used is 76%, please resize the disk size within the next 24 hours
|
||||
|
||||
1 resolved alert(s)
|
||||
- The web server web1 has been responding to 5% of HTTP requests with 5xx errors for the last 5 minutes
|
||||
|
||||
Once the template is created, you need to make reference to it in your **Contact point** (in the Optional `[contact point]` settings) .
|
||||
|
||||
{{<admonition type="note">}}
|
||||
It's not recommended to include individual alert information within notification templates. Instead, it's more effective to incorporate such details within the rule using labels and annotations.
|
||||
{{</admonition>}}
|
||||
187
docs/sources/alerting/fundamentals/templates.md
Normal file
187
docs/sources/alerting/fundamentals/templates.md
Normal file
@@ -0,0 +1,187 @@
|
||||
---
|
||||
aliases:
|
||||
- ../fundamentals/notifications/templates/ # /docs/grafana/<GRAFANA_VERSION>/alerting/fundamentals/notifications/templates/
|
||||
- ../contact-points/message-templating/ # /docs/grafana/<GRAFANA_VERSION>/alerting/contact-points/message-templating/
|
||||
- ../alert-rules/message-templating/ # /docs/grafana/<GRAFANA_VERSION>/alerting/alert-rules/message-templating/
|
||||
- ../unified-alerting/message-templating/ # /docs/grafana/<GRAFANA_VERSION>/alerting/unified-alerting/message-templating/
|
||||
canonical: https://grafana.com/docs/grafana/latest/alerting/fundamentals/notifications/templates/
|
||||
description: Use templating to customize, format, and reuse alert notification messages. Create more flexible and informative alert notification messages by incorporating dynamic content, such as metric values, labels, and other contextual information.
|
||||
keywords:
|
||||
- grafana
|
||||
- alerting
|
||||
- guide
|
||||
- contact point
|
||||
- templating
|
||||
labels:
|
||||
products:
|
||||
- cloud
|
||||
- enterprise
|
||||
- oss
|
||||
title: Templates
|
||||
meta_image: /media/docs/alerting/how-notification-templates-works.png
|
||||
weight: 115
|
||||
refs:
|
||||
labels:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/fundamentals/alert-rules/annotation-label/#labels
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/annotation-label/#labels
|
||||
annotations:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/fundamentals/alert-rules/annotation-label/#annotations
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/annotation-label/#annotations
|
||||
templating-labels-annotations:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/alerting-rules/templating-labels-annotations/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/templating-labels-annotations/
|
||||
notification-message-reference:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/configure-notifications/template-notifications/reference/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/reference/
|
||||
notification-messages:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/configure-notifications/template-notifications/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/
|
||||
create-notification-templates:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/alerting/configure-notifications/template-notifications/create-notification-templates/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/create-notification-templates/
|
||||
---
|
||||
|
||||
# Templates
|
||||
|
||||
Use templating to customize, format, and reuse alert notification messages. Create more flexible and informative alert notification messages by incorporating dynamic content, such as metric values, labels, and other contextual information.
|
||||
|
||||
In Grafana, you have various options to template your alert notification messages:
|
||||
|
||||
1. [Alert rule annotations](#template-annotations)
|
||||
|
||||
- Annotations add extra information, like `summary` and `description`, to alert instances for notification messages.
|
||||
- Template annotations to display query values that are meaningful to the alert, for example, the server name or the threshold query value.
|
||||
|
||||
1. [Alert rule labels](#template-labels)
|
||||
|
||||
- Labels are used to differentiate an alert instance from all other alert instances.
|
||||
- Template labels to add an additional label based on a query value, or when the labels from the query are incomplete or not descriptive enough.
|
||||
|
||||
1. [Notification templates](#template-notifications)
|
||||
- Notification templates are used by contact points for consistent messaging in notification titles and descriptions.
|
||||
- Template notifications when you want to customize the appearance and information of your notifications.
|
||||
- Avoid using notification templates to add extra information to alert instances—use annotations instead.
|
||||
|
||||
This diagram illustrates the entire templating process, from querying labels and templating the alert summary and notification to the final alert notification message.
|
||||
|
||||
{{< figure src="/media/docs/alerting/how-notification-templates-works.png" max-width="1200px" caption="How templating works" >}}
|
||||
|
||||
In this diagram:
|
||||
|
||||
1. The alert rule query returns `12345`, along with the values of the `instance` and `job` labels.
|
||||
1. This query result breaches the alert rule condition, firing the alert instance.
|
||||
1. The alert instance generates an annotation summary, defined by the template used in the alert rule summary. In this case, it displays the value of the `instance` label: `server1`.
|
||||
1. The Alertmanager receives the firing alert instance, including the final annotation summary, and determines the contact point that will process the alert.
|
||||
1. The Alertmanager uses the contact point's notification template to format the message, then sends the notification to the configured destination(s)—an email address.
|
||||
|
||||
## Template annotations
|
||||
|
||||
[Annotations](ref:annotations) can be defined in the alert rule to add extra information to alert instances.
|
||||
|
||||
When creating an alert rule, Grafana suggests several optional annotations, such as `description`, `summary`, `runbook_url`, `dashboardUId` and `panelId`, which help identify and respond to alerts. You can also create custom annotations.
|
||||
|
||||
Annotations are key-value pairs, and their values can contain a combination of text and template code that is evaluated when the alert fires.
|
||||
|
||||
Annotations can contain plain text, but you should template annotations if you need to display query values that are relevant to the alert, for example:
|
||||
|
||||
- Show the query value that triggers the alert.
|
||||
- Include labels returned by the query that identify the alert.
|
||||
- Format the annotation message depending on a query value.
|
||||
|
||||
Here’s an example of templating an annotation, which explains where and why the alert was triggered. In this case, the alert triggers when CPU usage exceeds a threshold, and the `summary` annotation provides the relevant details.
|
||||
|
||||
```
|
||||
CPU usage for {{ index $labels "instance" }} has exceeded 80% ({{ index $values "A" }}) for the last 5 minutes.
|
||||
```
|
||||
|
||||
The outcome of this template would be:
|
||||
|
||||
```
|
||||
CPU usage for Instance 1 has exceeded 80% (81.2345) for the last 5 minutes.
|
||||
```
|
||||
|
||||
Implement annotations that provide meaningful information to respond to your alerts. Annotations are displayed in the Grafana alert detail view and are included by default in notifications.
|
||||
|
||||
For more details on how to template annotations, refer to [Template annotations and labels](ref:templating-labels-annotations).
|
||||
|
||||
## Template labels
|
||||
|
||||
[Labels](ref:labels) are used to differentiate one alert instance from all other alert instances, as the set of labels uniquely identifies an alert instance. Notification policies and silences use labels to handle alert instances.
|
||||
|
||||
Template labels when you need to improve or change how alerts are uniquely identified. This is helpful if the labels you get from your query aren't detailed enough.
|
||||
|
||||
Here’s an example of templating a `severity` label based on the query value:
|
||||
|
||||
```
|
||||
{{ if (gt $values.A.Value 90.0) -}}
|
||||
critical
|
||||
{{ else if (gt $values.A.Value 80.0) -}}
|
||||
high
|
||||
{{ else if (gt $values.A.Value 60.0) -}}
|
||||
medium
|
||||
{{ else -}}
|
||||
low
|
||||
{{- end }}
|
||||
```
|
||||
|
||||
Avoid using query values in labels, as this may result in the creation of numerous alerts when only one is needed. Use annotation to inform about the query value instead.
|
||||
|
||||
For more details on how to template labels, refer to [Template annotations and labels](ref:templating-labels-annotations).
|
||||
|
||||
## Template notifications
|
||||
|
||||
[Notification templates](ref:notification-messages) allow you to customize the content of your notifications, such as the subject of an email or the body of a Slack message.
|
||||
|
||||
Notification templates differ from templating annotations and labels in the following ways:
|
||||
|
||||
- Notification templates are assigned to the **Contact point**, rather than the alert rule.
|
||||
- If not specified, the contact point uses a default template that includes relevant alert information.
|
||||
- You can create reusable notification templates and reference them in other templates.
|
||||
- The same template can be shared across multiple contact points, making it easier to maintain and ensuring consistency.
|
||||
- While both annotation/label templates and notification templates use the same templating language, the available variables and functions differ. For more details, refer to the [notification template reference](ref:notification-message-reference) and [annotation/label template reference](ref:templating-labels-annotations).
|
||||
- Notification templates should not be used to add additional information to individual alerts—use annotations for that purpose.
|
||||
|
||||
Here is an example of a notification template that summarizes all firing and resolved alerts in a notification group:
|
||||
|
||||
```
|
||||
{{ define "alerts.message" -}}
|
||||
{{ if .Alerts.Firing -}}
|
||||
{{ len .Alerts.Firing }} firing alert(s)
|
||||
{{ template "alerts.summarize" .Alerts.Firing }}
|
||||
{{- end }}
|
||||
{{- if .Alerts.Resolved -}}
|
||||
{{ len .Alerts.Resolved }} resolved alert(s)
|
||||
{{ template "alerts.summarize" .Alerts.Resolved }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{ define "alerts.summarize" -}}
|
||||
{{ range . -}}
|
||||
- {{ index .Annotations "summary" }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
The notification message to the contact point would look like this:
|
||||
|
||||
```
|
||||
1 firing alert(s)
|
||||
- The database server db1 has exceeded 75% of available disk space. Disk space used is 76%, please resize the disk size within the next 24 hours.
|
||||
|
||||
1 resolved alert(s)
|
||||
- The web server web1 has been responding to 5% of HTTP requests with 5xx errors for the last 5 minutes.
|
||||
```
|
||||
|
||||
For instructions on creating and using notification templates, refer to [Create notification templates.](ref:create-notification-templates)
|
||||
@@ -39,6 +39,11 @@ refs:
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
permission:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/
|
||||
role-based-access-control:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/
|
||||
@@ -109,7 +114,7 @@ For information about recent improvements to the reporting UI, refer to [Grafana
|
||||
|
||||
## Access control
|
||||
|
||||
When [RBAC](ref:rbac) is enabled, you need to have the relevant [Permissions][] to create and manage reports.
|
||||
When [RBAC](ref:rbac) is enabled, you need to have the relevant [Permissions](ref:permission) to create and manage reports.
|
||||
|
||||
## Create or update a report
|
||||
|
||||
|
||||
@@ -171,6 +171,8 @@ The following options are the same for both **Builder** and **Code** mode:
|
||||
|
||||
- **Line limit** -Defines the upper limit for the number of log lines returned by a query. The default is `1000`
|
||||
|
||||
- **Direction** - Determines the search order. **Backward** is a backward search starting at the end of the time range. **Forward** is a forward search starting at the beginning of the time range. The default is **Backward**
|
||||
|
||||
- **Step** Sets the step parameter of Loki metrics queries. The default value equals to the value of `$__interval` variable, which is calculated using the time range and the width of the graph (the number of pixels).
|
||||
|
||||
- **Resolution** Deprecated. Sets the step parameter of Loki metrics range queries. With a resolution of `1/1`, each pixel corresponds to one data point. `1/2` retrieves one data point for every other pixel, `1/10` retrieves one data point per 10 pixels, and so on. Lower resolutions perform better.
|
||||
|
||||
@@ -73,7 +73,7 @@ For instructions on how to add a data source to Grafana, refer to the [administr
|
||||
Only users with the organization administrator role can add data sources.
|
||||
Administrators can also [configure the data source via YAML](#provision-the-data-source) with Grafana's provisioning system.
|
||||
|
||||
{{< docs/play title="MySQL: Cities of the World Sample Data Set" url="https://play.grafana.org/d/8JOvPQr7k/" >}}
|
||||
{{< docs/play title="MySQL Overview" url="https://play.grafana.org/d/edyh1ib7db6rkb/mysql-overview" >}}
|
||||
|
||||
## Configure the data source
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ For instructions on how to add a data source to Grafana, refer to the [administr
|
||||
Only users with the organization administrator role can add data sources.
|
||||
Administrators can also [configure the data source via YAML](#provision-the-data-source) with Grafana's provisioning system.
|
||||
|
||||
{{< docs/play title="PostgreSQL Overview" url="https://play.grafana.org/d/ddvpgdhiwjvuod/postgresql-overview" >}}
|
||||
|
||||
## PostgreSQL settings
|
||||
|
||||
To configure basic settings for the data source, complete the following steps:
|
||||
|
||||
@@ -155,7 +155,7 @@ We also bundle a dashboard within Grafana so you can start viewing your metrics
|
||||
1. Navigate to the data source's [configuration page](ref:configure-prometheus-data-source).
|
||||
1. Select the **Dashboards** tab.
|
||||
|
||||
This displays dashboards for Grafana and Prometheus.
|
||||
This displays dashboards for Grafana and Prometheus.
|
||||
|
||||
1. Select **Import** for the dashboard to import.
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ To use profiling data, you should:
|
||||
|
||||
- [Configure your application to send profiles](/docs/pyroscope/<PYROSCOPE_VERSION>/configure-client/)
|
||||
- [Configure the Grafana Pyroscope data source](./configure-pyroscope-data-source/).
|
||||
- [View and query profiling data in Explore](./query-profile-data/)
|
||||
- [View and query profiling data using Explore Profiles or the query editor ](./query-profile-data/)
|
||||
|
||||
## Integrate profiles into dashboards
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
description: Use the query editor to explore your Pyroscope data.
|
||||
description: Explore your profiling data using Explore Profiles or the Pyroscope query editor.
|
||||
keywords:
|
||||
- query
|
||||
- profiling
|
||||
@@ -28,6 +28,16 @@ refs:
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/explore/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/explore/
|
||||
explore-profiles:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/explore/simplified-exploration/profiles/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/simplified-exploration/profiles/
|
||||
explore-profile-install:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/explore/simplified-exploration/profiles/access/
|
||||
- pattern: /docs/grafana-cloud/
|
||||
destination: /docs/grafana-cloud/visualizations/simplified-exploration/profiles/access/
|
||||
provisioning-data-sources:
|
||||
- pattern: /docs/grafana/
|
||||
destination: /docs/grafana/<GRAFANA_VERSION>/administration/provisioning/#datasources
|
||||
@@ -37,8 +47,64 @@ refs:
|
||||
|
||||
# Query profile data
|
||||
|
||||
You can query your profile data using the built-in data source query editor or you can use the open source Grafana Explore Profiles app.
|
||||
|
||||
## Explore Profiles
|
||||
|
||||
[Explore Profiles](ref:explore-profiles) is a native Grafana application designed to integrate seamlessly with Pyroscope, the open source continuous profiling platform, providing a smooth, queryless experience for browsing and analyzing profiling data.
|
||||
|
||||
You can use Explore Profiles in Grafana Cloud or in your own Grafana instance.
|
||||
For more information, refer to [Access or install Explore Profiles](ref:explore-profiles-install).
|
||||
|
||||
### Use cases
|
||||
|
||||
There are several different modes for viewing, analyzing, and comparing profiling data.
|
||||
|
||||
The main use cases are the following:
|
||||
|
||||
- Proactive: Cutting costs, addressing latency issues, or optimizing memory usage for applications
|
||||
- Reactive: Resolving incidents with line-level accuracy or debugging active latency/memory issues
|
||||
|
||||
Explore Profiles provides an intuitive interface to specifically support these use cases.
|
||||
You get a holistic view of all of your services and how they're functioning, but also the ability to drill down for more targeted root cause analysis.
|
||||
|
||||
Explore Profiles offers a convenient platform to analyze profiles and get insights that are impossible to get from using other traditional signals like logs, metrics, or tracing.
|
||||
|
||||
{{< youtube id="x9aPw_CbIQc" >}}
|
||||
|
||||
{{< docs/play title="the Grafana Play site" url="https://play.grafana.org/a/grafana-pyroscope-app/profiles-explorer" >}}
|
||||
|
||||
### Continuous profiling
|
||||
|
||||
While code profiling has been a long-standing practice, continuous profiling represents a modern and more advanced approach to performance monitoring.
|
||||
|
||||
This technique adds two critical dimensions to traditional profiles:
|
||||
|
||||
Time
|
||||
: Profiling data is collected _continuously_, providing a time-centric view that allows querying performance data from any point in the past.
|
||||
|
||||
Metadata
|
||||
: Profiles are enriched with metadata, adding contextual depth to the performance data.
|
||||
|
||||
These dimensions, coupled with the detailed nature of performance profiles, make continuous profiling a uniquely valuable tool.
|
||||
|
||||
### Flame graphs
|
||||
|
||||
<!-- vale Grafana.We = NO -->
|
||||
|
||||
Flame graphs help you visualize resource allocation and performance bottlenecks, and you even get suggested recommendations and performance fixes via AI-driven flame graph analysis, as well as line-level insights from our GitHub integration.
|
||||
|
||||
<!-- vale Grafana.We = YES -->
|
||||
|
||||
On views with a flame graph, you can use **Explain flame graph** to provide an AI flame graph analysis that explains the performance bottleneck, root cause, and recommended fix.
|
||||
For more information, refer to [Flame graph AI](https://grafana.com/docs/grafana-cloud/monitor-applications/profiles/flamegraph-ai/).
|
||||
|
||||
## Pyroscope query editor
|
||||
|
||||
The Pyroscope data source query editor gives you access to a profile type selector, a label selector, and collapsible options.
|
||||
|
||||
Like Explore Profiles, the query editor also provides a flame graph to visualize data.
|
||||
|
||||

|
||||
|
||||
To access the query editor:
|
||||
@@ -52,9 +118,9 @@ To access the query editor:
|
||||
{{< figure src="/media/docs/pyroscope/query-editor/select-profile.png" class="docs-image--no-shadow" max-width="450px" caption="Profile selector" >}}
|
||||
|
||||
1. Use the labels selector input to filter by labels. Pyroscope uses similar syntax to Prometheus to filter labels.
|
||||
Refer to [Pyroscope documentation](https://grafana.com/docs/pyroscope/latest/) for available operators and syntax.
|
||||
Refer to [Pyroscope documentation](https://grafana.com/docs/pyroscope/<PYROSCOPE_VERSION>/) for available operators and syntax.
|
||||
|
||||
While the label selector can be left empty to query all profiles without filtering by labels, the profile type or app must be selected for the query to be valid.
|
||||
While the label selector can be left empty to query all profiles without filtering by labels, you must select a profile type or app for the query to be valid.
|
||||
|
||||
Grafana doesn't show any data if the profile type or app isn’t selected when a query runs.
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ You can use a bar gauge visualization when you need to show:
|
||||
- Attendance
|
||||
- Process completion rates
|
||||
|
||||
## Configure a bar gauge visualization
|
||||
|
||||
The following video shows you how to create and configure a bar gauge visualization:
|
||||
|
||||
{{< youtube id="7PhDysObEXA" >}}
|
||||
|
||||
{{< docs/play title="Bar Gauge" url="https://play.grafana.org/d/vmie2cmWz/" >}}
|
||||
|
||||
## Supported data formats
|
||||
|
||||
@@ -51,7 +51,7 @@ refs:
|
||||
|
||||
Geomaps allow you to view and customize the world map using geospatial data. It's the ideal visualization if you have data that includes location information and you want to see it displayed in a map.
|
||||
|
||||
You can configure and overlay [map layers](#types), like heatmaps and networks, and blend included basemaps or your own custom maps. This helps you to easily focus on the important location-based characteristics of the data.
|
||||
You can configure and overlay [map layers](#layer-type), like heatmaps and networks, and blend included basemaps or your own custom maps. This helps you to easily focus on the important location-based characteristics of the data.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-example-8-1-0.png" max-width="1200px" alt="Geomap visualization" >}}
|
||||
|
||||
@@ -141,42 +141,42 @@ The other location types— airport codes or US state codes—aren't aut
|
||||
|
||||
If you want to use other codes or give the field a custom name, you can follow the steps in the [Location mode](#location-mode) section.
|
||||
|
||||
## Panel options
|
||||
## Configuration options
|
||||
|
||||
### Panel options
|
||||
|
||||
{{< docs/shared lookup="visualizations/panel-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
## Map View
|
||||
### Map view options
|
||||
|
||||
The map view controls the initial view of the map when the dashboard loads.
|
||||
|
||||
### Initial View
|
||||
#### Initial View
|
||||
|
||||
The initial view configures how the geomap renders when the panel is first loaded.
|
||||
|
||||
- **View** sets the center for the map when the panel first loads.
|
||||
- **Fit to data** fits the map view based on the data extents of Map layers and updates when data changes.
|
||||
- **Data** option allows selection of extent based on data from "All layers", a single "Layer", or the "Last value" from a selected layer.
|
||||
- **Layer** can be selected if fitting data from a single "Layer" or the "Last value" of a layer.
|
||||
- **Padding** sets padding in relative percent beyond data extent (not available when looking at "Last value" only).
|
||||
- **Max Zoom** sets the maximum zoom level when fitting data.
|
||||
- **Coordinates** sets the map view based on:
|
||||
- **Latitude**
|
||||
- **Longitude**
|
||||
- Default Views are also available including:
|
||||
- **(0°, 0°)**
|
||||
- **North America**
|
||||
- **South America**
|
||||
- **Europe**
|
||||
- **Africa**
|
||||
- **West Asia**
|
||||
- **South Asia**
|
||||
- **South-East Asia**
|
||||
- **East Asia**
|
||||
- **Australia**
|
||||
- **Oceania**
|
||||
- **Zoom** sets the initial zoom level.
|
||||
- **View** - Sets the center for the map when the panel first loads. Refer to the table following this list for view selections.
|
||||
- **Zoom** - Sets the initial zoom level.
|
||||
- **Use current map settings** - Use the settings of the current map to set the center.
|
||||
|
||||
### Share view
|
||||
<!-- prettier-ignore-start -->
|
||||
| View selection | Description |
|
||||
|---|---|
|
||||
| Fit to data | fits the map view based on the data extents of Map layers and updates when data changes.<ul><li>**Data** - option allows selection of extent based on data from "All layers", a single "Layer", or the "Last value" from a selected layer.</li><li>**Layer** - can be selected if fitting data from a single "Layer" or the "Last value" of a layer.</li><li>**Padding** - sets padding in relative percent beyond data extent (not available when looking at "Last value" only).</li><li>**Max zoom** - sets the maximum zoom level when fitting data.</li> |
|
||||
| (0°, 0°) | |
|
||||
| Coordinates | sets the map view based on: **Latitude** and **Longitude**. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Default Views are also available including:
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| | | | | |
|
||||
| ------------- | ------------- | ------ | ------ | --------- |
|
||||
| North America | South America | Europe | Africa | West Asia |
|
||||
| South Asia | South-East Asia | East Asia | Australia | Oceania |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### Share view
|
||||
|
||||
The **Share view** option allows you to link the movement and zoom actions of multiple map visualizations within the same dashboard. The map visualizations that have this option enabled act in tandem when one of them is moved or zoomed, leaving the other ones independent.
|
||||
|
||||
@@ -184,11 +184,28 @@ The **Share view** option allows you to link the movement and zoom actions of mu
|
||||
You might need to reload the dashboard for this feature to work.
|
||||
{{< /admonition >}}
|
||||
|
||||
## Map layers
|
||||
### Map layers options
|
||||
|
||||
Geomaps support showing multiple layers. Each layer determines how you visualize geospatial data on top of the base map.
|
||||
|
||||
### Types
|
||||
There are three options that you need to set for all maps:
|
||||
|
||||
- [Layer type](#layer-type)
|
||||
- [Data](#data)
|
||||
- [Location mode](#location-mode)
|
||||
|
||||
Other options are dependent on your map layer type and are described within the layer type section.
|
||||
|
||||
The layer controls allow you to create layers, change their name, reorder and delete layers.
|
||||
|
||||
- **Add layer** creates an additional, configurable data layer for the geomap. When you add a layer, you are prompted to select a layer type. You can change the layer type at any point during panel configuration. See the **Layer Types** section above for details on each layer type.
|
||||
- **Edit layer name (pencil icon)** renames the layer.
|
||||
- **Trash Bin** deletes the layer.
|
||||
- **Reorder (six dots/grab handle)** allows you to change the layer order. Data on higher layers will appear above data on lower layers. The visualization will update the layer order as you drag and drop to help simplify choosing a layer order.
|
||||
|
||||
You can add multiple layers of data to a single geomap in order to create rich, detailed visualizations.
|
||||
|
||||
#### Layer type
|
||||
|
||||
There are seven map layer types to choose from in a geomap.
|
||||
|
||||
@@ -199,6 +216,10 @@ There are seven map layer types to choose from in a geomap.
|
||||
- [Route (Beta)](#route-layer-beta) render data points as a route.
|
||||
- [Photos (Beta)](#photos-layer-beta) renders a photo at each data point.
|
||||
- [Network (Beta)](#network-layer-beta) visualizes a network graph from the data.
|
||||
- [Open Street Map](#open-street-map-layer) adds a map from a collaborative free geographic world database.
|
||||
- [CARTO basemap](#carto-basemap-layer) adds a layer from CARTO Raster basemaps.
|
||||
- [ArcGIS MapServer](#arcgis-mapserver-layer) adds a layer from an ESRI ArcGIS MapServer.
|
||||
- [XYZ Tile layer](#xyz-tile-layer) adds a map from a generic tile layer.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Beta is equivalent to the [public preview](/docs/release-life-cycle/) release stage.
|
||||
@@ -209,9 +230,7 @@ There are also two experimental (or alpha) layer types.
|
||||
- **Icon at last point (alpha)** renders an icon at the last data point.
|
||||
- **Dynamic GeoJSON (alpha)** styles a GeoJSON file based on query results.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
To enable experimental layers:
|
||||
Set `enable_alpha` to `true` in your configuration file:
|
||||
To enable experimental layers. Set `enable_alpha` to `true` in your configuration file:
|
||||
|
||||
```
|
||||
[panels]
|
||||
@@ -224,29 +243,11 @@ To enable the experimental layers using Docker, run the following command:
|
||||
docker run -p 3000:3000 -e "GF_PANELS_ENABLE_ALPHA=true" grafana/grafana:<VERSION>
|
||||
```
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
[Basemap layer types](#types-1) can also be added as layers. You can specify an opacity.
|
||||
{{% /admonition %}}
|
||||
|
||||
### Layer Controls
|
||||
|
||||
The layer controls allow you to create layers, change their name, reorder and delete layers.
|
||||
|
||||
- **Add layer** creates an additional, configurable data layer for the geomap. When you add a layer, you are prompted to select a layer type. You can change the layer type at any point during panel configuration. See the **Layer Types** section above for details on each layer type.
|
||||
- The layer controls allow you to rename, delete, and reorder the layers of the visualization.
|
||||
- **Edit layer name (pencil icon)** renames the layer.
|
||||
- **Trash Bin** deletes the layer.
|
||||
- **Reorder (six dots/grab handle)** allows you to change the layer order. Data on higher layers will appear above data on lower layers. The visualization will update the layer order as you drag and drop to help simplify choosing a layer order.
|
||||
|
||||
You can add multiple layers of data to a single geomap in order to create rich, detailed visualizations.
|
||||
|
||||
### Data
|
||||
#### Data
|
||||
|
||||
Geomaps need a source of geographical data gathered from a data source query which can return multiple datasets. By default Grafana picks the first dataset, but this drop-down allows you to pick other datasets if the query returns more than one.
|
||||
|
||||
### Location mode
|
||||
#### Location mode
|
||||
|
||||
There are four options to map the data returned by the selected query:
|
||||
|
||||
@@ -259,23 +260,290 @@ There are four options to map the data returned by the selected query:
|
||||
- **Geohash** specifies that your query holds geohash data. You will be prompted to select a string data field for the geohash from your database query.
|
||||
- **Lookup** specifies that your query holds location name data that needs to be mapped to a value. You will be prompted to select the lookup field from your database query and a gazetteer. The gazetteer is the directory that is used to map your queried data to a geographical point.
|
||||
|
||||
## Basemap layer
|
||||
#### Markers layer
|
||||
|
||||
The markers layer allows you to display data points as different marker shapes such as circles, squares, triangles, stars, and more.
|
||||
|
||||

|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Data | Configure the data settings for the layer. For more information, refer to [Data](#data). |
|
||||
| Location | Configure the data settings for the layer. For more information, refer to [Location mode](#location-mode). |
|
||||
| Size | Configures the size of the markers. The default is `Fixed size`, which makes all marker sizes the same regardless of the data; however, there is also an option to size the markers based on data corresponding to a selected field. `Min` and `Max` marker sizes have to be set such that the markers can scale within this range. |
|
||||
| Symbol | Allows you to choose the symbol, icon, or graphic to aid in providing additional visual context to your data. Choose from assets that are included with Grafana such as simple symbols or the Unicon library. You can also specify a URL containing an image asset. The image must be a scalable vector graphic (SVG). |
|
||||
| Symbol Vertical Align | Configures the vertical alignment of the symbol relative to the data point. Note that the symbol's rotation angle is applied first around the data point, then the vertical alignment is applied relative to the rotation of the symbol. |
|
||||
| Symbol Horizontal Align | Configures the horizontal alignment of the symbol relative to the data point. Note that the symbol's rotation angle is applied first around the data point, then the horizontal alignment is applied relative to the rotation of the symbol. |
|
||||
| Color | Configures the color of the markers. The default `Fixed color` sets all markers to a specific color. There is also an option to have conditional colors depending on the selected field data point values and the color scheme set in the `Standard options` section. |
|
||||
| Fill opacity | Configures the transparency of each marker. |
|
||||
| Rotation angle | Configures the rotation angle of each marker. The default is `Fixed value`, which makes all markers rotate to the same angle regardless of the data; however, there is also an option to set the rotation of the markers based on data corresponding to a selected field. |
|
||||
| Text label | Configures a text label for each marker. |
|
||||
| Show legend | Allows you to toggle the legend for the layer. |
|
||||
| Display tooltip | Allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### Heatmap layer
|
||||
|
||||
The heatmap layer clusters various data points to visualize locations with different densities.
|
||||
To add a heatmap layer:
|
||||
|
||||
Click on the drop-down menu under Data Layer and choose `Heatmap`.
|
||||
|
||||
Similar to `Markers`, you are prompted with various options to determine which data points to visualize and how you want to visualize them.
|
||||
|
||||

|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Data | Configure the data settings for the layer. For more information, refer to [Data](#data). |
|
||||
| Location | Configure the data settings for the layer. For more information, refer to [Location mode](#location-mode). |
|
||||
| Weight values | Configures the size of the markers. The default is `Fixed size`, which makes all marker sizes the same regardless of the data; however, there is also an option to size the markers based on data corresponding to a selected field. `Min` and `Max` marker sizes have to be set such that the markers can scale within this range. |
|
||||
| Radius | Configures the size of the heatmap clusters. |
|
||||
| Blur | Configures the amount of blur on each cluster. |
|
||||
| Opacity | Configures the opacity of each cluster. |
|
||||
| Display tooltip | Allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### GeoJSON layer
|
||||
|
||||
The GeoJSON layer allows you to select and load a static GeoJSON file from the filesystem.
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| GeoJSON URL | Provides a choice of GeoJSON files that ship with Grafana. |
|
||||
| Default Style | Controls which styles to apply when no rules above match.<ul><li>**Color** - configures the color of the default style</li><li>**Opacity** - configures the default opacity</li></ul> |
|
||||
| Style Rules | Apply styles based on feature properties <ul><li>**Rule** - allows you to select a _feature_, _condition_, and _value_ from the GeoJSON file in order to define a rule. The trash bin icon can be used to delete the current rule.</li><li>**Color** - configures the color of the style for the current rule</li><li>**Opacity** - configures the transparency level for the current rule</li> |
|
||||
| Display tooltip | Allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
Styles can be set within the "properties" object of the GeoJSON with support for the following geometries:
|
||||
|
||||
**Polygon, MultiPolygon**
|
||||
|
||||
- **"fill"** - The color of the interior of the polygon(s)
|
||||
- **"fill-opacity"** - The opacity of the interior of the polygon(s)
|
||||
- **"stroke-width"** - The width of the line component of the polygon(s)
|
||||
|
||||
**Point, MultiPoint**
|
||||
|
||||
- **"marker-color"** - The color of the point(s)
|
||||
- **"marker-size"** - The size of the point(s)
|
||||
|
||||
**LineString, MultiLineString**
|
||||
|
||||
- **"stroke"** - The color of the line(s)
|
||||
- **"stroke-width"** - The width of the line(s)
|
||||
|
||||
#### Night / Day layer
|
||||
|
||||
The Night / Day layer displays night and day regions based on the current time range.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-day-night-9-1-0.png" max-width="1200px" alt="Geomap panel Night / Day" >}}
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Data | Configures the data set for the layer. For more information, refer to [Data](#data). |
|
||||
| Show | Toggles the time source from panel time range. |
|
||||
| Night region color | Picks the color for the night region. |
|
||||
| Display sun | Toggles the sun icon. |
|
||||
| Opacity | Set the opacity from `0` (transparent) to `1` (opaque). |
|
||||
| Display tooltip | Allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
[Extensions for OpenLayers - DayNight](https://viglino.github.io/ol-ext/examples/layer/map.daynight.html)
|
||||
|
||||
#### Route layer (Beta)
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
The Route layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{% /admonition %}}
|
||||
|
||||
The Route layer renders data points as a route.
|
||||
|
||||
{{< figure src="/media/docs/grafana/geomap-route-layer-basic-9-4-0.png" max-width="1200px" alt="Geomap panel Route" >}}
|
||||
|
||||
The layer can also render a route with arrows.
|
||||
|
||||
{{< figure src="/media/docs/grafana/geomap-route-layer-arrow-size-9-4-0.png" max-width="1200px" alt="Geomap panel Route arrows with size" >}}
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Data | configure the data settings for the layer. For more information, refer to [Data](#data). |
|
||||
| Location | configure the data settings for the layer. For more information, refer to [Location mode](#location-mode). |
|
||||
| Size | sets the route thickness. Fixed value by default. When field data is selected you can set the Min and Max range in which field data can scale. |
|
||||
| Color | sets the route color. Set to `Fixed color` by default. You can also tie the color to field data. |
|
||||
| Fill opacity | configures the opacity of the route. |
|
||||
| Text label | configures a text label for each route. |
|
||||
| Arrow | sets the arrow styling to display along route, in order of data. Choose from: **None**, **Forward**, and **Reverse** |
|
||||
| Display tooltip | allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
[Extensions for OpenLayers - Flow Line Style](http://viglino.github.io/ol-ext/examples/style/map.style.gpxline.html)
|
||||
|
||||
#### Photos layer (Beta)
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
The Photos layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{% /admonition %}}
|
||||
|
||||
The Photos layer renders a photo at each data point.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-photos-9-3-0.png" max-width="1200px" alt="Geomap panel Photos" >}}
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Data | Configure the data settings for the layer. For more information, refer to [Data](#data). |
|
||||
| Location | Configure the data settings for the layer. For more information, refer to [Location mode](#location-mode). |
|
||||
| Image Source field | Allows you to select a string field containing image data in either of the following formats:<ul><li>**Image URLs**</li><li>**Base64 encoded** - Image binary ("data:image/png;base64,...")</li></ul> |
|
||||
| Kind | Sets the frame style around the images. Choose from: **Square**, **Circle**, **Anchored**, and **Folio**. |
|
||||
| Crop | Toggles whether the images are cropped to fit. |
|
||||
| Shadow | Toggles a box shadow behind the images. |
|
||||
| Border | Sets the border size around images. |
|
||||
| Border color | Sets the border color around images. |
|
||||
| Radius | Sets the overall size of images in pixels. |
|
||||
| Display tooltip | Allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
[Extensions for OpenLayers - Image Photo Style](http://viglino.github.io/ol-ext/examples/style/map.style.photo.html)
|
||||
|
||||
#### Network layer (Beta)
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
The Network layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{% /admonition %}}
|
||||
|
||||
The Network layer renders a network graph. This layer supports the same [data format supported by the node graph visualization](ref:data-format) with the addition of [geospatial data](#location-mode) included in the nodes data. The geospatial data is used to locate and render the nodes on the map.
|
||||
|
||||
{{< figure src="/media/docs/grafana/screenshot-grafana-10-1-geomap-network-layer-v2.png" max-width="750px" alt="Geomap network layer" >}}
|
||||
|
||||
You can convert node graph data to a network layer:
|
||||
{{< video-embed src="/media/docs/grafana/screen-recording-10-1-geomap-network-layer-from-node-graph.mp4" max-width="750px" alt="Node graph to Geomap network layer" >}}
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Data | Configure the data settings for the layer. For more information, refer to [Data](#data). |
|
||||
| Location | Configure the data settings for the layer. For more information, refer to [Location mode](#location-mode). |
|
||||
| Arrow | Sets the arrow direction to display for each edge, with forward meaning source to target. Choose from: **None**, **Forward**, **Reverse** and **Both**. |
|
||||
| Show legend | Allows you to toggle the legend for the layer. **Note:** The legend currently only supports node data. |
|
||||
| Display tooltip | Allows you to toggle tooltips for the layer. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
##### Node styles options
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Size | Configures the size of the nodes. The default is `Fixed size`, which makes all node sizes the same regardless of the data; however, there is also an option to size the nodes based on data corresponding to a selected field. `Min` and `Max` node sizes have to be set such that the nodes can scale within this range. |
|
||||
| Symbol | Allows you to choose the symbol, icon, or graphic to aid in providing additional visual context to your data. Choose from assets that are included with Grafana such as simple symbols or the Unicon library. You can also specify a URL containing an image asset. The image must be a scalable vector graphic (SVG). |
|
||||
| Color | Configures the color of the nodes. The default `Fixed color` sets all nodes to a specific color. There is also an option to have conditional colors depending on the selected field data point values and the color scheme set in the `Standard options` section. |
|
||||
| Fill opacity | Configures the transparency of each node. |
|
||||
| Rotation angle | Configures the rotation angle of each node. The default is `Fixed value`, which makes all nodes rotate to the same angle regardless of the data; however, there is also an option to set the rotation of the nodes based on data corresponding to a selected field. |
|
||||
| Text label | Configures a text label for each node. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
##### Edge styles options
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| Size | Configures the line width of the edges. The default is `Fixed size`, which makes all edge line widths the same regardless of the data; however, there is also an option to size the edges based on data corresponding to a selected field. `Min` and `Max` eges sizes have to be set such that the edges can scale within this range. |
|
||||
| Color | Configures the color of the edges. The default `Fixed color` sets all edges to a specific color. There is also an option to have conditional colors depending on the selected field data point values and the color scheme set in the `Standard options` section. |
|
||||
| Fill opacity | Configures the transparency of each edge. |
|
||||
| Text label | Configures a text label for each edge. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### Open Street Map layer
|
||||
|
||||
A map from a collaborative free geographic world database.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-osm-9-1-0.png" max-width="1200px" alt="Geomap panel Open Street Map" >}}
|
||||
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
- **Display tooltip** - allows you to toggle tooltips for the layer.
|
||||
|
||||
[About Open Street Map](https://www.openstreetmap.org/about)
|
||||
|
||||
#### CARTO basemap layer
|
||||
|
||||
A CARTO layer is from CARTO Raster basemaps.
|
||||
|
||||
- **Theme**
|
||||
- Auto
|
||||
- Light
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-carto-light-9-1-0.png" max-width="1200px" alt="Geomap panel CARTO light example" >}}
|
||||
- Dark
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-carto-dark-9-1-0.png" max-width="1200px" alt="Geomap panel CARTO dark example" >}}
|
||||
- **Show labels** shows the Country details on top of the map.
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
- **Display tooltip** - allows you to toggle tooltips for the layer.
|
||||
|
||||
[About CARTO](https://carto.com/about-us/)
|
||||
|
||||
#### ArcGIS MapServer layer
|
||||
|
||||
An ArcGIS layer is a layer from an ESRI ArcGIS MapServer.
|
||||
|
||||
- **Server Instance** to select the map type.
|
||||
- World Street Map
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-wsm-9-1-0.png" max-width="1200px" alt="Geomap panel ArcGIS World Street Map" >}}
|
||||
- World Imagery
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-wi-9-1-0.png" max-width="1200px" alt="Geomap panel ArcGIS World Imagery" >}}
|
||||
- World Physical
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-wp-9-1-0.png" max-width="1200px" alt="Geomap panel ArcGIS World Physical" >}}
|
||||
- Topographic
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-topographic-9-1-0.png" max-width="1200px" alt="Geomap panel ArcGIS Topographic" >}}
|
||||
- USA Topographic
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-usa-topographic-9-1-0.png" max-width="1200px" alt="Geomap panel ArcGIS USA Topographic" >}}
|
||||
- World Ocean
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-ocean-9-1-0.png" max-width="1200px" alt="Geomap panel ArcGIS World Ocean" >}}
|
||||
- Custom MapServer (see [XYZ](#xyz-tile-layer) for formatting)
|
||||
- URL template
|
||||
- Attribution
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
- **Display tooltip** - allows you to toggle tooltips for the layer.
|
||||
|
||||
##### More Information
|
||||
|
||||
- [ArcGIS Services](https://services.arcgisonline.com/arcgis/rest/services)
|
||||
- [About ESRI](https://www.esri.com/en-us/about/about-esri/overview)
|
||||
|
||||
#### XYZ Tile layer
|
||||
|
||||
The XYZ Tile layer is a map from a generic tile layer.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-xyz-9-1-0.png" max-width="1200px" alt="Geomap panel xyz example" >}}
|
||||
|
||||
- **URL template** - Set a valid tile server url, with {z}/{x}/{y} for example: https://tile.openstreetmap.org/{z}/{x}/{y}.png
|
||||
- **Attribution** sets the reference string for the layer if displayed in [map controls](#show-attribution)
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
|
||||
##### More information
|
||||
|
||||
- [Tiled Web Map Wikipedia](https://en.wikipedia.org/wiki/Tiled_web_map)
|
||||
- [List of Open Street Map Tile Servers](https://wiki.openstreetmap.org/wiki/Tile_servers)
|
||||
|
||||
### Basemap layer options
|
||||
|
||||
A basemap layer provides the visual foundation for a mapping application. It typically contains data with global coverage. Several base layer options
|
||||
are available each with specific configuration options to style the base map.
|
||||
|
||||
### Types
|
||||
Basemap layer types can also be added as layers. You can specify an opacity.
|
||||
|
||||
There are four basemap layer types to choose from in a geomap.
|
||||
|
||||
- [Open Street Map](#open-street-map-layer) adds a map from a collaborative free geographic world database.
|
||||
- [CARTO](#carto-layer) adds a layer from CARTO Raster basemaps.
|
||||
- [ArcGIS](#arcgis-layer) adds a layer from an ESRI ArcGIS MapServer.
|
||||
- [XYZ](#xyz-tile-layer) adds a map from a generic tile layer.
|
||||
- [CARTO basemap](#carto-basemap-layer) adds a layer from CARTO Raster basemaps.
|
||||
- [ArcGIS MapServer](#arcgis-mapserver-layer) adds a layer from an ESRI ArcGIS MapServer.
|
||||
- [XYZ Tile layer](#xyz-tile-layer) adds a map from a generic tile layer.
|
||||
|
||||
### Default
|
||||
|
||||
The default base layer uses the [CARTO](#carto-layer) map. You can define custom default base layers in the `.ini` configuration file.
|
||||
The default basemap layer uses the CARTO map. You can define custom default base layers in the `.ini` configuration file.
|
||||
|
||||

|
||||
|
||||
@@ -299,6 +567,9 @@ geomap_default_baselayer = `{
|
||||
|
||||
- **esri-xyz** loads the ESRI tile server. There are already multiple server instances implemented to show the various map styles: `world-imagery`, `world-physical`, `topo`, `usa-topo`, and `ocean`. The `custom` server option allows you to configure your own ArcGIS map server. Here are some examples:
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab-content name="World imagery" >}}
|
||||
|
||||
```ini
|
||||
geomap_default_baselayer = `{
|
||||
"type": "esri-xyz",
|
||||
@@ -308,6 +579,9 @@ geomap_default_baselayer = `{
|
||||
}`
|
||||
```
|
||||
|
||||
{{< /tab-content >}}
|
||||
{{< tab-content name="Custom" >}}
|
||||
|
||||
```ini
|
||||
geomap_default_baselayer = `{
|
||||
"type": "esri-xyz",
|
||||
@@ -319,6 +593,9 @@ geomap_default_baselayer = `{
|
||||
}`
|
||||
```
|
||||
|
||||
{{< /tab-content >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
- **osm-standard** loads the OpenStreetMap tile server. There are no additional configurations needed and the `config` fields can be left blank. Here is an example:
|
||||
|
||||
```ini
|
||||
@@ -342,343 +619,57 @@ default_baselayer_config = `{
|
||||
|
||||
`enable_custom_baselayers` allows you to enable or disable custom open source base maps that are already implemented. The default is `true`.
|
||||
|
||||
## Markers layer
|
||||
|
||||
The markers layer allows you to display data points as different marker shapes such as circles, squares, triangles, stars, and more.
|
||||
|
||||

|
||||
|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/geomap-markers-options-11-1-0.png" max-width="350px" alt="Markers layer options" >}}
|
||||
|
||||
- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode).
|
||||
- **Size** configures the size of the markers. The default is `Fixed size`, which makes all marker sizes the same regardless of the data; however, there is also an option to size the markers based on data corresponding to a selected field. `Min` and `Max` marker sizes have to be set such that the markers can scale within this range.
|
||||
- **Symbol** allows you to choose the symbol, icon, or graphic to aid in providing additional visual context to your data. Choose from assets that are included with Grafana such as simple symbols or the Unicon library. You can also specify a URL containing an image asset. The image must be a scalable vector graphic (SVG).
|
||||
- **Symbol Vertical Align** configures the vertical alignment of the symbol relative to the data point. Note that the symbol's rotation angle is applied first around the data point, then the vertical alignment is applied relative to the rotation of the symbol.
|
||||
- **Symbol Horizontal Align** configures the horizontal alignment of the symbol relative to the data point. Note that the symbol's rotation angle is applied first around the data point, then the horizontal alignment is applied relative to the rotation of the symbol.
|
||||
- **Color** configures the color of the markers. The default `Fixed color` sets all markers to a specific color. There is also an option to have conditional colors depending on the selected field data point values and the color scheme set in the `Standard options` section.
|
||||
- **Fill opacity** configures the transparency of each marker.
|
||||
- **Rotation angle** configures the rotation angle of each marker. The default is `Fixed value`, which makes all markers rotate to the same angle regardless of the data; however, there is also an option to set the rotation of the markers based on data corresponding to a selected field.
|
||||
- **Text label** configures a text label for each marker.
|
||||
- **Show legend** allows you to toggle the legend for the layer.
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
## Heatmap layer
|
||||
|
||||
The heatmap layer clusters various data points to visualize locations with different densities.
|
||||
To add a heatmap layer:
|
||||
|
||||
Click on the drop-down menu under Data Layer and choose `Heatmap`.
|
||||
|
||||
Similar to `Markers`, you are prompted with various options to determine which data points to visualize and how you want to visualize them.
|
||||
|
||||

|
||||
|
||||
{{< figure src="/media/docs/grafana/panels-visualizations/geomap-heatmap-options-11-1-0.png" max-width="350px" alt="Heatmap layer options" >}}
|
||||
|
||||
- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode).
|
||||
- **Weight values** configure the intensity of the heatmap clusters. `Fixed value` keeps a constant weight value throughout all data points. This value should be in the range of 0~1. Similar to Markers, there is an alternate option in the drop-down to automatically scale the weight values depending on data values.
|
||||
- **Radius** configures the size of the heatmap clusters.
|
||||
- **Blur** configures the amount of blur on each cluster.
|
||||
- **Opacity** configures the opacity of each cluster.
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
## GeoJSON layer
|
||||
|
||||
The GeoJSON layer allows you to select and load a static GeoJSON file from the filesystem.
|
||||
|
||||
- **GeoJSON URL** provides a choice of GeoJSON files that ship with Grafana.
|
||||
- **Default Style** controls which styles to apply when no rules above match.
|
||||
- **Color** configures the color of the default style
|
||||
- **Opacity** configures the default opacity
|
||||
- **Style Rules** apply styles based on feature properties
|
||||
- **Rule** allows you to select a _feature_, _condition_, and _value_ from the GeoJSON file in order to define a rule. The trash bin icon can be used to delete the current rule.
|
||||
- **Color** configures the color of the style for the current rule
|
||||
- **Opacity** configures the transparency level for the current rule
|
||||
- **Add style rule** creates additional style rules.
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Styles can be set within the "properties" object of the GeoJSON with support for the following geometries:
|
||||
|
||||
- Polygon, MultiPolygon
|
||||
|
||||
- **"fill"** - The color of the interior of the polygon(s)
|
||||
- **"fill-opacity"** - The opacity of the interior of the polygon(s)
|
||||
- **"stroke-width"** - The width of the line component of the polygon(s)
|
||||
|
||||
- Point, MultiPoint
|
||||
|
||||
- **"marker-color"** - The color of the point(s)
|
||||
- **"marker-size"** - The size of the point(s)
|
||||
|
||||
- LineString, MultiLineString
|
||||
- **"stroke"** - The color of the line(s)
|
||||
- **"stroke-width"** - The width of the line(s)
|
||||
|
||||
{{% /admonition %}}
|
||||
|
||||
## Night / Day layer
|
||||
|
||||
The Night / Day layer displays night and day regions based on the current time range.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-day-night-9-1-0.png" max-width="1200px" caption="Geomap panel Night / Day" >}}
|
||||
|
||||
### Options
|
||||
|
||||
- **Data** configures the data set for the layer. For more information, refer to [Data](#data).
|
||||
- **Show** toggles the time source from panel time range.
|
||||
- **Night region color** picks the color for the night region.
|
||||
- **Display sun** toggles the sun icon.
|
||||
- **Opacity** set the opacity from `0` (transparent) to `1` (opaque).
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-day-night-options-9-1-0.png" max-width="1200px" caption="Geomap panel Night / Day options" >}}
|
||||
|
||||
### More information
|
||||
|
||||
- [**Extensions for OpenLayers - DayNight**](https://viglino.github.io/ol-ext/examples/layer/map.daynight.html)
|
||||
|
||||
## Route layer (Beta)
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
The Route layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{% /admonition %}}
|
||||
|
||||
The Route layer renders data points as a route.
|
||||
|
||||
{{< figure src="/media/docs/grafana/geomap-route-layer-basic-9-4-0.png" max-width="1200px" caption="Geomap panel Route" >}}
|
||||
|
||||
### Options
|
||||
|
||||
- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode).
|
||||
- **Size** sets the route thickness. Fixed value by default. When field data is selected you can set the Min and Max range in which field data can scale.
|
||||
- **Color** sets the route color. Set to `Fixed color` by default. You can also tie the color to field data.
|
||||
- **Fill opacity** configures the opacity of the route.
|
||||
- **Text label** configures a text label for each route.
|
||||
- **Arrow** sets the arrow styling to display along route, in order of data.
|
||||
- **None**
|
||||
- **Forward**
|
||||
- **Reverse**
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
{{< figure src="/media/docs/grafana/geomap-route-layer-arrow-size-9-4-0.png" max-width="1200px" caption="Geomap panel Route arrows with size" >}}
|
||||
|
||||
### More information
|
||||
|
||||
- [**Extensions for OpenLayers - Flow Line Style**](http://viglino.github.io/ol-ext/examples/style/map.style.gpxline.html)
|
||||
|
||||
## Photos layer (Beta)
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
The Photos layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{% /admonition %}}
|
||||
|
||||
The Photos layer renders a photo at each data point.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-photos-9-3-0.png" max-width="1200px" caption="Geomap panel Photos" >}}
|
||||
|
||||
### Options
|
||||
|
||||
- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode).
|
||||
- **Image Source field** allows you to select a string field containing image data in either of the following formats:
|
||||
- **Image URLs**
|
||||
- **Base64 encoded** - Image binary ("data:image/png;base64,...")
|
||||
- **Kind** sets the frame style around the images. Choose from:
|
||||
- **Square**
|
||||
- **Circle**
|
||||
- **Anchored**
|
||||
- **Folio**
|
||||
- **Crop** toggles whether the images are cropped to fit.
|
||||
- **Shadow** toggles a box shadow behind the images.
|
||||
- **Border** sets the border size around images.
|
||||
- **Border color** sets the border color around images.
|
||||
- **Radius** sets the overall size of images in pixels.
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-photos-options-9-3-0.png" max-width="1200px" caption="Geomap panel Photos options" >}}
|
||||
|
||||
### More information
|
||||
|
||||
- [**Extensions for OpenLayers - Image Photo Style**](http://viglino.github.io/ol-ext/examples/style/map.style.photo.html)
|
||||
|
||||
## Network layer (Beta)
|
||||
|
||||
{{% admonition type="caution" %}}
|
||||
The Network layer is currently in [public preview](/docs/release-life-cycle/). Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
|
||||
{{% /admonition %}}
|
||||
|
||||
The Network layer renders a network graph. This layer supports the same [data format supported by the node graph visualization](ref:data-format) with the addition of [geospatial data](#location-mode) included in the nodes data. The geospatial data is used to locate and render the nodes on the map.
|
||||
|
||||
{{< figure src="/media/docs/grafana/screenshot-grafana-10-1-geomap-network-layer-v2.png" max-width="750px" caption="Geomap network layer" >}}
|
||||
{{< video-embed src="/media/docs/grafana/screen-recording-10-1-geomap-network-layer-from-node-graph.mp4" max-width="750px" caption="Node graph to Geomap network layer" >}}
|
||||
|
||||
### Options
|
||||
|
||||
- **Data** and **Location mode** configure the data settings for the layer. For more information, refer to [Data](#data) and [Location mode](#location-mode).
|
||||
- **Arrow** sets the arrow direction to display for each edge, with forward meaning source to target. Choose from:
|
||||
- **None**
|
||||
- **Forward**
|
||||
- **Reverse**
|
||||
- **Both**
|
||||
- **Show legend** allows you to toggle the legend for the layer. **Note:** The legend currently only supports node data.
|
||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||
|
||||
#### Node styles
|
||||
|
||||
- **Size** configures the size of the nodes. The default is `Fixed size`, which makes all node sizes the same regardless of the data; however, there is also an option to size the nodes based on data corresponding to a selected field. `Min` and `Max` node sizes have to be set such that the nodes can scale within this range.
|
||||
- **Symbol** allows you to choose the symbol, icon, or graphic to aid in providing additional visual context to your data. Choose from assets that are included with Grafana such as simple symbols or the Unicon library. You can also specify a URL containing an image asset. The image must be a scalable vector graphic (SVG).
|
||||
- **Color** configures the color of the nodes. The default `Fixed color` sets all nodes to a specific color. There is also an option to have conditional colors depending on the selected field data point values and the color scheme set in the `Standard options` section.
|
||||
- **Fill opacity** configures the transparency of each node.
|
||||
- **Rotation angle** configures the rotation angle of each node. The default is `Fixed value`, which makes all nodes rotate to the same angle regardless of the data; however, there is also an option to set the rotation of the nodes based on data corresponding to a selected field.
|
||||
- **Text label** configures a text label for each node.
|
||||
|
||||
#### Edge styles
|
||||
|
||||
- **Size** configures the line width of the edges. The default is `Fixed size`, which makes all edge line widths the same regardless of the data; however, there is also an option to size the edges based on data corresponding to a selected field. `Min` and `Max` eges sizes have to be set such that the edges can scale within this range.
|
||||
- **Color** configures the color of the edges. The default `Fixed color` sets all edges to a specific color. There is also an option to have conditional colors depending on the selected field data point values and the color scheme set in the `Standard options` section.
|
||||
- **Fill opacity** configures the transparency of each edge.
|
||||
- **Text label** configures a text label for each edge.
|
||||
|
||||
## CARTO layer
|
||||
|
||||
A CARTO layer is from CARTO Raster basemaps.
|
||||
|
||||
### Options
|
||||
|
||||
- **Theme**
|
||||
- Auto
|
||||
- Light
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-carto-light-9-1-0.png" max-width="1200px" caption="Geomap panel CARTO light example" >}}
|
||||
- Dark
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-carto-dark-9-1-0.png" max-width="1200px" caption="Geomap panel CARTO dark example" >}}
|
||||
- **Show labels** shows the Country details on top of the map.
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-carto-options-9-1-0.png" max-width="1200px" caption="Geomap panel CARTO options" >}}
|
||||
|
||||
### More Information
|
||||
|
||||
- [**About CARTO**](https://carto.com/about-us/)
|
||||
|
||||
## XYZ tile layer
|
||||
|
||||
The XYZ tile layer is a map from a generic tile layer.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-xyz-9-1-0.png" max-width="1200px" caption="Geomap panel xyz example" >}}
|
||||
|
||||
### Options
|
||||
|
||||
- **URL template**
|
||||
|
||||
> **Note:** Set a valid tile server url, with {z}/{x}/{y} for example: https://tile.openstreetmap.org/{z}/{x}/{y}.png
|
||||
|
||||
- **Attribution** sets the reference string for the layer if displayed in [map controls](#show-attribution)
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-xyz-options-9-1-0.png" max-width="1200px" caption="Geomap panel xyz options" >}}
|
||||
|
||||
### More information
|
||||
|
||||
- [**Tiled Web Map Wikipedia**](https://en.wikipedia.org/wiki/Tiled_web_map)
|
||||
- [**List of Open Street Map Tile Servers**](https://wiki.openstreetmap.org/wiki/Tile_servers)
|
||||
|
||||
## Open Street Map layer
|
||||
|
||||
A map from a collaborative free geographic world database.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-osm-9-1-0.png" max-width="1200px" caption="Geomap panel Open Street Map" >}}
|
||||
|
||||
### Options
|
||||
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-osm-options-9-1-0.png" max-width="1200px" caption="Geomap panel Open Street Map options" >}}
|
||||
|
||||
### More Information
|
||||
|
||||
- [**About Open Street Map**](https://www.openstreetmap.org/about)
|
||||
|
||||
## ArcGIS layer
|
||||
|
||||
An ArcGIS layer is a layer from an ESRI ArcGIS MapServer.
|
||||
|
||||
### Options
|
||||
|
||||
- **Server Instance** to select the map type.
|
||||
- World Street Map
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-wsm-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS World Street Map" >}}
|
||||
- World Imagery
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-wi-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS World Imagery" >}}
|
||||
- World Physical
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-wp-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS World Physical" >}}
|
||||
- Topographic
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-topographic-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS Topographic" >}}
|
||||
- USA Topographic
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-usa-topographic-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS USA Topographic" >}}
|
||||
- World Ocean
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-ocean-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS World Ocean" >}}
|
||||
- Custom MapServer (see [XYZ](#xyz-tile-layer) for formatting)
|
||||
- URL template
|
||||
- Attribution
|
||||
- **Opacity** from 0 (transparent) to 1 (opaque)
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-arcgis-options-9-1-0.png" max-width="1200px" caption="Geomap panel ArcGIS options" >}}
|
||||
|
||||
### More Information
|
||||
|
||||
- [**ArcGIS Services**](https://services.arcgisonline.com/arcgis/rest/services)
|
||||
- [**About ESRI**](https://www.esri.com/en-us/about/about-esri/overview)
|
||||
|
||||
## Map Controls
|
||||
### Map controls options
|
||||
|
||||
The map controls section contains various options for map information and tool overlays.
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-9-1-0.png" max-width="1200px" caption="Geomap panel map controls" >}}
|
||||
|
||||
### Zoom
|
||||
|
||||
This section describes each of the zoom controls.
|
||||
<!-- prettier-ignore-start -->
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| [Show zoom control](#show-zoom-control) | Displays zoom controls in the upper left corner. |
|
||||
| [Mouse wheel zoom](#mouse-wheel-zoom) | Enables the mouse wheel to be used for zooming in or out. |
|
||||
| [Show attribution](#show-attribution) | Displays attribution for basemap layers. |
|
||||
| [Show scale](#show-scale) | Displays scale information in the bottom left corner in meters (m) or kilometers (km). |
|
||||
| [Show measure tools](#show-measure-tools) | Displays measure tools in the upper right corner. This includes the [Length](#length) and [Area](#area) options. |
|
||||
| [Show debug](#show-debug) | Displays debug information in the upper right corner. |
|
||||
| [Tooltip](#tooltip) | Controls display of tooltips. |
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
#### Show zoom control
|
||||
|
||||
Displays zoom controls in the upper left corner. This control can be useful when using systems that don't have a mouse.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-zoom-9-1-0.png" max-width="1200px" caption="Geomap panel zoom" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-zoom-9-1-0.png" max-width="1200px" alt="Geomap panel zoom" >}}
|
||||
|
||||
#### Mouse wheel zoom
|
||||
|
||||
Enables the mouse wheel to be used for zooming in or out.
|
||||
|
||||
### Show attribution
|
||||
#### Show attribution
|
||||
|
||||
Displays attribution for basemap layers.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-attribution-9-1-0.png" max-width="1200px" caption="Geomap panel attribution" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-attribution-9-1-0.png" max-width="1200px" alt="Geomap panel attribution" >}}
|
||||
|
||||
### Show scale
|
||||
#### Show scale
|
||||
|
||||
Displays scale information in the bottom left corner.
|
||||
Displays scale information in the bottom left corner in meters (m) or kilometers (km).
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-scale-9-1-0.png" max-width="1200px" caption="Geomap panel scale" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-scale-9-1-0.png" max-width="1200px" alt="Geomap panel scale" >}}
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
Currently only displays units in [m]/[km].
|
||||
{{% /admonition %}}
|
||||
|
||||
### Show measure tools
|
||||
#### Show measure tools
|
||||
|
||||
Displays measure tools in the upper right corner. Measurements appear only when this control is open.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-measure-9-1-0.png" max-width="1200px" caption="Geomap panel measure" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-measure-9-1-0.png" max-width="1200px" alt="Geomap panel measure" >}}
|
||||
|
||||
- **Click** to start measuring
|
||||
- **Continue clicking** to continue measurement
|
||||
- **Double-click** to end measurement
|
||||
|
||||
{{% admonition type="note" %}}
|
||||
When you change measurement type or units, the previous measurement is removed from the map. If the control is closed and then re-opened, the most recent measurement is displayed. A measurement can be modified by clicking and dragging on it.
|
||||
{{% /admonition %}}
|
||||
|
||||
#### Length
|
||||
##### Length
|
||||
|
||||
Get the spherical length of a geometry. This length is the sum of the great circle distances between coordinates. For multi-part geometries, the length is the sum of the length of each part. Geometries are assumed to be in 'EPSG:3857'.
|
||||
|
||||
@@ -687,9 +678,9 @@ Get the spherical length of a geometry. This length is the sum of the great circ
|
||||
- **Miles (mi)**
|
||||
- **Nautical miles (nmi)**
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-measure-length-9-1-0.png" max-width="1200px" caption="Geomap panel measure length" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-measure-length-9-1-0.png" max-width="1200px" alt="Geomap panel measure length" >}}
|
||||
|
||||
#### Area
|
||||
##### Area
|
||||
|
||||
Get the spherical area of a geometry. This area is calculated assuming that polygon edges are segments of great circles on a sphere. Geometries are assumed to be in 'EPSG:3857'.
|
||||
|
||||
@@ -700,38 +691,38 @@ Get the spherical area of a geometry. This area is calculated assuming that poly
|
||||
- **Acres (acre)**
|
||||
- **Hectare (ha)**
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-measure-area-9-1-0.png" max-width="1200px" caption="Geomap panel measure area" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-measure-area-9-1-0.png" max-width="1200px" alt="Geomap panel measure area" >}}
|
||||
|
||||
### Show debug
|
||||
#### Show debug
|
||||
|
||||
Displays debug information in the upper right corner. This can be useful for debugging or validating a data source.
|
||||
|
||||
- **Zoom** displays current zoom level of the map.
|
||||
- **Center** displays the current **longitude**, **latitude** of the map center.
|
||||
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-debug-9-1-0.png" max-width="1200px" caption="Geomap panel debug" >}}
|
||||
{{< figure src="/static/img/docs/geomap-panel/geomap-map-controls-debug-9-1-0.png" max-width="1200px" alt="Geomap panel debug" >}}
|
||||
|
||||
### Tooltip
|
||||
#### Tooltip
|
||||
|
||||
- **None** displays tooltips only when a data point is clicked.
|
||||
- **Details** displays tooltips when a mouse pointer hovers over a data point.
|
||||
|
||||
## Standard options
|
||||
### Standard options
|
||||
|
||||
{{< docs/shared lookup="visualizations/standard-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
## Data links
|
||||
### Data links
|
||||
|
||||
{{< docs/shared lookup="visualizations/datalink-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
## Value mappings
|
||||
### Value mappings
|
||||
|
||||
{{< docs/shared lookup="visualizations/value-mappings-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
## Thresholds
|
||||
### Thresholds
|
||||
|
||||
{{< docs/shared lookup="visualizations/thresholds-options-2.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
## Field overrides
|
||||
### Field overrides
|
||||
|
||||
{{< docs/shared lookup="visualizations/overrides-options.md" source="grafana" version="<GRAFANA_VERSION>" >}}
|
||||
|
||||
@@ -701,6 +701,18 @@ You can enable both policies simultaneously.
|
||||
|
||||
Set the policy template that will be used when adding the `Content-Security-Policy-Report-Only` header to your requests. `$NONCE` in the template includes a random nonce.
|
||||
|
||||
### actions_allow_post_url
|
||||
|
||||
Sets API paths to be accessible between plugins using the POST verb. This is a comma separated list, and uses glob matching.
|
||||
|
||||
This will allow access to all plugins that have a backend:
|
||||
|
||||
`actions_allow_post_url=/api/plugins/*`
|
||||
|
||||
This will limit access to the backend of a single plugin:
|
||||
|
||||
`actions_allow_post_url=/api/plugins/grafana-special-app`
|
||||
|
||||
<hr />
|
||||
|
||||
### angular_support_enabled
|
||||
|
||||
@@ -281,13 +281,13 @@ Grafana supports user authentication through Okta, which is useful when you want
|
||||
- In the **Single sign on URL** field, use the `/saml/acs` endpoint URL of your Grafana instance, for example, `https://grafana.example.com/saml/acs`.
|
||||
- In the **Audience URI (SP Entity ID)** field, use the `/saml/metadata` endpoint URL, for example, `https://grafana.example.com/saml/metadata`.
|
||||
- Leave the default values for **Name ID format** and **Application username**.
|
||||
- In the **ATTRIBUTE STATEMENTS (OPTIONAL)** section, enter the SAML attributes to be shared with Grafana, for example:
|
||||
- In the **ATTRIBUTE STATEMENTS (OPTIONAL)** section, enter the SAML attributes to be shared with Grafana. The attribute names in Okta need to match exactly what is defined within Grafana, for example:
|
||||
|
||||
| Attribute name (in Grafana) | Value (in Okta profile) |
|
||||
| --------------------------- | -------------------------------------- |
|
||||
| Login | `user.login` |
|
||||
| Email | `user.email` |
|
||||
| DisplayName | `user.firstName + " " + user.lastName` |
|
||||
| Attribute name (in Grafana) | Name and value (in Okta profile) |
|
||||
| --------------------------- | -------------------------------------------------- |
|
||||
| Login | Login `user.login` |
|
||||
| Email | Email `user.email` |
|
||||
| DisplayName | DisplayName `user.firstName + " " + user.lastName` |
|
||||
|
||||
- In the **GROUP ATTRIBUTE STATEMENTS (OPTIONAL)** section, enter a group attribute name (for example, `Group`) and set filter to `Matches regex .*` to return all user groups.
|
||||
|
||||
|
||||
@@ -97,6 +97,14 @@ On a minimal CentOS 8 installation, the following dependencies are required for
|
||||
libXcomposite libXdamage libXtst cups libXScrnSaver pango atk adwaita-cursor-theme adwaita-icon-theme at at-spi2-atk at-spi2-core cairo-gobject colord-libs dconf desktop-file-utils ed emacs-filesystem gdk-pixbuf2 glib-networking gnutls gsettings-desktop-schemas gtk-update-icon-cache gtk3 hicolor-icon-theme jasper-libs json-glib libappindicator-gtk3 libdbusmenu libdbusmenu-gtk3 libepoxy liberation-fonts liberation-narrow-fonts liberation-sans-fonts liberation-serif-fonts libgusb libindicator-gtk3 libmodman libproxy libsoup libwayland-cursor libwayland-egl libxkbcommon m4 mailx nettle patch psmisc redhat-lsb-core redhat-lsb-submod-security rest spax time trousers xdg-utils xkeyboard-config alsa-lib libX11-xcb
|
||||
```
|
||||
|
||||
**RHEL:**
|
||||
|
||||
On a minimal RHEL 8 installation, the following dependencies are required for the image rendering to function:
|
||||
|
||||
```bash
|
||||
linux-vdso.so.1 libdl.so.2 libpthread.so.0 libgobject-2.0.so.0 libglib-2.0.so.0 libnss3.so libnssutil3.so libsmime3.so libnspr4.so libatk-1.0.so.0 libatk-bridge-2.0.so.0 libcups.so.2 libgio-2.0.so.0 libdrm.so.2 libdbus-1.so.3 libexpat.so.1 libxcb.so.1 libxkbcommon.so.0 libm.so.6 libX11.so.6 libXcomposite.so.1 libXdamage.so.1 libXext.so.6 libXfixes.so.3 libXrandr.so.2 libgbm.so.1 libpango-1.0.so.0 libcairo.so.2 libasound.so.2 libatspi.so.0 libgcc_s.so.1 libc.so.6 /lib64/ld-linux-x86-64.so.2 libgnutls.so.30 libpcre.so.1 libffi.so.6 libplc4.so libplds4.so librt.so.1 libgmodule-2.0.so.0 libgssapi_krb5.so.2 libkrb5.so.3 libk5crypto.so.3 libcom_err.so.2 libavahi-common.so.3 libavahi-client.so.3 libcrypt.so.1 libz.so.1 libselinux.so.1 libresolv.so.2 libmount.so.1 libsystemd.so.0 libXau.so.6 libXrender.so.1 libthai.so.0 libfribidi.so.0 libpixman-1.so.0 libfontconfig.so.1 libpng16.so.16 libxcb-render.so.0 libidn2.so.0 libunistring.so.2 libtasn1.so.6 libnettle.so.6 libhogweed.so.4 libgmp.so.10 libkrb5support.so.0 libkeyutils.so.1 libpcre2-8.so.0 libuuid.so.1 liblz4.so.1 libgcrypt.so.20 libbz2.so.1
|
||||
```
|
||||
|
||||
## Certificate signed by internal certificate authorities
|
||||
|
||||
In many cases, Grafana runs on internal servers and uses certificates that have not been signed by a CA ([Certificate Authority](https://en.wikipedia.org/wiki/Certificate_authority)) known to Chrome, and therefore cannot be validated. Chrome internally uses NSS ([Network Security Services](https://en.wikipedia.org/wiki/Network_Security_Services)) for cryptographic operations such as the validation of certificates.
|
||||
|
||||
@@ -278,6 +278,67 @@ To install plugins in the Grafana Helm Charts, complete the following steps:
|
||||
|
||||
1. Search for the above plugins and they should be marked as installed.
|
||||
|
||||
### Configure a Private CA (Certificate Authority)
|
||||
|
||||
In many enterprise networks, TLS certificates are issued by a private certificate authority and are not trusted by default (using the provided OS trust chain).
|
||||
|
||||
If your Grafana instance needs to interact with services exposing certificates issued by these private CAs, then you need to ensure Grafana trusts the root certificate.
|
||||
|
||||
You might need to configure this if you:
|
||||
|
||||
- have plugins that require connectivity to other self hosted systems. For example, if you've installed the Grafana Enterprise Metrics, Logs, or Traces (GEM, GEL, GET) plugins, and your GEM (or GEL/GET) cluster is using a private certificate.
|
||||
- want to connect to data sources which are listening on HTTPS with a private certificate.
|
||||
- are using a backend database for persistence, or caching service that uses private certificates for encryption in transit.
|
||||
|
||||
In some cases you can specify a self-signed certificate within Grafana (such as in some data sources), or choose to skip TLS certificate validation (this is not recommended unless absolutely necessary).
|
||||
|
||||
A simple solution which should work across your entire instance (plugins, data sources, and backend connections) is to add your self-signed CA certificate to your Kubernetes deployment.
|
||||
|
||||
1. Create a ConfigMap containing the certificate, and deploy it to your Kubernetes cluster
|
||||
|
||||
```yaml
|
||||
# grafana-ca-configmap.yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: grafana-ca-cert
|
||||
data:
|
||||
ca.pem: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
(rest of the CA cert)
|
||||
-----END CERTIFICATE-----
|
||||
```
|
||||
|
||||
```bash
|
||||
kubectl apply --filename grafana-ca-configmap.yaml --namespace monitoring
|
||||
```
|
||||
|
||||
1. Open the Helm `values.yaml` file in your favorite editor.
|
||||
|
||||
1. Find the line that says `extraConfigmapMounts:` and under that section, specify the additional ConfigMap that you want to mount.
|
||||
|
||||
```yaml
|
||||
.......
|
||||
............
|
||||
......
|
||||
extraConfigmapMounts:
|
||||
- name: ca-certs-configmap
|
||||
mountPath: /etc/ssl/certs/ca.pem
|
||||
subPath: ca.pem
|
||||
configMap: grafana-ca-cert
|
||||
readOnly: true
|
||||
.......
|
||||
............
|
||||
......
|
||||
```
|
||||
|
||||
1. Save the changes and use the `helm upgrade` command to update your Grafana deployment and mount the new ConfigMap:
|
||||
|
||||
```bash
|
||||
helm upgrade my-grafana grafana/grafana --values values.yaml --namespace monitoring
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
This section includes troubleshooting tips you might find helpful when deploying Grafana on Kubernetes via Helm.
|
||||
|
||||
115
docs/sources/upgrade-guide/when-to-upgrade/index.md
Normal file
115
docs/sources/upgrade-guide/when-to-upgrade/index.md
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
description: Strategies for upgrading your self-managed Grafana instance
|
||||
keywords:
|
||||
- grafana
|
||||
- configuration
|
||||
- documentation
|
||||
- upgrade
|
||||
title: Strategies for upgrading your self-managed Grafana instance
|
||||
menuTitle: Upgrade strategies
|
||||
weight: 1000
|
||||
---
|
||||
|
||||
# Strategies for upgrading your self-managed Grafana instance
|
||||
|
||||
At Grafana Labs, we believe in shipping features early and often, and in recent years we’ve increased our commitment to that philosophy.
|
||||
|
||||
We no longer wait for the yearly major release to give you access to the next big improvement. Instead, we regularly make new features, bug fixes, and security patches available to our self-managing users ([Grafana OSS](https://grafana.com/oss/grafana/) and [Grafana Enterprise](https://grafana.com/products/enterprise/)) throughout the year.
|
||||
|
||||
Having a dependable release process provides users like you with the best Grafana experience possible, and it provides the flexibility to upgrade in a manner that works best for you and your organization.
|
||||
|
||||
## What to expect from each release type
|
||||
|
||||
We split Grafana OSS and Grafana Enterprise releases into three main categories:
|
||||
|
||||
- **Minor release (every other month)**: These releases can include new features, deprecation notices, notices about upcoming breaking changes, previously announced breaking changes, bug fixes, and security vulnerability patches.
|
||||
- **Major release (once a year, in April/May)**: These are like a minor release, but accompanied by [GrafanaCON](https://grafana.com/events/grafanacon/) and a comprehensive upgrade guide for users who like to upgrade only once a year.
|
||||
- **Patching release (every month)**: These include bug fixes for currently supported versions, as well as any security vulnerability patches.
|
||||
|
||||
You can choose your cadence: For frequent self-managed updates, you should follow the minor release (for example, upgrade 10.1 to 10.2), which also gives you access to the latest features. If you need a longer period to review our new releases, you should follow the major releases. Both strategies get patching releases with security fixes (high severity security fixes also result in ad-hoc patch releases). We’ll get into additional guidance on upgrade cadences later in this guide.
|
||||
|
||||
## How to find the specifics for a release
|
||||
|
||||
We love sharing all our great features with you so you can leverage Grafana to its fullest. We also understand that great release documentation allows you to upgrade with confidence.
|
||||
Whether it’s knowing that a bug has been fixed, seeing that a security vulnerability is patched, or understanding how to mitigate the impact of breaking changes, proper documentation allows you to make informed decisions about when to upgrade your local Grafana instances.
|
||||
|
||||
We provide release documentation in multiple places to address different needs:
|
||||
|
||||
- [**What’s new**](https://grafana.com/docs/grafana/latest/whatsnew/?pg=blog&plcmt=body-txt) outlines new features debuting in each major and minor release.
|
||||
- [**Breaking changes**](https://grafana.com/docs/grafana/latest/breaking-changes/?pg=blog&plcmt=body-txt) notify you of updates included in major releases that could impact you and provide mitigation recommendations when needed.
|
||||
- [**Upgrade guides**](https://grafana.com/docs/grafana/latest/upgrade-guide/?pg=blog&plcmt=body-txt) instruct you on how to upgrade to a newer minor or major version.
|
||||
- And finally, a [**changelog**](https://github.com/grafana/grafana/blob/main/CHANGELOG.md) is generated for every release (major, minor, patching, security) and outlines all changes included in that release.
|
||||
|
||||
## When to expect releases
|
||||
|
||||
Currently, Grafana is on a monthly release cycle. Here’s a look at scheduled releases for 2024:
|
||||
|
||||
| **Anticipated release date** | **Grafana versions** | **Release type** |
|
||||
| ---------------------------- | -------------------- | ------------------ |
|
||||
| May 14, 2024 | 11 | Major and patching |
|
||||
| June 25, 2024 | 11.1 | Minor and patching |
|
||||
| July 23, 2024 | 11.1.x | Patching |
|
||||
| Aug. 27, 2024 | 11.2 | Minor and patching |
|
||||
| Sept. 24, 2024 | 11.2.x | Patching |
|
||||
| Oct. 22, 2024 | 11.3 | Minor and patching |
|
||||
| November/December 2024 | To be determined | To be determined |
|
||||
|
||||
### A few important notes
|
||||
|
||||
- The schedule above outlines how we plan release dates. However, unforeseen events and circumstances may cause dates to change.
|
||||
- High severity security and feature degradation incidents will result in ad-hoc releases that are not scheduled ahead of time.
|
||||
- Patching releases are for the current (last released) minor version of Grafana. Additional older versions of Grafana may be included if there is a critical bug or security vulnerability that needs to be patched.
|
||||
- A Grafana release freeze occurs for a week in November and again during the end of December. This does not apply to changes that may be required during the course of an operational or security incident.
|
||||
|
||||
## What to know about version support
|
||||
|
||||
Self-managed Grafana users have control over when they upgrade to a new version of Grafana. To help you make an informed decision about whether it's time to upgrade, it’s important that you understand the level of support provided for your current version.
|
||||
|
||||
For self-managed Grafana (both Enterprise and OSS), the support for versions is as follows:
|
||||
|
||||
- Support for each minor release extends to nine months after the release date.
|
||||
- Support for the last minor release of a major version is extended an additional six months, for a total of 15 months of support after the release date.
|
||||
|
||||
Here is an overview of projected version support through 2024:
|
||||
|
||||
| **Version** | **Release date** | **Support end of life (EOL)** |
|
||||
| ------------------------- | ----------------------- | ----------------------------- |
|
||||
| 10.3 | January 2024 | October 2024 |
|
||||
| 10.4 (Last minor of 10.0) | March 2024 | June 2025 (extended support) |
|
||||
| 11.0 | May 2024 | February 2025 |
|
||||
| 11.1 | June 2024 | March 2025 |
|
||||
| 11.2 | August 2024 (tentative) | May 2025 (tentative) |
|
||||
|
||||
{{< admonition type="note" >}}
|
||||
Grafana 9.5.x was the last supported minor for the 9.0 major release and is no longer supported as of July 2024.
|
||||
{{< /admonition >}}
|
||||
|
||||
## How are these versions supported?
|
||||
|
||||
The level of support changes as new versions of Grafana are released. Here are a few details to keep in mind:
|
||||
|
||||
- The current (most recently released) version of Grafana gets the highest level of support. Releases for this version include all the new features along with all bug fixes.
|
||||
- All supported versions receive security patches for vulnerabilities impacting that version.
|
||||
- All supported versions receive patches for bugs that cause critical feature degradation incidents.
|
||||
|
||||
Keeping all this in mind, users that want to receive the most recent features and all bug fixes should be on the current (most recently released) version of Grafana.
|
||||
|
||||
### What is a critical feature degradation?
|
||||
|
||||
A critical feature degradation usually meets one of the following criteria:
|
||||
|
||||
- Major functionality is universally unavailable (for example, cannot create dashboards, unable to authenticate).
|
||||
- Major (critical) impact to a significant amount of customers.
|
||||
- Major escalated incident for one or many customers.
|
||||
|
||||
## Self-managing upgrade strategies
|
||||
|
||||
Based on your needs, you can choose your ideal upgrade strategy. Here’s what that might look like in practice:
|
||||
|
||||
| **Strategy/cadence** | **Advantages/disadvantages** | **Example upgrade procedure** |
|
||||
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Minor / bi-monthly (11.1 to 11.2)** | Our recommended strategy. It combines up-to-date, secure releases with access to latest features as soon as they're released. <ul><li>Small changelog to review</li><li>Highest compatibility with actively maintained plugins</li><li>Easy migration to [Grafana Cloud](https://grafana.com/products/cloud)</li></ul> | <ul><li>**June 2024**: You review the 11.1 changelog and deploy the release to testing</li><li>**July 2024**: You deploy 11.1 to production</li><li>**August 2024**: 11.2 is released</li></ul> |
|
||||
| **Major / yearly (10.0 to 11.0)** | Yearly upgrade path that still gives access to up-to-date features presented at GrafanaCON.<ul><li>Big changelog to review</li><li>High compatibility with plugins</li><li>Relatively easy migration to [Grafana Cloud](https://grafana.com/products/cloud)</li></ul> | <ul><li>**April 2024**: 11.0 is released, you start a big changelog review</li><li>**May 2024**: You deploy 11.0 to testing</li><li>**June 2024**: You deploy 11.0 to production</li><li>**April 2025**: 12.0 is released</li></ul> |
|
||||
| **Previous major / yearly (9.5 to 10.4)** | Release with extended support timeline<ul><li>Limited compatibility with actively developed plugins</li><li>Big changelog to review</li><li>Migrations to Grafana Cloud might require professional support</li></ul> | <ul><li>**April 2024**: 11.0 is released, marking the previous minor (10.4.x) with extended support, you start a big changelog review (9.5.x to 10.4.x)</li><li>**May 2024**: You deploy 10.4.x to testing</li><li>**June 2024**: You deploy 10.4.x to production</li></ul> |
|
||||
|
||||
For each strategy, you should stay informed about patch releases that fix security vulnerabilities (released monthly, plus ad-hoc releases). Follow the “minor” strategy for the most flexibility, as you can also occasionally lengthen the cadence to a full quarter and still rely on your currently deployed minor release being supported with security fixes.
|
||||
7
go.mod
7
go.mod
@@ -143,7 +143,6 @@ require (
|
||||
github.com/redis/go-redis/v9 v9.1.0 // @grafana/alerting-backend
|
||||
github.com/robfig/cron/v3 v3.0.1 // @grafana/grafana-backend-group
|
||||
github.com/russellhaering/goxmldsig v1.4.0 // @grafana/grafana-backend-group
|
||||
github.com/scottlepp/go-duck v0.0.21 // @grafana/grafana-app-platform-squad
|
||||
github.com/spf13/cobra v1.8.1 // @grafana/grafana-app-platform-squad
|
||||
github.com/spf13/pflag v1.0.5 // @grafana-app-platform-squad
|
||||
github.com/spyzhov/ajson v0.9.0 // @grafana/grafana-app-platform-squad
|
||||
@@ -222,7 +221,6 @@ require (
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 // @grafana/grafana-search-and-storage
|
||||
github.com/FZambia/eagle v0.1.0 // indirect
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/RoaringBitmap/roaring v0.9.4 // indirect
|
||||
@@ -230,8 +228,6 @@ require (
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect
|
||||
github.com/apache/thrift v0.20.0 // indirect
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
@@ -345,7 +341,6 @@ require (
|
||||
github.com/jpillora/backoff v1.0.0 // indirect
|
||||
github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6 // indirect
|
||||
github.com/karlseguin/ccache/v3 v3.0.5 // indirect
|
||||
github.com/klauspost/asmfmt v1.3.2 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
@@ -361,8 +356,6 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||
github.com/miekg/dns v1.1.59 // indirect
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
|
||||
16
go.sum
16
go.sum
@@ -1462,7 +1462,6 @@ github.com/GoogleCloudPlatform/cloudsql-proxy v1.29.0/go.mod h1:spvB9eLJH9dutlbP
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
|
||||
github.com/KimMachineGun/automemlimit v0.6.0/go.mod h1:T7xYht7B8r6AG/AqFcUdc7fzd2bIdBKmepfP2S1svPY=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
@@ -1536,8 +1535,6 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20210223225224-5bea62493d91/go.mod h1:c9sxoIT3YgLxH4UhLOCKaBlEojuMhVYpk4Ntv3opUTQ=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 h1:q4dksr6ICHXqG5hm0ZW5IHyeEJXoIJSOZeBLmWPNeIQ=
|
||||
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs=
|
||||
github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
|
||||
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
|
||||
github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg=
|
||||
@@ -1549,14 +1546,10 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
|
||||
github.com/apache/thrift v0.17.0/go.mod h1:OLxhMRJxomX+1I/KUw03qoV3mMz16BwaKI+d4fPBx7Q=
|
||||
github.com/apache/thrift v0.20.0 h1:631+KvYbsBZxmuJjYwhezVsrfc/TbqtZV4QcxOX1fOI=
|
||||
github.com/apache/thrift v0.20.0/go.mod h1:hOk1BQqcp2OLzGsyVXdfMk7YFlMxK3aoEVhjD06QhB8=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
@@ -2176,7 +2169,6 @@ github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
|
||||
github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84=
|
||||
github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg=
|
||||
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI=
|
||||
@@ -2646,10 +2638,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
||||
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
|
||||
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
@@ -2785,9 +2775,7 @@ github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJys
|
||||
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
|
||||
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
|
||||
@@ -3021,7 +3009,6 @@ github.com/phpdave11/gofpdi v1.0.13 h1:o61duiW8M9sMlkVXWlvP92sZJtGKENvW3VExs6dZu
|
||||
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
@@ -3174,8 +3161,6 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.26 h1:F+GIVtGqCFxPxO46ujf8cEOP574MBoRm3gNbPXECbxs=
|
||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.26/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||
github.com/scottlepp/go-duck v0.0.21 h1:bFg5/8ULOo62vmvIjEOy1EOf7Q86cpzq82BDN5RakVE=
|
||||
github.com/scottlepp/go-duck v0.0.21/go.mod h1:m6V1VGZ4hdgvCj6+BmNMFo0taqiWhMx3CeL3uKHmP2E=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
|
||||
@@ -4331,7 +4316,6 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
|
||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U=
|
||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
|
||||
13
go.work.sum
13
go.work.sum
@@ -143,8 +143,6 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNL
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0 h1:gggzg0SUMs6SQbEw+3LoSsYf9YMjkupeAnHMX8O9mmY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
|
||||
github.com/Azure/azure-service-bus-go v0.11.5 h1:EVMicXGNrSX+rHRCBgm/TRQ4VUZ1m3yAYM/AB2R/SOs=
|
||||
github.com/Azure/go-amqp v0.16.4 h1:/1oIXrq5zwXLHaoYDliJyiFjJSpJZMWGgtMX9e0/Z30=
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk=
|
||||
@@ -164,6 +162,7 @@ github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dX
|
||||
github.com/GoogleCloudPlatform/cloudsql-proxy v1.29.0 h1:YNu23BtH0PKF+fg3ykSorCp6jSTjcEtfnYLzbmcjVRA=
|
||||
github.com/IBM/sarama v1.43.0 h1:YFFDn8mMI2QL0wOrG0J2sFoVIAFl7hS9JQi2YZsXtJc=
|
||||
github.com/IBM/sarama v1.43.0/go.mod h1:zlE6HEbC/SMQ9mhEYaF7nNLYOUyrs0obySKCckWP9BM=
|
||||
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
|
||||
github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
|
||||
github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
|
||||
github.com/KimMachineGun/automemlimit v0.6.0 h1:p/BXkH+K40Hax+PuWWPQ478hPjsp9h1CPDhLlA3Z37E=
|
||||
@@ -214,6 +213,8 @@ github.com/apache/arrow/go/v12 v12.0.1 h1:JsR2+hzYYjgSUkBSaahpqCetqZMr76djX80fF/
|
||||
github.com/apache/arrow/go/v13 v13.0.0 h1:kELrvDQuKZo8csdWYqBQfyi431x6Zs/YJTEgUuSVcWk=
|
||||
github.com/apache/arrow/go/v13 v13.0.0/go.mod h1:W69eByFNO0ZR30q1/7Sr9d83zcVZmF2MiP3fFYAWJOc=
|
||||
github.com/apache/arrow/go/v14 v14.0.2 h1:N8OkaJEOfI3mEZt07BIkvo4sC6XDbL+48MBPWO5IONw=
|
||||
github.com/apache/thrift v0.20.0 h1:631+KvYbsBZxmuJjYwhezVsrfc/TbqtZV4QcxOX1fOI=
|
||||
github.com/apache/thrift v0.20.0/go.mod h1:hOk1BQqcp2OLzGsyVXdfMk7YFlMxK3aoEVhjD06QhB8=
|
||||
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3 h1:ZSTrOEhiM5J5RFxEaFvMZVEAM1KvT1YzbEOwB2EAGjA=
|
||||
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
|
||||
@@ -392,8 +393,7 @@ github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs0
|
||||
github.com/google/go-jsonnet v0.18.0 h1:/6pTy6g+Jh1a1I2UMoAODkqELFiVIdOxbNwv0DDzoOg=
|
||||
github.com/google/go-jsonnet v0.18.0/go.mod h1:C3fTzyVJDslXdiTqw/bTFk7vSGyCtH3MGRbDfvEwGd0=
|
||||
github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9 h1:OF1IPgv+F4NmqmJ98KTjdN97Vs1JxDPB3vbmYzV2dpk=
|
||||
github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
|
||||
github.com/google/go-replayers/httpreplay v1.1.1 h1:H91sIMlt1NZzN7R+/ASswyouLJfW0WLW7fhyUFvDEkY=
|
||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
@@ -490,6 +490,8 @@ github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3ro
|
||||
github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY=
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46 h1:veS9QfglfvqAw2e+eeNT/SbGySq8ajECXJ9e4fPoLhY=
|
||||
github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4=
|
||||
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs=
|
||||
@@ -525,6 +527,9 @@ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvls
|
||||
github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
|
||||
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
|
||||
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI=
|
||||
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
|
||||
github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=
|
||||
github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc=
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||
"npmClient": "yarn",
|
||||
"version": "11.2.2"
|
||||
"version": "11.2.3"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"license": "AGPL-3.0-only",
|
||||
"private": true,
|
||||
"name": "grafana",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"repository": "github:grafana/grafana",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production nx exec --verbose -- webpack --config scripts/webpack/webpack.prod.js",
|
||||
@@ -400,7 +400,7 @@
|
||||
"tslib": "2.6.3",
|
||||
"tween-functions": "^1.2.0",
|
||||
"type-fest": "^4.18.2",
|
||||
"uplot": "1.6.30",
|
||||
"uplot": "1.6.31",
|
||||
"uuid": "9.0.1",
|
||||
"visjs-network": "4.25.0",
|
||||
"whatwg-fetch": "3.6.20",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/data",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana Data Library",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "7.0.1",
|
||||
"@grafana/schema": "11.2.2",
|
||||
"@grafana/schema": "11.2.3",
|
||||
"@types/d3-interpolate": "^3.0.0",
|
||||
"@types/string-hash": "1.1.3",
|
||||
"d3-interpolate": "3.0.1",
|
||||
@@ -57,7 +57,7 @@
|
||||
"string-hash": "^1.1.3",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tslib": "2.6.3",
|
||||
"uplot": "1.6.30",
|
||||
"uplot": "1.6.31",
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/e2e-selectors",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana End-to-End Test Selectors Library",
|
||||
"keywords": [
|
||||
"cli",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@grafana/eslint-plugin",
|
||||
"description": "ESLint rules for use within the Grafana repo. Not suitable (or supported) for external use.",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"main": "./index.cjs",
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/flamegraph",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana flamegraph visualization component",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -44,8 +44,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@emotion/css": "11.11.2",
|
||||
"@grafana/data": "11.2.2",
|
||||
"@grafana/ui": "11.2.2",
|
||||
"@grafana/data": "11.2.3",
|
||||
"@grafana/ui": "11.2.3",
|
||||
"@leeoniya/ufuzzy": "1.0.14",
|
||||
"d3": "^7.8.5",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@grafana/saga-icons",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"private": true,
|
||||
"description": "Icons for Grafana",
|
||||
"author": "Grafana Labs",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"license": "AGPL-3.0-only",
|
||||
"name": "@grafana/o11y-ds-frontend",
|
||||
"private": true,
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Library to manage traces in Grafana.",
|
||||
"sideEffects": false,
|
||||
"repository": {
|
||||
@@ -18,12 +18,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/css": "11.11.2",
|
||||
"@grafana/data": "11.2.2",
|
||||
"@grafana/e2e-selectors": "11.2.2",
|
||||
"@grafana/data": "11.2.3",
|
||||
"@grafana/e2e-selectors": "11.2.3",
|
||||
"@grafana/experimental": "1.7.13",
|
||||
"@grafana/runtime": "11.2.2",
|
||||
"@grafana/schema": "11.2.2",
|
||||
"@grafana/ui": "11.2.2",
|
||||
"@grafana/runtime": "11.2.3",
|
||||
"@grafana/schema": "11.2.3",
|
||||
"@grafana/ui": "11.2.3",
|
||||
"react-select": "5.8.0",
|
||||
"react-use": "17.5.1",
|
||||
"rxjs": "7.8.1",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@grafana/plugin-configs",
|
||||
"description": "Shared dependencies and files for core plugins",
|
||||
"private": true,
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"dependencies": {
|
||||
"tslib": "2.6.3"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "AGPL-3.0-only",
|
||||
"name": "@grafana/prometheus",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana Prometheus Library",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
@@ -38,12 +38,12 @@
|
||||
"dependencies": {
|
||||
"@emotion/css": "11.11.2",
|
||||
"@floating-ui/react": "0.26.22",
|
||||
"@grafana/data": "11.2.2",
|
||||
"@grafana/data": "11.2.3",
|
||||
"@grafana/experimental": "1.7.13",
|
||||
"@grafana/faro-web-sdk": "1.9.0",
|
||||
"@grafana/runtime": "11.2.2",
|
||||
"@grafana/schema": "11.2.2",
|
||||
"@grafana/ui": "11.2.2",
|
||||
"@grafana/runtime": "11.2.3",
|
||||
"@grafana/schema": "11.2.3",
|
||||
"@grafana/ui": "11.2.3",
|
||||
"@hello-pangea/dnd": "16.6.0",
|
||||
"@leeoniya/ufuzzy": "1.0.14",
|
||||
"@lezer/common": "1.2.1",
|
||||
@@ -76,7 +76,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/eslint-plugin": "11.11.0",
|
||||
"@grafana/e2e-selectors": "11.2.2",
|
||||
"@grafana/e2e-selectors": "11.2.3",
|
||||
"@grafana/tsconfig": "^1.3.0-rc1",
|
||||
"@rollup/plugin-image": "3.0.3",
|
||||
"@rollup/plugin-node-resolve": "15.2.3",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/runtime",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana Runtime Library",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -37,11 +37,11 @@
|
||||
"postpack": "mv package.json.bak package.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grafana/data": "11.2.2",
|
||||
"@grafana/e2e-selectors": "11.2.2",
|
||||
"@grafana/data": "11.2.3",
|
||||
"@grafana/e2e-selectors": "11.2.3",
|
||||
"@grafana/faro-web-sdk": "^1.3.6",
|
||||
"@grafana/schema": "11.2.2",
|
||||
"@grafana/ui": "11.2.2",
|
||||
"@grafana/schema": "11.2.3",
|
||||
"@grafana/ui": "11.2.3",
|
||||
"history": "4.10.1",
|
||||
"lodash": "4.17.21",
|
||||
"rxjs": "7.8.1",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/schema",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana Schema Library",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
limit: number;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends common.OptionsWithLegend, common.OptionsWithTooltip, common.OptionsWithTextFormatting {
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends common.SingleStatBaseOptions {
|
||||
displayMode: common.BarGaugeDisplayMode;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export enum VizDisplayMode {
|
||||
Candles = 'candles',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export enum HorizontalConstraint {
|
||||
Center = 'center',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface MetricStat {
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
selectedSeries: number;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export type UpdateConfig = {
|
||||
render: boolean,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export type BucketAggregation = (DateHistogram | Histogram | Terms | Filters | GeoHashGrid | Nested);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends common.SingleStatBaseOptions {
|
||||
minVizHeight: number;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
basemap: ui.MapLayerOptions;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
/**
|
||||
* Controls the color mode of the heatmap
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends common.OptionsWithLegend, common.OptionsWithTooltip {
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
dedupStrategy: common.LogsDedupStrategy;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export enum QueryEditorMode {
|
||||
Builder = 'builder',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface ArcOption {
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
/**
|
||||
* Select the pie chart display style.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends common.SingleStatBaseOptions {
|
||||
colorMode: common.BigValueColorMode;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends ui.OptionsWithLegend, ui.OptionsWithTooltip, ui.OptionsWithTimezones {
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends ui.OptionsWithLegend, ui.OptionsWithTooltip, ui.OptionsWithTimezones {
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as ui from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options {
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
// Run 'make gen-cue' from repository root to regenerate.
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export enum TextMode {
|
||||
Code = 'code',
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
export interface Options extends common.OptionsWithTimezones {
|
||||
legend: common.VizLegendOptions;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
/**
|
||||
* Identical to timeseries... except it does not have timezone settings
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import * as common from '@grafana/schema';
|
||||
|
||||
export const pluginVersion = "11.2.2";
|
||||
export const pluginVersion = "11.2.3";
|
||||
|
||||
/**
|
||||
* Auto is "table" in the UI
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"license": "AGPL-3.0-only",
|
||||
"private": true,
|
||||
"name": "@grafana/sql",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/grafana/grafana.git",
|
||||
@@ -15,11 +15,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/css": "11.11.2",
|
||||
"@grafana/data": "11.2.2",
|
||||
"@grafana/e2e-selectors": "11.2.2",
|
||||
"@grafana/data": "11.2.3",
|
||||
"@grafana/e2e-selectors": "11.2.3",
|
||||
"@grafana/experimental": "1.7.13",
|
||||
"@grafana/runtime": "11.2.2",
|
||||
"@grafana/ui": "11.2.2",
|
||||
"@grafana/runtime": "11.2.3",
|
||||
"@grafana/ui": "11.2.3",
|
||||
"@react-awesome-query-builder/ui": "6.6.2",
|
||||
"immutable": "4.3.7",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Grafana Labs",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@grafana/ui",
|
||||
"version": "11.2.2",
|
||||
"version": "11.2.3",
|
||||
"description": "Grafana Components Library",
|
||||
"keywords": [
|
||||
"grafana",
|
||||
@@ -50,10 +50,10 @@
|
||||
"@emotion/css": "11.11.2",
|
||||
"@emotion/react": "11.11.4",
|
||||
"@floating-ui/react": "0.26.22",
|
||||
"@grafana/data": "11.2.2",
|
||||
"@grafana/e2e-selectors": "11.2.2",
|
||||
"@grafana/data": "11.2.3",
|
||||
"@grafana/e2e-selectors": "11.2.3",
|
||||
"@grafana/faro-web-sdk": "^1.3.6",
|
||||
"@grafana/schema": "11.2.2",
|
||||
"@grafana/schema": "11.2.3",
|
||||
"@hello-pangea/dnd": "16.6.0",
|
||||
"@leeoniya/ufuzzy": "1.0.14",
|
||||
"@monaco-editor/react": "4.6.0",
|
||||
@@ -110,7 +110,7 @@
|
||||
"slate-react": "0.22.10",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tslib": "2.6.3",
|
||||
"uplot": "1.6.30",
|
||||
"uplot": "1.6.31",
|
||||
"uuid": "9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -32,7 +32,7 @@ export const AutoSizeInput = React.forwardRef<HTMLInputElement, Props>((props, r
|
||||
|
||||
// Update internal state when controlled `value` prop changes
|
||||
useEffect(() => {
|
||||
if (controlledValue !== undefined) {
|
||||
if (controlledValue) {
|
||||
setValue(controlledValue);
|
||||
}
|
||||
}, [controlledValue]);
|
||||
|
||||
@@ -637,6 +637,8 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
|
||||
if hs.Cfg.EnforceDomain {
|
||||
m.Use(middleware.ValidateHostHeader(hs.Cfg))
|
||||
}
|
||||
// handle action urls
|
||||
m.UseMiddleware(middleware.ValidateActionUrl(hs.Cfg, hs.log))
|
||||
|
||||
m.Use(middleware.HandleNoCacheHeaders)
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -30,6 +32,12 @@ func logError(message string, err error) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func RunCmdCLI(c *cli.Context) error {
|
||||
os.Exit(RunCmd())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunCmd runs the build command and returns the exit code
|
||||
func RunCmd() int {
|
||||
opts := BuildOptsFromFlags()
|
||||
|
||||
@@ -2,20 +2,6 @@ package main
|
||||
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
// ArgCountWrapper will cause the action to fail if there were not exactly `num` args provided.
|
||||
func ArgCountWrapper(num int, action cli.ActionFunc) cli.ActionFunc {
|
||||
return func(ctx *cli.Context) error {
|
||||
if ctx.NArg() != num {
|
||||
if err := cli.ShowSubcommandHelp(ctx); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
return cli.Exit("", 1)
|
||||
}
|
||||
|
||||
return action(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// ArgCountWrapper will cause the action to fail if there were more than `num` args provided.
|
||||
func MaxArgCountWrapper(max int, action cli.ActionFunc) cli.ActionFunc {
|
||||
return func(ctx *cli.Context) error {
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/compilers"
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/errutil"
|
||||
"github.com/grafana/grafana/pkg/build/grafana"
|
||||
"github.com/grafana/grafana/pkg/build/syncutil"
|
||||
)
|
||||
|
||||
func BuildBackend(ctx *cli.Context) error {
|
||||
metadata, err := config.GenerateMetadata(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
version := metadata.GrafanaVersion
|
||||
|
||||
var (
|
||||
edition = config.Edition(ctx.String("edition"))
|
||||
cfg = config.Config{
|
||||
NumWorkers: ctx.Int("jobs"),
|
||||
}
|
||||
)
|
||||
|
||||
buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get version / package info for mode '%s': %w", metadata.ReleaseMode.Mode, err)
|
||||
}
|
||||
|
||||
const grafanaDir = "."
|
||||
|
||||
log.Printf("Building Grafana back-end, version %q, %s edition, variants [%v]",
|
||||
version, edition, buildConfig.Variants)
|
||||
|
||||
p := syncutil.NewWorkerPool(cfg.NumWorkers)
|
||||
defer p.Close()
|
||||
|
||||
if err := compilers.Install(); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
g, _ := errutil.GroupWithContext(ctx.Context)
|
||||
for _, variant := range buildConfig.Variants {
|
||||
variant := variant
|
||||
|
||||
opts := grafana.BuildVariantOpts{
|
||||
Variant: variant,
|
||||
Edition: edition,
|
||||
Version: version,
|
||||
GrafanaDir: grafanaDir,
|
||||
}
|
||||
|
||||
p.Schedule(g.Wrap(func() error {
|
||||
return grafana.BuildVariant(ctx.Context, opts)
|
||||
}))
|
||||
}
|
||||
if err := g.Wait(); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
log.Println("Successfully built back-end binaries!")
|
||||
return nil
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/docker"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud"
|
||||
)
|
||||
|
||||
func BuildDocker(c *cli.Context) error {
|
||||
if err := docker.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
useUbuntu := c.Bool("ubuntu")
|
||||
buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
shouldSave := buildConfig.Docker.ShouldSave
|
||||
if shouldSave {
|
||||
if err := gcloud.ActivateServiceAccount(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
edition := config.Edition(c.String("edition"))
|
||||
|
||||
version := metadata.GrafanaVersion
|
||||
|
||||
log.Printf("Building Docker images, version %s, %s edition, Ubuntu based: %v...", version, edition,
|
||||
useUbuntu)
|
||||
|
||||
for _, arch := range buildConfig.Docker.Architectures {
|
||||
if _, err := docker.BuildImage(version, arch, ".", useUbuntu, shouldSave, edition, metadata.ReleaseMode.Mode); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Successfully built Docker images!")
|
||||
return nil
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/errutil"
|
||||
"github.com/grafana/grafana/pkg/build/frontend"
|
||||
"github.com/grafana/grafana/pkg/build/syncutil"
|
||||
)
|
||||
|
||||
func BuildFrontend(c *cli.Context) error {
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, mode, err := frontend.GetConfig(c, metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := syncutil.NewWorkerPool(cfg.NumWorkers)
|
||||
defer p.Close()
|
||||
|
||||
g, _ := errutil.GroupWithContext(c.Context)
|
||||
if err := frontend.Build(mode, frontend.GrafanaDir, p, g); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.Wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("Successfully built Grafana front-end!")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/errutil"
|
||||
"github.com/grafana/grafana/pkg/build/frontend"
|
||||
"github.com/grafana/grafana/pkg/build/syncutil"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func BuildFrontendPackages(c *cli.Context) error {
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg, mode, err := frontend.GetConfig(c, metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := syncutil.NewWorkerPool(cfg.NumWorkers)
|
||||
defer p.Close()
|
||||
|
||||
g, _ := errutil.GroupWithContext(c.Context)
|
||||
if err := frontend.BuildFrontendPackages(cfg.PackageVersion, mode, frontend.GrafanaDir, p, g); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
if err := g.Wait(); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
log.Println("Successfully built Grafana front-end packages!")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/errutil"
|
||||
"github.com/grafana/grafana/pkg/build/plugins"
|
||||
"github.com/grafana/grafana/pkg/build/syncutil"
|
||||
)
|
||||
|
||||
func BuildInternalPlugins(c *cli.Context) error {
|
||||
cfg := config.Config{
|
||||
NumWorkers: c.Int("jobs"),
|
||||
}
|
||||
|
||||
const grafanaDir = "."
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("Building internal Grafana plug-ins...")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
p := syncutil.NewWorkerPool(cfg.NumWorkers)
|
||||
defer p.Close()
|
||||
|
||||
var g *errutil.Group
|
||||
g, ctx = errutil.GroupWithContext(ctx)
|
||||
if err := plugins.Build(ctx, grafanaDir, p, g, buildConfig); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
if err := g.Wait(); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
if err := plugins.Download(ctx, grafanaDir, p); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
log.Println("Successfully built Grafana plug-ins!")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/env"
|
||||
"github.com/grafana/grafana/pkg/build/git"
|
||||
)
|
||||
|
||||
// checkOpts are options used to create a new GitHub check for the enterprise downstream test.
|
||||
type checkOpts struct {
|
||||
SHA string
|
||||
URL string
|
||||
Branch string
|
||||
PR int
|
||||
}
|
||||
|
||||
func getCheckOpts(args []string) (*checkOpts, error) {
|
||||
branch, ok := env.Lookup("DRONE_SOURCE_BRANCH", args)
|
||||
if !ok {
|
||||
return nil, cli.Exit("Unable to retrieve build source branch", 1)
|
||||
}
|
||||
|
||||
var (
|
||||
rgx = git.PRCheckRegexp()
|
||||
matches = rgx.FindStringSubmatch(branch)
|
||||
)
|
||||
|
||||
sha, ok := env.Lookup("SOURCE_COMMIT", args)
|
||||
if !ok {
|
||||
if matches == nil || len(matches) <= 1 {
|
||||
return nil, cli.Exit("Unable to retrieve source commit", 1)
|
||||
}
|
||||
sha = matches[2]
|
||||
}
|
||||
|
||||
url, ok := env.Lookup("DRONE_BUILD_LINK", args)
|
||||
if !ok {
|
||||
return nil, cli.Exit(`missing environment variable "DRONE_BUILD_LINK"`, 1)
|
||||
}
|
||||
|
||||
prStr, ok := env.Lookup("OSS_PULL_REQUEST", args)
|
||||
if !ok {
|
||||
if matches == nil || len(matches) <= 1 {
|
||||
return nil, cli.Exit("Unable to retrieve PR number", 1)
|
||||
}
|
||||
|
||||
prStr = matches[1]
|
||||
}
|
||||
|
||||
pr, err := strconv.Atoi(prStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &checkOpts{
|
||||
Branch: branch,
|
||||
PR: pr,
|
||||
SHA: sha,
|
||||
URL: url,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EnterpriseCheckBegin creates the GitHub check and signals the beginning of the downstream build / test process
|
||||
func EnterpriseCheckBegin(c *cli.Context) error {
|
||||
var (
|
||||
ctx = c.Context
|
||||
client = git.NewGitHubClient(ctx, c.String("github-token"))
|
||||
)
|
||||
|
||||
opts, err := getCheckOpts(os.Environ())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = git.CreateEnterpriseStatus(ctx, client.Repositories, opts.SHA, opts.URL, "pending"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func EnterpriseCheckSuccess(c *cli.Context) error {
|
||||
return completeEnterpriseCheck(c, true)
|
||||
}
|
||||
|
||||
func EnterpriseCheckFail(c *cli.Context) error {
|
||||
return completeEnterpriseCheck(c, false)
|
||||
}
|
||||
|
||||
func completeEnterpriseCheck(c *cli.Context, success bool) error {
|
||||
var (
|
||||
ctx = c.Context
|
||||
client = git.NewGitHubClient(ctx, c.String("github-token"))
|
||||
)
|
||||
|
||||
// Update the pull request labels
|
||||
opts, err := getCheckOpts(os.Environ())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
status := "failure"
|
||||
if success {
|
||||
status = "success"
|
||||
}
|
||||
|
||||
// Update the GitHub check...
|
||||
if _, err := git.CreateEnterpriseStatus(ctx, client.Repositories, opts.SHA, opts.URL, status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete branch if needed
|
||||
log.Printf("Checking branch '%s' against '%s'", git.PRCheckRegexp().String(), opts.Branch)
|
||||
if git.PRCheckRegexp().MatchString(opts.Branch) {
|
||||
log.Println("Deleting branch", opts.Branch)
|
||||
if err := git.DeleteEnterpriseBranch(ctx, client.Git, opts.Branch); err != nil {
|
||||
return fmt.Errorf("error deleting enterprise branch: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
label := "enterprise-failed"
|
||||
if success {
|
||||
label = "enterprise-ok"
|
||||
}
|
||||
|
||||
return git.AddLabelToPR(ctx, client.Issues, opts.PR, label)
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetCheckOpts(t *testing.T) {
|
||||
t.Run("it should return the checkOpts if the correct environment variables are set", func(t *testing.T) {
|
||||
args := []string{
|
||||
"SOURCE_COMMIT=1234",
|
||||
"DRONE_SOURCE_BRANCH=test",
|
||||
"DRONE_BUILD_LINK=http://example.com",
|
||||
"OSS_PULL_REQUEST=1",
|
||||
}
|
||||
|
||||
opts, err := getCheckOpts(args)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, opts.SHA, "1234")
|
||||
require.Equal(t, opts.URL, "http://example.com")
|
||||
})
|
||||
t.Run("it should return an error if SOURCE_COMMIT is not set", func(t *testing.T) {
|
||||
args := []string{
|
||||
"DRONE_BUILD_LINK=http://example.com",
|
||||
"DRONE_SOURCE_BRANCH=test",
|
||||
"DRONE_BUILD_LINK=http://example.com",
|
||||
"OSS_PULL_REQUEST=1",
|
||||
}
|
||||
|
||||
opts, err := getCheckOpts(args)
|
||||
require.Nil(t, opts)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("it should return an error if DRONE_BUILD_LINK is not set", func(t *testing.T) {
|
||||
args := []string{
|
||||
"SOURCE_COMMIT=1234",
|
||||
"DRONE_SOURCE_BRANCH=test",
|
||||
"OSS_PULL_REQUEST=1",
|
||||
}
|
||||
|
||||
opts, err := getCheckOpts(args)
|
||||
require.Nil(t, opts)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("it should return an error if OSS_PULL_REQUEST is not set", func(t *testing.T) {
|
||||
args := []string{
|
||||
"SOURCE_COMMIT=1234",
|
||||
"DRONE_SOURCE_BRANCH=test",
|
||||
"DRONE_BUILD_LINK=http://example.com",
|
||||
}
|
||||
|
||||
opts, err := getCheckOpts(args)
|
||||
require.Nil(t, opts)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("it should return an error if OSS_PULL_REQUEST is not an integer", func(t *testing.T) {
|
||||
args := []string{
|
||||
"SOURCE_COMMIT=1234",
|
||||
"DRONE_SOURCE_BRANCH=test",
|
||||
"DRONE_BUILD_LINK=http://example.com",
|
||||
"OSS_PULL_REQUEST=http://example.com",
|
||||
}
|
||||
|
||||
opts, err := getCheckOpts(args)
|
||||
require.Nil(t, opts)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
)
|
||||
|
||||
func ExportVersion(c *cli.Context) error {
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
const distDir = "dist"
|
||||
if err := os.RemoveAll(distDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Mkdir(distDir, 0750); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint:gosec
|
||||
if err := os.WriteFile(filepath.Join(distDir, "grafana.version"), []byte(metadata.GrafanaVersion), 0664); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
@@ -18,6 +18,25 @@ const (
|
||||
ubuntu = "ubuntu"
|
||||
)
|
||||
|
||||
// GetImageFiles returns the list of image (.img, but should be .tar because they are tar archives) files that are
|
||||
// created in the 'tag' process and stored in the prerelease bucket, waiting to be released.
|
||||
func GetImageFiles(grafana string, version string, architectures []config.Architecture) []string {
|
||||
bases := []string{alpine, ubuntu}
|
||||
images := []string{}
|
||||
for _, base := range bases {
|
||||
for _, arch := range architectures {
|
||||
image := fmt.Sprintf("%s-%s-%s.img", grafana, version, arch)
|
||||
if base == "ubuntu" {
|
||||
image = fmt.Sprintf("%s-%s-ubuntu-%s.img", grafana, version, arch)
|
||||
}
|
||||
|
||||
images = append(images, image)
|
||||
}
|
||||
}
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
func FetchImages(c *cli.Context) error {
|
||||
if c.NArg() > 0 {
|
||||
if err := cli.ShowSubcommandHelp(c); err != nil {
|
||||
@@ -44,74 +63,65 @@ func FetchImages(c *cli.Context) error {
|
||||
Tag: metadata.GrafanaVersion,
|
||||
}
|
||||
|
||||
edition := fmt.Sprintf("-%s", cfg.Edition)
|
||||
grafana := "grafana"
|
||||
if cfg.Edition == "enterprise" {
|
||||
grafana = "grafana-enterprise"
|
||||
}
|
||||
if cfg.Edition == "enterprise2" {
|
||||
grafana = "grafana-enterprise2"
|
||||
}
|
||||
if cfg.Edition == "grafana" || cfg.Edition == "oss" {
|
||||
grafana = "grafana-oss"
|
||||
}
|
||||
|
||||
err = gcloud.ActivateServiceAccount()
|
||||
if err != nil {
|
||||
baseURL := fmt.Sprintf("gs://%s/%s/", cfg.Bucket, cfg.Tag)
|
||||
images := GetImageFiles(grafana, cfg.Tag, cfg.Archs)
|
||||
|
||||
log.Printf("Fetching images [%v]", images)
|
||||
|
||||
if err := gcloud.ActivateServiceAccount(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var basesStr []string
|
||||
for _, base := range cfg.Distribution {
|
||||
switch base {
|
||||
case alpine:
|
||||
basesStr = append(basesStr, "")
|
||||
case ubuntu:
|
||||
basesStr = append(basesStr, "-ubuntu")
|
||||
default:
|
||||
return fmt.Errorf("unrecognized base %q", base)
|
||||
}
|
||||
}
|
||||
|
||||
err = downloadFromGCS(cfg, basesStr, edition)
|
||||
if err != nil {
|
||||
if err := DownloadImages(baseURL, images, "."); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = loadImages(cfg, basesStr, edition)
|
||||
if err != nil {
|
||||
if err := LoadImages(images, "."); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadImages(cfg docker.Config, basesStr []string, edition string) error {
|
||||
log.Println("Loading fetched image files to local docker registry...")
|
||||
log.Printf("Number of images to be loaded: %d\n", len(basesStr)*len(cfg.Archs))
|
||||
for _, base := range basesStr {
|
||||
for _, arch := range cfg.Archs {
|
||||
imageFilename := fmt.Sprintf("grafana%s-%s%s-%s.img", edition, cfg.Tag, base, arch)
|
||||
log.Printf("image file name: %s\n", imageFilename)
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("docker", "load", "-i", imageFilename)
|
||||
cmd.Dir = "."
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf("out: %s\n", out)
|
||||
return fmt.Errorf("error loading image: %q", err)
|
||||
}
|
||||
log.Printf("Successfully loaded %s!\n %s\n", fmt.Sprintf("grafana%s-%s%s-%s", edition, cfg.Tag, base, arch), out)
|
||||
// LoadImages uses the `docker load -i` command to load the image tar file into the docker daemon so that it can be
|
||||
// tagged and pushed.
|
||||
func LoadImages(images []string, source string) error {
|
||||
p := filepath.Clean(source)
|
||||
for _, image := range images {
|
||||
image := filepath.Join(p, image)
|
||||
log.Println("Loading image", image)
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("docker", "load", "-i", image)
|
||||
cmd.Dir = "."
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf("out: %s\n", out)
|
||||
return fmt.Errorf("error loading image: %q", err)
|
||||
}
|
||||
log.Println("Loaded image", image)
|
||||
}
|
||||
log.Println("Images successfully loaded!")
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadFromGCS(cfg docker.Config, basesStr []string, edition string) error {
|
||||
log.Printf("Downloading Docker images from GCS bucket: %s\n", cfg.Bucket)
|
||||
|
||||
for _, base := range basesStr {
|
||||
for _, arch := range cfg.Archs {
|
||||
src := fmt.Sprintf("gs://%s/%s/grafana%s-%s%s-%s.img", cfg.Bucket, cfg.Tag, edition, cfg.Tag, base, arch)
|
||||
args := strings.Split(fmt.Sprintf("-m cp -r %s .", src), " ")
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("gsutil", args...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download: %w\n%s", err, out)
|
||||
}
|
||||
func DownloadImages(baseURL string, images []string, destination string) error {
|
||||
for _, image := range images {
|
||||
p := baseURL + image
|
||||
log.Println("Downloading image", p)
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("gsutil", "-m", "cp", "-r", p, destination)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download: %w\n%s", err, out)
|
||||
}
|
||||
}
|
||||
log.Printf("Successfully fetched image files from %s bucket!\n", cfg.Bucket)
|
||||
return nil
|
||||
}
|
||||
|
||||
48
pkg/build/cmd/fetchimages_test.go
Normal file
48
pkg/build/cmd/fetchimages_test.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetImageFiles(t *testing.T) {
|
||||
var (
|
||||
architectures = []config.Architecture{
|
||||
config.ArchAMD64,
|
||||
config.ArchARM64,
|
||||
config.ArchARMv7,
|
||||
}
|
||||
)
|
||||
|
||||
t.Run("1.2.3", func(t *testing.T) {
|
||||
expect := []string{
|
||||
"grafana-oss-1.2.3-amd64.img",
|
||||
"grafana-oss-1.2.3-arm64.img",
|
||||
"grafana-oss-1.2.3-armv7.img",
|
||||
"grafana-oss-1.2.3-ubuntu-amd64.img",
|
||||
"grafana-oss-1.2.3-ubuntu-arm64.img",
|
||||
"grafana-oss-1.2.3-ubuntu-armv7.img",
|
||||
}
|
||||
|
||||
res := GetImageFiles("grafana-oss", "1.2.3", architectures)
|
||||
|
||||
require.Equal(t, expect, res)
|
||||
})
|
||||
|
||||
t.Run("1.2.3+example-01", func(t *testing.T) {
|
||||
expect := []string{
|
||||
"grafana-oss-1.2.3+example-01-amd64.img",
|
||||
"grafana-oss-1.2.3+example-01-arm64.img",
|
||||
"grafana-oss-1.2.3+example-01-armv7.img",
|
||||
"grafana-oss-1.2.3+example-01-ubuntu-amd64.img",
|
||||
"grafana-oss-1.2.3+example-01-ubuntu-arm64.img",
|
||||
"grafana-oss-1.2.3+example-01-ubuntu-armv7.img",
|
||||
}
|
||||
|
||||
res := GetImageFiles("grafana-oss", "1.2.3+example-01", architectures)
|
||||
|
||||
require.Equal(t, expect, res)
|
||||
})
|
||||
}
|
||||
@@ -16,37 +16,15 @@ var (
|
||||
Usage: "The edition of Grafana to build (oss or enterprise)",
|
||||
Value: "oss",
|
||||
}
|
||||
variantsFlag = cli.StringFlag{
|
||||
Name: "variants",
|
||||
Usage: "Comma-separated list of variants to build",
|
||||
}
|
||||
triesFlag = cli.IntFlag{
|
||||
Name: "tries",
|
||||
Usage: "Specify number of tries before failing",
|
||||
Value: 1,
|
||||
}
|
||||
noInstallDepsFlag = cli.BoolFlag{
|
||||
Name: "no-install-deps",
|
||||
Usage: "Don't install dependencies",
|
||||
}
|
||||
signingAdminFlag = cli.BoolFlag{
|
||||
Name: "signing-admin",
|
||||
Usage: "Use manifest signing admin API endpoint?",
|
||||
}
|
||||
signFlag = cli.BoolFlag{
|
||||
Name: "sign",
|
||||
Usage: "Enable plug-in signing (you must set GRAFANA_API_KEY)",
|
||||
}
|
||||
dryRunFlag = cli.BoolFlag{
|
||||
Name: "dry-run",
|
||||
Usage: "Only simulate actions",
|
||||
}
|
||||
gitHubTokenFlag = cli.StringFlag{
|
||||
Name: "github-token",
|
||||
Value: "",
|
||||
EnvVars: []string{"GITHUB_TOKEN"},
|
||||
Usage: "GitHub token",
|
||||
}
|
||||
tagFlag = cli.StringFlag{
|
||||
Name: "tag",
|
||||
Usage: "Grafana version tag",
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud/storage"
|
||||
"github.com/grafana/grafana/pkg/build/gcom"
|
||||
"github.com/grafana/grafana/pkg/build/packaging"
|
||||
)
|
||||
|
||||
@@ -125,6 +126,51 @@ func getReleaseURLs() (string, string, error) {
|
||||
return pconf.Grafana.WhatsNewURL, pconf.Grafana.ReleaseNotesURL, nil
|
||||
}
|
||||
|
||||
func Builds(baseURL *url.URL, grafana, version string, packages []packaging.BuildArtifact) ([]GCOMPackage, error) {
|
||||
builds := make([]GCOMPackage, len(packages))
|
||||
for i, v := range packages {
|
||||
var (
|
||||
os = v.Distro
|
||||
arch = v.Arch
|
||||
)
|
||||
|
||||
if v.Distro == "windows" {
|
||||
os = "win"
|
||||
if v.Ext == "msi" {
|
||||
os = "win-installer"
|
||||
}
|
||||
}
|
||||
|
||||
if v.Distro == "rhel" {
|
||||
if arch == "aarch64" {
|
||||
arch = "arm64"
|
||||
}
|
||||
if arch == "x86_64" {
|
||||
arch = "amd64"
|
||||
}
|
||||
}
|
||||
|
||||
if v.Distro == "deb" {
|
||||
if arch == "armhf" {
|
||||
arch = "armv7"
|
||||
if v.RaspberryPi {
|
||||
log.Println(v.Distro, arch, "raspberrypi == true")
|
||||
arch = "armv6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u := gcom.GetURL(baseURL, version, grafana, v.Distro, v.Arch, v.Ext, v.Musl, v.RaspberryPi)
|
||||
builds[i] = GCOMPackage{
|
||||
OS: os,
|
||||
URL: u.String(),
|
||||
Arch: arch,
|
||||
}
|
||||
}
|
||||
|
||||
return builds, nil
|
||||
}
|
||||
|
||||
// publishPackages publishes packages to grafana.com.
|
||||
func publishPackages(cfg packaging.PublishConfig) error {
|
||||
log.Printf("Publishing Grafana packages, version %s, %s edition, %s mode, dryRun: %v, simulating: %v...\n",
|
||||
@@ -133,14 +179,17 @@ func publishPackages(cfg packaging.PublishConfig) error {
|
||||
versionStr := fmt.Sprintf("v%s", cfg.Version)
|
||||
log.Printf("Creating release %s at grafana.com...\n", versionStr)
|
||||
|
||||
var sfx string
|
||||
var pth string
|
||||
var (
|
||||
pth string
|
||||
grafana = "grafana"
|
||||
)
|
||||
|
||||
switch cfg.Edition {
|
||||
case config.EditionOSS:
|
||||
pth = "oss"
|
||||
case config.EditionEnterprise:
|
||||
grafana = "grafana-enterprise"
|
||||
pth = "enterprise"
|
||||
sfx = packaging.EnterpriseSfx
|
||||
default:
|
||||
return fmt.Errorf("unrecognized edition %q", cfg.Edition)
|
||||
}
|
||||
@@ -152,28 +201,19 @@ func publishPackages(cfg packaging.PublishConfig) error {
|
||||
pth = path.Join(pth, packaging.ReleaseFolder)
|
||||
}
|
||||
|
||||
product := fmt.Sprintf("grafana%s", sfx)
|
||||
pth = path.Join(pth, product)
|
||||
baseArchiveURL := fmt.Sprintf("https://dl.grafana.com/%s", pth)
|
||||
|
||||
builds := make([]buildRepr, len(packaging.ArtifactConfigs))
|
||||
for i, ba := range packaging.ArtifactConfigs {
|
||||
u := ba.GetURL(baseArchiveURL, cfg)
|
||||
|
||||
sha256, err := getSHA256(u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
builds[i] = buildRepr{
|
||||
OS: ba.Os,
|
||||
URL: u,
|
||||
SHA256: string(sha256),
|
||||
Arch: ba.Arch,
|
||||
}
|
||||
pth = path.Join(pth)
|
||||
baseArchiveURL := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "dl.grafana.com",
|
||||
Path: pth,
|
||||
}
|
||||
|
||||
r := releaseRepr{
|
||||
builds, err := Builds(baseArchiveURL, grafana, cfg.Version, packaging.ArtifactConfigs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := Release{
|
||||
Version: cfg.Version,
|
||||
ReleaseDate: time.Now().UTC(),
|
||||
Builds: builds,
|
||||
@@ -195,6 +235,15 @@ func publishPackages(cfg packaging.PublishConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, v := range r.Builds {
|
||||
sha, err := getSHA256(v.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Builds[i].SHA256 = string(sha)
|
||||
}
|
||||
|
||||
for _, b := range r.Builds {
|
||||
if err := postRequest(cfg, fmt.Sprintf("versions/%s/packages", cfg.Version), b,
|
||||
fmt.Sprintf("create build %s %s", b.OS, b.Arch)); err != nil {
|
||||
@@ -211,6 +260,7 @@ func publishPackages(cfg packaging.PublishConfig) error {
|
||||
|
||||
func getSHA256(u string) ([]byte, error) {
|
||||
shaURL := fmt.Sprintf("%s.sha256", u)
|
||||
|
||||
// nolint:gosec
|
||||
resp, err := http.Get(shaURL)
|
||||
if err != nil {
|
||||
@@ -232,7 +282,7 @@ func getSHA256(u string) ([]byte, error) {
|
||||
return sha256, nil
|
||||
}
|
||||
|
||||
func postRequest(cfg packaging.PublishConfig, pth string, obj any, descr string) error {
|
||||
func postRequest(cfg packaging.PublishConfig, pth string, body any, descr string) error {
|
||||
var sfx string
|
||||
switch cfg.Edition {
|
||||
case config.EditionOSS:
|
||||
@@ -243,7 +293,7 @@ func postRequest(cfg packaging.PublishConfig, pth string, obj any, descr string)
|
||||
}
|
||||
product := fmt.Sprintf("grafana%s", sfx)
|
||||
|
||||
jsonB, err := json.Marshal(obj)
|
||||
jsonB, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to JSON encode release: %w", err)
|
||||
}
|
||||
@@ -303,20 +353,20 @@ func constructURL(product string, pth string) (string, error) {
|
||||
return u.String(), err
|
||||
}
|
||||
|
||||
type buildRepr struct {
|
||||
type GCOMPackage struct {
|
||||
OS string `json:"os"`
|
||||
URL string `json:"url"`
|
||||
SHA256 string `json:"sha256"`
|
||||
Arch string `json:"arch"`
|
||||
}
|
||||
|
||||
type releaseRepr struct {
|
||||
Version string `json:"version"`
|
||||
ReleaseDate time.Time `json:"releaseDate"`
|
||||
Stable bool `json:"stable"`
|
||||
Beta bool `json:"beta"`
|
||||
Nightly bool `json:"nightly"`
|
||||
WhatsNewURL string `json:"whatsNewUrl"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
Builds []buildRepr `json:"-"`
|
||||
type Release struct {
|
||||
Version string `json:"version"`
|
||||
ReleaseDate time.Time `json:"releaseDate"`
|
||||
Stable bool `json:"stable"`
|
||||
Beta bool `json:"beta"`
|
||||
Nightly bool `json:"nightly"`
|
||||
WhatsNewURL string `json:"whatsNewUrl"`
|
||||
ReleaseNotesURL string `json:"releaseNotesUrl"`
|
||||
Builds []GCOMPackage `json:"-"`
|
||||
}
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/packaging"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_constructURL(t *testing.T) {
|
||||
@@ -33,3 +40,221 @@ func Test_constructURL(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilds(t *testing.T) {
|
||||
baseURL := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "dl.example.com",
|
||||
Path: path.Join("oss", "release"),
|
||||
}
|
||||
|
||||
version := "1.2.3"
|
||||
grafana := "grafana"
|
||||
packages := []packaging.BuildArtifact{
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "arm64",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "rhel",
|
||||
Arch: "aarch64",
|
||||
Ext: "rpm",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "arm64",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
RaspberryPi: true,
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "armv7",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "zip",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "msi",
|
||||
},
|
||||
}
|
||||
|
||||
expect := []GCOMPackage{
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3_arm64.deb",
|
||||
OS: "deb",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3-1.aarch64.rpm",
|
||||
OS: "rhel",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.linux-arm64.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-rpi_1.2.3_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv6",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.linux-armv7.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.windows-amd64.zip",
|
||||
OS: "win",
|
||||
Arch: "amd64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3.windows-amd64.msi",
|
||||
OS: "win-installer",
|
||||
Arch: "amd64",
|
||||
},
|
||||
}
|
||||
|
||||
builds, err := Builds(baseURL, grafana, version, packages)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expect), len(builds))
|
||||
|
||||
for i := range builds {
|
||||
t.Run(fmt.Sprintf("[%d/%d] %s", i+1, len(builds), expect[i].URL), func(t *testing.T) {
|
||||
assert.Equal(t, expect[i].URL, builds[i].URL)
|
||||
assert.Equal(t, expect[i].OS, builds[i].OS)
|
||||
assert.Equal(t, expect[i].Arch, builds[i].Arch)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildsWithPlus(t *testing.T) {
|
||||
baseURL := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "dl.example.com",
|
||||
Path: path.Join("oss", "release"),
|
||||
}
|
||||
|
||||
version := "1.2.3+example-01"
|
||||
grafana := "grafana"
|
||||
packages := []packaging.BuildArtifact{
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "arm64",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "rhel",
|
||||
Arch: "aarch64",
|
||||
Ext: "rpm",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "arm64",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
RaspberryPi: true,
|
||||
},
|
||||
{
|
||||
Distro: "deb",
|
||||
Arch: "armhf",
|
||||
Ext: "deb",
|
||||
},
|
||||
{
|
||||
Distro: "linux",
|
||||
Arch: "armv7",
|
||||
Ext: "tar.gz",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "zip",
|
||||
},
|
||||
{
|
||||
Distro: "windows",
|
||||
Arch: "amd64",
|
||||
Ext: "msi",
|
||||
},
|
||||
}
|
||||
|
||||
expect := []GCOMPackage{
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3+example~01_arm64.deb",
|
||||
OS: "deb",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example~01-1.aarch64.rpm",
|
||||
OS: "rhel",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.linux-arm64.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "arm64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-rpi_1.2.3+example~01_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv6",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana_1.2.3+example~01_armhf.deb",
|
||||
OS: "deb",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.linux-armv7.tar.gz",
|
||||
OS: "linux",
|
||||
Arch: "armv7",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.windows-amd64.zip",
|
||||
OS: "win",
|
||||
Arch: "amd64",
|
||||
},
|
||||
{
|
||||
URL: "https://dl.example.com/oss/release/grafana-1.2.3+example-01.windows-amd64.msi",
|
||||
OS: "win-installer",
|
||||
Arch: "amd64",
|
||||
},
|
||||
}
|
||||
|
||||
builds, err := Builds(baseURL, grafana, version, packages)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expect), len(builds))
|
||||
|
||||
for i := range builds {
|
||||
t.Run(fmt.Sprintf("[%d/%d] %s", i+1, len(builds), expect[i].URL), func(t *testing.T) {
|
||||
assert.Equal(t, expect[i].URL, builds[i].URL)
|
||||
assert.Equal(t, expect[i].OS, builds[i].OS)
|
||||
assert.Equal(t, expect[i].Arch, builds[i].Arch)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/docker"
|
||||
)
|
||||
|
||||
var additionalCommands []*cli.Command = make([]*cli.Command, 0, 5)
|
||||
@@ -21,28 +19,8 @@ func main() {
|
||||
app := cli.NewApp()
|
||||
app.Commands = cli.Commands{
|
||||
{
|
||||
Name: "build-backend",
|
||||
Usage: "Build one or more variants of back-end binaries",
|
||||
ArgsUsage: "[version]",
|
||||
Action: MaxArgCountWrapper(1, BuildBackend),
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&variantsFlag,
|
||||
&editionFlag,
|
||||
&buildIDFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "build-frontend-packages",
|
||||
Usage: "Build front-end packages",
|
||||
ArgsUsage: "[version]",
|
||||
Action: BuildFrontendPackages,
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&editionFlag,
|
||||
&buildIDFlag,
|
||||
&noInstallDepsFlag,
|
||||
},
|
||||
Name: "build",
|
||||
Action: build.RunCmdCLI,
|
||||
},
|
||||
{
|
||||
Name: "e2e-tests",
|
||||
@@ -71,44 +49,11 @@ func main() {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "build-frontend",
|
||||
Usage: "Build front-end artifacts",
|
||||
ArgsUsage: "[version]",
|
||||
Action: MaxArgCountWrapper(1, BuildFrontend),
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&editionFlag,
|
||||
&buildIDFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "whatsnew-checker",
|
||||
Usage: "Checks whatsNewUrl in package.json for differences between the tag and the docs version",
|
||||
Action: WhatsNewChecker,
|
||||
},
|
||||
{
|
||||
Name: "build-docker",
|
||||
Usage: "Build Grafana Docker images",
|
||||
Action: MaxArgCountWrapper(1, BuildDocker),
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&editionFlag,
|
||||
&cli.BoolFlag{
|
||||
Name: "ubuntu",
|
||||
Usage: "Use Ubuntu base image",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "shouldSave",
|
||||
Usage: "Should save docker image to tarball",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "archs",
|
||||
Value: strings.Join(docker.AllArchs, ","),
|
||||
Usage: "Comma separated architectures to build",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "upload-cdn",
|
||||
Usage: "Upload public/* to a cdn bucket",
|
||||
@@ -117,23 +62,6 @@ func main() {
|
||||
&editionFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "shellcheck",
|
||||
Usage: "Run shellcheck on shell scripts",
|
||||
Action: Shellcheck,
|
||||
},
|
||||
{
|
||||
Name: "build-plugins",
|
||||
Usage: "Build internal plug-ins",
|
||||
Action: MaxArgCountWrapper(1, BuildInternalPlugins),
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&editionFlag,
|
||||
&signingAdminFlag,
|
||||
&signFlag,
|
||||
&noInstallDepsFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "publish-metrics",
|
||||
Usage: "Publish a set of metrics from stdin",
|
||||
@@ -145,30 +73,6 @@ func main() {
|
||||
Usage: "Verify Drone configuration",
|
||||
Action: VerifyDrone,
|
||||
},
|
||||
{
|
||||
Name: "verify-starlark",
|
||||
Usage: "Verify Starlark configuration",
|
||||
ArgsUsage: "<workspace path>",
|
||||
Action: VerifyStarlark,
|
||||
},
|
||||
{
|
||||
Name: "export-version",
|
||||
Usage: "Exports version in dist/grafana.version",
|
||||
Action: ExportVersion,
|
||||
},
|
||||
{
|
||||
Name: "package",
|
||||
Usage: "Package one or more Grafana variants",
|
||||
ArgsUsage: "[version]",
|
||||
Action: MaxArgCountWrapper(1, Package),
|
||||
Flags: []cli.Flag{
|
||||
&jobsFlag,
|
||||
&variantsFlag,
|
||||
&editionFlag,
|
||||
&buildIDFlag,
|
||||
&signFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "store-storybook",
|
||||
Usage: "Stores storybook to GCS buckets",
|
||||
@@ -279,18 +183,6 @@ func main() {
|
||||
&editionFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "publish-enterprise2",
|
||||
Usage: "Handle Grafana Enterprise2 Docker images",
|
||||
ArgsUsage: "[version]",
|
||||
Action: Enterprise2,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "dockerhub-repo",
|
||||
Usage: "DockerHub repo to push images",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -399,36 +291,6 @@ func main() {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "enterprise-check",
|
||||
Usage: "Commands for testing against Grafana Enterprise",
|
||||
Subcommands: cli.Commands{
|
||||
{
|
||||
Name: "begin",
|
||||
Usage: "Creates the GitHub check in a pull request and begins the tests",
|
||||
Action: EnterpriseCheckBegin,
|
||||
Flags: []cli.Flag{
|
||||
&gitHubTokenFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "success",
|
||||
Usage: "Updates the GitHub check in a pull request to show a successful build and updates the pull request labels",
|
||||
Action: EnterpriseCheckSuccess,
|
||||
Flags: []cli.Flag{
|
||||
&gitHubTokenFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fail",
|
||||
Usage: "Updates the GitHub check in a pull request to show a failed build and updates the pull request labels",
|
||||
Action: EnterpriseCheckFail,
|
||||
Flags: []cli.Flag{
|
||||
&gitHubTokenFlag,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
app.Commands = append(app.Commands, additionalCommands...)
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -23,6 +24,11 @@ func NpmRetrieveAction(c *cli.Context) error {
|
||||
return fmt.Errorf("no tag version specified, exitting")
|
||||
}
|
||||
|
||||
if strings.Contains(tag, "security") {
|
||||
log.Printf("skipping npm publish because version '%s' has 'security'", tag)
|
||||
return nil
|
||||
}
|
||||
|
||||
prereleaseBucket := strings.TrimSpace(os.Getenv("PRERELEASE_BUCKET"))
|
||||
if prereleaseBucket == "" {
|
||||
return cli.Exit("the environment variable PRERELEASE_BUCKET must be set", 1)
|
||||
@@ -48,6 +54,11 @@ func NpmStoreAction(c *cli.Context) error {
|
||||
return fmt.Errorf("no tag version specified, exiting")
|
||||
}
|
||||
|
||||
if strings.Contains(tag, "security") {
|
||||
log.Printf("skipping npm publish because version '%s' has 'security'", tag)
|
||||
return nil
|
||||
}
|
||||
|
||||
prereleaseBucket := strings.TrimSpace(os.Getenv("PRERELEASE_BUCKET"))
|
||||
if prereleaseBucket == "" {
|
||||
return cli.Exit("the environment variable PRERELEASE_BUCKET must be set", 1)
|
||||
@@ -73,6 +84,11 @@ func NpmReleaseAction(c *cli.Context) error {
|
||||
return fmt.Errorf("no tag version specified, exitting")
|
||||
}
|
||||
|
||||
if strings.Contains(tag, "security") {
|
||||
log.Printf("skipping npm publish because version '%s' has 'security'", tag)
|
||||
return nil
|
||||
}
|
||||
|
||||
err := npm.PublishNpmPackages(c.Context, tag)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/gpg"
|
||||
"github.com/grafana/grafana/pkg/build/packaging"
|
||||
"github.com/grafana/grafana/pkg/build/syncutil"
|
||||
)
|
||||
|
||||
func Package(c *cli.Context) error {
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
edition := config.Edition(c.String("edition"))
|
||||
|
||||
releaseMode, err := metadata.GetReleaseMode()
|
||||
if err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
releaseModeConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
|
||||
cfg := config.Config{
|
||||
NumWorkers: c.Int("jobs"),
|
||||
SignPackages: c.Bool("sign"),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
variants := []config.Variant{}
|
||||
variantStrs := strings.Split(c.String("variants"), ",")
|
||||
if c.String("variants") != "" {
|
||||
for _, varStr := range variantStrs {
|
||||
if varStr == "" {
|
||||
continue
|
||||
}
|
||||
variants = append(variants, config.Variant(varStr))
|
||||
}
|
||||
} else {
|
||||
variants = releaseModeConfig.Variants
|
||||
}
|
||||
|
||||
if len(variants) == 0 {
|
||||
variants = config.AllVariants
|
||||
}
|
||||
|
||||
log.Printf("Packaging Grafana version %q, version mode %s, %s edition, variants %s", metadata.GrafanaVersion, releaseMode.Mode,
|
||||
edition, strings.Join(variantStrs, ","))
|
||||
|
||||
if cfg.SignPackages {
|
||||
if err := gpg.LoadGPGKeys(&cfg); err != nil {
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
defer gpg.RemoveGPGFiles(cfg)
|
||||
if err := gpg.Import(cfg); err != nil {
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
}
|
||||
|
||||
p := syncutil.NewWorkerPool(cfg.NumWorkers)
|
||||
defer p.Close()
|
||||
|
||||
if err := packaging.PackageGrafana(ctx, metadata.GrafanaVersion, ".", cfg, edition, variants, releaseModeConfig.PluginSignature.Sign, p); err != nil {
|
||||
return cli.Exit(err, 1)
|
||||
}
|
||||
|
||||
log.Println("Successfully packaged Grafana!")
|
||||
return nil
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/docker"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud"
|
||||
)
|
||||
|
||||
func Enterprise2(c *cli.Context) error {
|
||||
if c.NArg() > 0 {
|
||||
if err := cli.ShowSubcommandHelp(c); err != nil {
|
||||
return cli.Exit(err.Error(), 1)
|
||||
}
|
||||
return cli.Exit("", 1)
|
||||
}
|
||||
|
||||
if err := gcloud.ActivateServiceAccount(); err != nil {
|
||||
return fmt.Errorf("couldn't activate service account, err: %w", err)
|
||||
}
|
||||
|
||||
metadata, err := config.GenerateMetadata(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buildConfig, err := config.GetBuildConfig(metadata.ReleaseMode.Mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg := docker.Config{
|
||||
Archs: buildConfig.Docker.Architectures,
|
||||
Distribution: buildConfig.Docker.Distribution,
|
||||
DockerHubRepo: c.String("dockerhub-repo"),
|
||||
Tag: metadata.GrafanaVersion,
|
||||
}
|
||||
|
||||
err = dockerLoginEnterprise2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var distributionStr []string
|
||||
for _, distribution := range cfg.Distribution {
|
||||
switch distribution {
|
||||
case alpine:
|
||||
distributionStr = append(distributionStr, "")
|
||||
case ubuntu:
|
||||
distributionStr = append(distributionStr, "-ubuntu")
|
||||
default:
|
||||
return fmt.Errorf("unrecognized distribution %q", distribution)
|
||||
}
|
||||
}
|
||||
|
||||
for _, distribution := range distributionStr {
|
||||
var imageFileNames []string
|
||||
for _, arch := range cfg.Archs {
|
||||
imageFilename := fmt.Sprintf("%s:%s%s-%s", cfg.DockerHubRepo, cfg.Tag, distribution, arch)
|
||||
err := docker.PushImage(imageFilename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageFileNames = append(imageFileNames, imageFilename)
|
||||
}
|
||||
manifest := fmt.Sprintf("%s:%s%s", cfg.DockerHubRepo, cfg.Tag, distribution)
|
||||
args := []string{"manifest", "create", manifest}
|
||||
args = append(args, imageFileNames...)
|
||||
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("docker", args...)
|
||||
cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled")
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to create Docker manifest: %w\n%s", err, output)
|
||||
}
|
||||
|
||||
err = docker.PushManifest(manifest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func dockerLoginEnterprise2() error {
|
||||
log.Println("Docker login...")
|
||||
cmd := exec.Command("gcloud", "auth", "configure-docker")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("error logging in to DockerHub: %s %q", out, err)
|
||||
}
|
||||
|
||||
log.Println("Successful login!")
|
||||
return nil
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func Shellcheck(c *cli.Context) error {
|
||||
log.Println("Running shellcheck...")
|
||||
|
||||
fpaths := []string{}
|
||||
if err := filepath.Walk("scripts", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.HasSuffix(path, ".sh") {
|
||||
fpaths = append(fpaths, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return fmt.Errorf("couldn't traverse scripts/: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("Running shellcheck on %s", strings.Join(fpaths, ","))
|
||||
args := append([]string{"-e", "SC1071", "-e", "SC2162"}, fpaths...)
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("shellcheck", args...)
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("shellcheck failed: %s", output)
|
||||
}
|
||||
|
||||
log.Println("Successfully ran shellcheck!")
|
||||
return nil
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
@@ -14,9 +15,28 @@ import (
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
"github.com/grafana/grafana/pkg/build/droneutil"
|
||||
"github.com/grafana/grafana/pkg/build/gcloud"
|
||||
"github.com/grafana/grafana/pkg/build/packaging"
|
||||
)
|
||||
|
||||
// PackageRegexp returns a regexp for matching packages corresponding to a certain Grafana edition.
|
||||
func PackageRegexp(edition config.Edition) *regexp.Regexp {
|
||||
var sfx string
|
||||
switch edition {
|
||||
case config.EditionOSS:
|
||||
case config.EditionEnterprise:
|
||||
sfx = "-enterprise"
|
||||
case config.EditionEnterprise2:
|
||||
sfx = "-enterprise2"
|
||||
default:
|
||||
panic(fmt.Sprintf("unrecognized edition %q", edition))
|
||||
}
|
||||
rePkg, err := regexp.Compile(fmt.Sprintf(`^grafana%s(?:-rpi)?[-_][^-_]+.*$`, sfx))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to compile regexp: %s", err))
|
||||
}
|
||||
|
||||
return rePkg
|
||||
}
|
||||
|
||||
const releaseFolder = "release"
|
||||
const mainFolder = "main"
|
||||
const releaseBranchFolder = "prerelease"
|
||||
@@ -181,7 +201,7 @@ func uploadPackages(cfg uploadConfig) error {
|
||||
return fmt.Errorf("failed to list packages: %w", err)
|
||||
}
|
||||
fpaths := []string{}
|
||||
rePkg := packaging.PackageRegexp(cfg.edition)
|
||||
rePkg := PackageRegexp(cfg.edition)
|
||||
for _, fpath := range matches {
|
||||
fname := filepath.Base(fpath)
|
||||
if strings.Contains(fname, "latest") || !rePkg.MatchString(fname) {
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func mapSlice[I any, O any](a []I, f func(I) O) []O {
|
||||
o := make([]O, len(a))
|
||||
for i, e := range a {
|
||||
o[i] = f(e)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
// VerifyStarlark is the CLI Action for verifying Starlark files in a workspace.
|
||||
// It expects a single context argument which is the path to the workspace.
|
||||
// The actual verification procedure can return multiple errors which are
|
||||
// joined together to be one holistic error for the action.
|
||||
func VerifyStarlark(c *cli.Context) error {
|
||||
if c.NArg() != 1 {
|
||||
var message string
|
||||
if c.NArg() == 0 {
|
||||
message = "ERROR: missing required argument <workspace path>"
|
||||
}
|
||||
if c.NArg() > 1 {
|
||||
message = "ERROR: too many arguments"
|
||||
}
|
||||
|
||||
if err := cli.ShowSubcommandHelp(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cli.Exit(message, 1)
|
||||
}
|
||||
|
||||
workspace := c.Args().Get(0)
|
||||
verificationErrs, executionErr := verifyStarlark(c.Context, workspace, buildifierLintCommand)
|
||||
if executionErr != nil {
|
||||
return executionErr
|
||||
}
|
||||
|
||||
if len(verificationErrs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
noun := "file"
|
||||
if len(verificationErrs) > 1 {
|
||||
noun += "s"
|
||||
}
|
||||
|
||||
return fmt.Errorf("verification failed for %d %s:\n%s",
|
||||
len(verificationErrs),
|
||||
noun,
|
||||
strings.Join(
|
||||
mapSlice(verificationErrs, func(e error) string { return e.Error() }),
|
||||
"\n",
|
||||
))
|
||||
}
|
||||
|
||||
type commandFunc = func(path string) (command string, args []string)
|
||||
|
||||
func buildifierLintCommand(path string) (string, []string) {
|
||||
return "buildifier", []string{"-lint", "warn", "-mode", "check", path}
|
||||
}
|
||||
|
||||
// verifyStarlark walks all directories starting at provided workspace path and
|
||||
// verifies any Starlark files it finds.
|
||||
// Starlark files are assumed to end with the .star extension.
|
||||
// The verification relies on linting frovided by the 'buildifier' binary which
|
||||
// must be in the PATH.
|
||||
// A slice of verification errors are returned, one for each file that failed verification.
|
||||
// If any execution of the `buildifier` command fails, this is returned separately.
|
||||
// commandFn is executed on every Starlark file to determine the command and arguments to be executed.
|
||||
// The caller is trusted and it is the callers responsibility to ensure that the resulting command is safe to execute.
|
||||
func verifyStarlark(ctx context.Context, workspace string, commandFn commandFunc) ([]error, error) {
|
||||
var verificationErrs []error
|
||||
|
||||
// All errors from filepath.WalkDir are filtered by the fs.WalkDirFunc.
|
||||
// Lstat or ReadDir errors are reported as verificationErrors.
|
||||
// If any execution of the `buildifier` command fails or if the context is cancelled,
|
||||
// it is reported as an error and any verification of subsequent files is skipped.
|
||||
err := filepath.WalkDir(workspace, func(path string, d fs.DirEntry, err error) error {
|
||||
// Skip verification of the file or files within the directory if there is an error
|
||||
// returned by Lstat or ReadDir.
|
||||
if err != nil {
|
||||
verificationErrs = append(verificationErrs, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if filepath.Ext(path) == ".star" {
|
||||
command, args := commandFn(path)
|
||||
// The caller is trusted.
|
||||
//nolint:gosec
|
||||
cmd := exec.CommandContext(ctx, command, args...)
|
||||
cmd.Dir = workspace
|
||||
|
||||
_, err = cmd.Output()
|
||||
if err == nil { // No error, early return.
|
||||
return nil
|
||||
}
|
||||
|
||||
// The error returned from cmd.Output() is never wrapped.
|
||||
//nolint:errorlint
|
||||
if err, ok := err.(*exec.ExitError); ok {
|
||||
switch err.ExitCode() {
|
||||
// Case comments are informed by the output of `buildifier --help`
|
||||
case 1: // syntax errors in input
|
||||
verificationErrs = append(verificationErrs, errors.New(string(err.Stderr)))
|
||||
return nil
|
||||
case 2: // usage errors: invoked incorrectly
|
||||
return fmt.Errorf("command %q: %s", cmd, err.Stderr)
|
||||
case 3: // unexpected runtime errors: file I/O problems or internal bugs
|
||||
return fmt.Errorf("command %q: %s", cmd, err.Stderr)
|
||||
case 4: // check mode failed (reformat is needed)
|
||||
verificationErrs = append(verificationErrs, errors.New(string(err.Stderr)))
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("command %q: %s", cmd, err.Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
// Error was not an exit error from the command.
|
||||
return fmt.Errorf("command %q: %v", cmd, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return verificationErrs, err
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
//go:build requires_buildifier
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestVerifyStarlark(t *testing.T) {
|
||||
t.Run("execution errors", func(t *testing.T) {
|
||||
t.Run("invalid usage", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
workspace := t.TempDir()
|
||||
err := os.WriteFile(filepath.Join(workspace, "ignored.star"), []byte{}, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
_, executionErr := verifyStarlark(ctx, workspace, func(string) (string, []string) { return "buildifier", []string{"--invalid"} })
|
||||
if executionErr == nil {
|
||||
t.Fatalf("Expected execution error but got none")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("context cancellation", func(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
workspace := t.TempDir()
|
||||
err := os.WriteFile(filepath.Join(workspace, "ignored.star"), []byte{}, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
err = os.WriteFile(filepath.Join(workspace, "other-ignored.star"), []byte{}, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
cancel()
|
||||
|
||||
_, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand)
|
||||
if executionErr == nil {
|
||||
t.Fatalf("Expected execution error but got none")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("verification errors", func(t *testing.T) {
|
||||
t.Run("a single file with lint", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
workspace := t.TempDir()
|
||||
|
||||
invalidContent := []byte(`load("scripts/drone/other.star", "function")
|
||||
|
||||
function()`)
|
||||
err := os.WriteFile(filepath.Join(workspace, "has-lint.star"), invalidContent, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
verificationErrs, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand)
|
||||
if executionErr != nil {
|
||||
t.Fatalf("Unexpected execution error: %v", executionErr)
|
||||
}
|
||||
if len(verificationErrs) == 0 {
|
||||
t.Fatalf(`"has-lint.star" requires linting but the verifyStarlark function provided no linting error`)
|
||||
}
|
||||
if len(verificationErrs) > 1 {
|
||||
t.Fatalf(`verifyStarlark returned multiple errors for the "has-lint.star" file but only one was expected: %v`, verificationErrs)
|
||||
}
|
||||
if !strings.Contains(verificationErrs[0].Error(), "has-lint.star:1: module-docstring: The file has no module docstring.") {
|
||||
t.Fatalf(`"has-lint.star" is missing a module docstring but the verifyStarlark function linting error did not mention this, instead we got: %v`, verificationErrs[0])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no files with lint", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
workspace := t.TempDir()
|
||||
|
||||
content := []byte(`"""
|
||||
This module does nothing.
|
||||
"""
|
||||
|
||||
load("scripts/drone/other.star", "function")
|
||||
|
||||
function()
|
||||
`)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(workspace, "no-lint.star"), content, os.ModePerm))
|
||||
|
||||
verificationErrs, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand)
|
||||
if executionErr != nil {
|
||||
t.Fatalf("Unexpected execution error: %v", executionErr)
|
||||
}
|
||||
if len(verificationErrs) != 0 {
|
||||
t.Log(`"no-lint.star" has no lint but the verifyStarlark function provided at least one error`)
|
||||
for _, err := range verificationErrs {
|
||||
t.Log(err)
|
||||
}
|
||||
t.FailNow()
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("multiple files with lint", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
workspace := t.TempDir()
|
||||
|
||||
invalidContent := []byte(`load("scripts/drone/other.star", "function")
|
||||
|
||||
function()`)
|
||||
require.NoError(t, os.WriteFile(filepath.Join(workspace, "has-lint.star"), invalidContent, os.ModePerm))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(workspace, "has-lint2.star"), invalidContent, os.ModePerm))
|
||||
|
||||
verificationErrs, executionErr := verifyStarlark(ctx, workspace, buildifierLintCommand)
|
||||
if executionErr != nil {
|
||||
t.Fatalf("Unexpected execution error: %v", executionErr)
|
||||
}
|
||||
if len(verificationErrs) == 0 {
|
||||
t.Fatalf(`Two files require linting but the verifyStarlark function provided no linting error`)
|
||||
}
|
||||
if len(verificationErrs) == 1 {
|
||||
t.Fatalf(`Two files require linting but the verifyStarlark function provided only one linting error: %v`, verificationErrs[0])
|
||||
}
|
||||
if len(verificationErrs) > 2 {
|
||||
t.Fatalf(`verifyStarlark returned more errors than expected: %v`, verificationErrs)
|
||||
}
|
||||
if !strings.Contains(verificationErrs[0].Error(), "has-lint.star:1: module-docstring: The file has no module docstring.") {
|
||||
t.Errorf(`"has-lint.star" is missing a module docstring but the verifyStarlark function linting error did not mention this, instead we got: %v`, verificationErrs[0])
|
||||
}
|
||||
if !strings.Contains(verificationErrs[1].Error(), "has-lint2.star:1: module-docstring: The file has no module docstring.") {
|
||||
t.Fatalf(`"has-lint2.star" is missing a module docstring but the verifyStarlark function linting error did not mention this, instead we got: %v`, verificationErrs[0])
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package compilers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
ArmV6 = "/opt/rpi-tools/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
|
||||
Armv7 = "arm-linux-gnueabihf-gcc"
|
||||
Armv7Musl = "/tmp/arm-linux-musleabihf-cross/bin/arm-linux-musleabihf-gcc"
|
||||
Arm64 = "aarch64-linux-gnu-gcc"
|
||||
Arm64Musl = "/tmp/aarch64-linux-musl-cross/bin/aarch64-linux-musl-gcc"
|
||||
Osx64 = "/tmp/osxcross/target/bin/o64-clang"
|
||||
Win64 = "x86_64-w64-mingw32-gcc"
|
||||
LinuxX64 = "/tmp/x86_64-centos6-linux-gnu/bin/x86_64-centos6-linux-gnu-gcc"
|
||||
LinuxX64Musl = "/tmp/x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc"
|
||||
)
|
||||
|
||||
func Install() error {
|
||||
// From the os.TempDir documentation:
|
||||
// On Unix systems, it returns $TMPDIR if non-empty,
|
||||
// else /tmp. On Windows, it uses GetTempPath,
|
||||
// returning the first non-empty value from %TMP%, %TEMP%, %USERPROFILE%,
|
||||
// or the Windows directory. On Plan 9, it returns /tmp.
|
||||
tmp := os.TempDir()
|
||||
|
||||
var (
|
||||
centosArchive = "x86_64-centos6-linux-gnu.tar.xz"
|
||||
osxArchive = "osxcross.tar.xz"
|
||||
)
|
||||
|
||||
for _, fname := range []string{centosArchive, osxArchive} {
|
||||
path := filepath.Join(tmp, fname)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return fmt.Errorf("stat error: %w", err)
|
||||
}
|
||||
// Ignore gosec G204 as this function is only used in the build process.
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("tar", "xfJ", fname)
|
||||
cmd.Dir = tmp
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to unpack %q: %q, %w", fname, output, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/executil"
|
||||
)
|
||||
|
||||
type Revision struct {
|
||||
Timestamp int64
|
||||
SHA256 string
|
||||
EnterpriseCommit string
|
||||
Branch string
|
||||
}
|
||||
|
||||
func GrafanaTimestamp(ctx context.Context, dir string) (int64, error) {
|
||||
out, err := executil.OutputAt(ctx, dir, "git", "show", "-s", "--format=%ct")
|
||||
if err != nil {
|
||||
return time.Now().Unix(), nil
|
||||
}
|
||||
|
||||
stamp, err := strconv.ParseInt(out, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse output from git show: %q", out)
|
||||
}
|
||||
|
||||
return stamp, nil
|
||||
}
|
||||
|
||||
// GrafanaRevision uses git commands to get information about the checked out Grafana code located at 'grafanaDir'.
|
||||
// This could maybe be a more generic "Describe" function in the "git" package.
|
||||
func GrafanaRevision(ctx context.Context, grafanaDir string) (Revision, error) {
|
||||
stamp, err := GrafanaTimestamp(ctx, grafanaDir)
|
||||
if err != nil {
|
||||
return Revision{}, err
|
||||
}
|
||||
|
||||
sha, err := executil.OutputAt(ctx, grafanaDir, "git", "rev-parse", "--short", "HEAD")
|
||||
if err != nil {
|
||||
return Revision{}, err
|
||||
}
|
||||
|
||||
enterpriseCommit, err := executil.OutputAt(ctx, grafanaDir, "git", "-C", "../grafana-enterprise", "rev-parse", "--short", "HEAD")
|
||||
if err != nil {
|
||||
enterpriseCommit, err = executil.OutputAt(ctx, grafanaDir, "git", "-C", "..", "rev-parse", "--short", "HEAD")
|
||||
if err != nil {
|
||||
enterpriseCommit, err = executil.OutputAt(ctx, grafanaDir, "git", "-C", "/tmp/grafana-enterprise", "rev-parse", "--short", "HEAD")
|
||||
if err != nil {
|
||||
log.Println("Could not get enterprise commit. Error:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
branch, err := executil.OutputAt(ctx, grafanaDir, "git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
if err != nil {
|
||||
return Revision{}, err
|
||||
}
|
||||
|
||||
return Revision{
|
||||
SHA256: sha,
|
||||
EnterpriseCommit: enterpriseCommit,
|
||||
Branch: branch,
|
||||
Timestamp: stamp,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package cryptoutil
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func MD5File(fpath string) error {
|
||||
// Ignore gosec G304 as this function is only used in the build process.
|
||||
//nolint:gosec
|
||||
fd, err := os.Open(fpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := fd.Close(); err != nil {
|
||||
log.Printf("error closing file at '%s': %s", fpath, err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
h := md5.New() // nolint:gosec
|
||||
if _, err = io.Copy(h, fd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint:gosec
|
||||
if err := os.WriteFile(fpath+".md5", []byte(fmt.Sprintf("%x\n", h.Sum(nil))), 0664); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/config"
|
||||
)
|
||||
|
||||
// verifyArchive verifies the integrity of an archive file.
|
||||
func verifyArchive(archive string) error {
|
||||
log.Printf("Verifying checksum of %q", archive)
|
||||
|
||||
//nolint:gosec
|
||||
shaB, err := os.ReadFile(archive + ".sha256")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exp := strings.TrimSpace(string(shaB))
|
||||
|
||||
//nolint:gosec
|
||||
f, err := os.Open(archive)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
log.Println("error closing file:", err)
|
||||
}
|
||||
}()
|
||||
|
||||
h := sha256.New()
|
||||
_, err = io.Copy(h, f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
chksum := hex.EncodeToString(h.Sum(nil))
|
||||
if chksum != exp {
|
||||
return fmt.Errorf("archive checksum is different than expected: %q", archive)
|
||||
}
|
||||
|
||||
log.Printf("Archive %q has expected checksum: %s", archive, exp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuildImage builds a Docker image.
|
||||
// The image tag is returned.
|
||||
func BuildImage(version string, arch config.Architecture, grafanaDir string, useUbuntu, shouldSave bool, edition config.Edition, mode config.VersionMode) ([]string, error) {
|
||||
var baseArch string
|
||||
|
||||
switch arch {
|
||||
case "amd64":
|
||||
case "armv7":
|
||||
baseArch = "arm32v7/"
|
||||
case "arm64":
|
||||
baseArch = "arm64v8/"
|
||||
default:
|
||||
return []string{}, fmt.Errorf("unrecognized architecture %q", arch)
|
||||
}
|
||||
|
||||
libc := "-musl"
|
||||
baseImage := fmt.Sprintf("%salpine:3.18.5", baseArch)
|
||||
tagSuffix := ""
|
||||
if useUbuntu {
|
||||
libc = ""
|
||||
baseImage = fmt.Sprintf("%subuntu:22.04", baseArch)
|
||||
tagSuffix = "-ubuntu"
|
||||
}
|
||||
|
||||
var editionStr string
|
||||
var dockerRepo string
|
||||
var additionalDockerRepo string
|
||||
var tags []string
|
||||
var imageFileBase string
|
||||
var dockerEnterprise2Repo string
|
||||
if repo, ok := os.LookupEnv("DOCKER_ENTERPRISE2_REPO"); ok {
|
||||
dockerEnterprise2Repo = repo
|
||||
}
|
||||
|
||||
switch edition {
|
||||
case config.EditionOSS:
|
||||
dockerRepo = "grafana/grafana-image-tags"
|
||||
additionalDockerRepo = "grafana/grafana-oss-image-tags"
|
||||
imageFileBase = "grafana-oss"
|
||||
case config.EditionEnterprise:
|
||||
dockerRepo = "grafana/grafana-enterprise-image-tags"
|
||||
imageFileBase = "grafana-enterprise"
|
||||
editionStr = "-enterprise"
|
||||
case config.EditionEnterprise2:
|
||||
dockerRepo = dockerEnterprise2Repo
|
||||
imageFileBase = "grafana-enterprise2"
|
||||
editionStr = "-enterprise2"
|
||||
default:
|
||||
return []string{}, fmt.Errorf("unrecognized edition %s", edition)
|
||||
}
|
||||
|
||||
buildDir := filepath.Join(grafanaDir, "packaging/docker")
|
||||
// For example: grafana-8.5.0-52819pre.linux-amd64-musl.tar.gz
|
||||
archive := fmt.Sprintf("grafana%s-%s.linux-%s%s.tar.gz", editionStr, version, arch, libc)
|
||||
if err := verifyArchive(filepath.Join(buildDir, archive)); err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
|
||||
tag := fmt.Sprintf("%s:%s%s-%s", dockerRepo, version, tagSuffix, arch)
|
||||
tags = append(tags, tag)
|
||||
|
||||
args := []string{
|
||||
"build",
|
||||
"-q",
|
||||
"--build-arg", fmt.Sprintf("BASE_IMAGE=%s", baseImage),
|
||||
"--build-arg", fmt.Sprintf("GRAFANA_TGZ=%s", archive),
|
||||
"--build-arg", "GO_SRC=tgz-builder",
|
||||
"--build-arg", "JS_SRC=tgz-builder",
|
||||
"--build-arg", "RUN_SH=./run.sh",
|
||||
"--tag", tag,
|
||||
"--no-cache",
|
||||
"--file", "../../Dockerfile",
|
||||
".",
|
||||
"--label", fmt.Sprintf("mode=%s", string(mode)),
|
||||
}
|
||||
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("docker", args...)
|
||||
cmd.Dir = buildDir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled", "DOCKER_BUILDKIT=1")
|
||||
log.Printf("Running Docker: DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_BUILDKIT=1 %s", cmd)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return []string{}, fmt.Errorf("building Docker image failed: %w", err)
|
||||
}
|
||||
if shouldSave {
|
||||
imageFile := fmt.Sprintf("%s-%s%s-%s.img", imageFileBase, version, tagSuffix, arch)
|
||||
//nolint:gosec
|
||||
cmd = exec.Command("docker", "save", tag, "-o", imageFile)
|
||||
cmd.Dir = buildDir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
log.Printf("Running Docker: %s", cmd)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return []string{}, fmt.Errorf("saving Docker image failed: %w", err)
|
||||
}
|
||||
gcsURL := fmt.Sprintf("gs://grafana-prerelease/artifacts/docker/%s/%s", version, imageFile)
|
||||
//nolint:gosec
|
||||
cmd = exec.Command("gsutil", "-q", "cp", imageFile, gcsURL)
|
||||
cmd.Dir = buildDir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
log.Printf("Running gsutil: %s", cmd)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return []string{}, fmt.Errorf("storing Docker image failed: %w", err)
|
||||
}
|
||||
log.Printf("Docker image %s stored to grafana-prerelease GCS bucket", imageFile)
|
||||
}
|
||||
if additionalDockerRepo != "" {
|
||||
additionalTag := fmt.Sprintf("%s:%s%s-%s", additionalDockerRepo, version, tagSuffix, arch)
|
||||
|
||||
//nolint:gosec
|
||||
cmd = exec.Command("docker", "tag", tag, additionalTag)
|
||||
cmd.Dir = buildDir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
log.Printf("Running Docker: %s", cmd)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return []string{}, fmt.Errorf("tagging Docker image failed: %w", err)
|
||||
}
|
||||
tags = append(tags, additionalTag)
|
||||
}
|
||||
|
||||
return tags, nil
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// AllArchs is a list of all supported Docker image architectures.
|
||||
var AllArchs = []string{"amd64", "arm64"}
|
||||
|
||||
// emulatorImage is the docker image used as the cross-platform emulator
|
||||
var emulatorImage = "tonistiigi/binfmt:qemu-v7.0.0"
|
||||
|
||||
// Init initializes the OS for Docker image building.
|
||||
func Init() error {
|
||||
// Necessary for cross-platform builds
|
||||
if err := os.Setenv("DOCKER_BUILDKIT", "1"); err != nil {
|
||||
log.Println("error setting DOCKER_BUILDKIT environment variable:", err)
|
||||
}
|
||||
|
||||
// Enable execution of Docker images for other architectures
|
||||
//nolint:gosec
|
||||
cmd := exec.Command("docker", "run", "--privileged", "--rm",
|
||||
emulatorImage, "--install", "all")
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to enable execution of cross-platform Docker images: %w\n%s", err, output)
|
||||
}
|
||||
log.Println("emulators have been installed successfully!")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
tries = 3
|
||||
sleepTime = 30
|
||||
)
|
||||
|
||||
func PushImage(newImage string) error {
|
||||
var err error
|
||||
for i := 0; i < tries; i++ {
|
||||
log.Printf("push attempt #%d...", i+1)
|
||||
var out []byte
|
||||
cmd := exec.Command("docker", "push", newImage)
|
||||
cmd.Dir = "."
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf("output: %s", out)
|
||||
log.Printf("sleep for %d, before retrying...", sleepTime)
|
||||
time.Sleep(sleepTime * time.Second)
|
||||
} else {
|
||||
log.Printf("Successfully pushed %s!", newImage)
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("error pushing images to DockerHub: %q", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func PushManifest(manifest string) error {
|
||||
log.Printf("Pushing Docker manifest %s...", manifest)
|
||||
|
||||
var err error
|
||||
for i := 0; i < tries; i++ {
|
||||
log.Printf("push attempt #%d...", i+1)
|
||||
var out []byte
|
||||
cmd := exec.Command("docker", "manifest", "push", manifest)
|
||||
cmd.Env = append(os.Environ(), "DOCKER_CLI_EXPERIMENTAL=enabled")
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Printf("output: %s", out)
|
||||
log.Printf("sleep for %d, before retrying...", sleepTime)
|
||||
time.Sleep(sleepTime * time.Second)
|
||||
} else {
|
||||
log.Printf("Successful manifest push! %s", string(out))
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to push manifest, err: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
18
pkg/build/env/lookup.go
vendored
18
pkg/build/env/lookup.go
vendored
@@ -1,18 +0,0 @@
|
||||
package env
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Lookup is the equivalent of os.LookupEnv, only you are able to provide the list of environment variables.
|
||||
// To use this as os.LookupEnv would be used, simply call
|
||||
// `env.Lookup("ENVIRONMENT_VARIABLE", os.Environ())`
|
||||
func Lookup(name string, vars []string) (string, bool) {
|
||||
for _, v := range vars {
|
||||
if strings.HasPrefix(v, name) {
|
||||
return strings.TrimPrefix(v, name+"="), true
|
||||
}
|
||||
}
|
||||
|
||||
return "", false
|
||||
}
|
||||
43
pkg/build/env/lookup_test.go
vendored
43
pkg/build/env/lookup_test.go
vendored
@@ -1,43 +0,0 @@
|
||||
package env_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/env"
|
||||
)
|
||||
|
||||
func TestLookup(t *testing.T) {
|
||||
values := []string{"ENV_1=a", "ENV_2=b", "ENV_3=c", "ENV_4_TEST="}
|
||||
|
||||
{
|
||||
v, ok := env.Lookup("ENV_1", values)
|
||||
require.Equal(t, v, "a")
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
{
|
||||
v, ok := env.Lookup("ENV_2", values)
|
||||
require.Equal(t, v, "b")
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
{
|
||||
v, ok := env.Lookup("ENV_3", values)
|
||||
require.Equal(t, v, "c")
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
{
|
||||
v, ok := env.Lookup("ENV_4_TEST", values)
|
||||
require.Equal(t, v, "")
|
||||
require.True(t, ok)
|
||||
}
|
||||
|
||||
{
|
||||
v, ok := env.Lookup("NOT_THERE", values)
|
||||
require.Equal(t, v, "")
|
||||
require.False(t, ok)
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package errutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Group struct {
|
||||
cancel func()
|
||||
wg sync.WaitGroup
|
||||
errOnce sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
func GroupWithContext(ctx context.Context) (*Group, context.Context) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Group{cancel: cancel}, ctx
|
||||
}
|
||||
|
||||
// Wait waits for any wrapped goroutines to finish and returns any error having occurred in one of them.
|
||||
func (g *Group) Wait() error {
|
||||
log.Println("Waiting on Group")
|
||||
g.wg.Wait()
|
||||
if g.cancel != nil {
|
||||
log.Println("Group canceling its context after waiting")
|
||||
g.cancel()
|
||||
}
|
||||
return g.err
|
||||
}
|
||||
|
||||
// Cancel cancels the associated context.
|
||||
func (g *Group) Cancel() {
|
||||
log.Println("Group's Cancel method being called")
|
||||
g.cancel()
|
||||
}
|
||||
|
||||
// Wrap wraps a function to be executed in a goroutine.
|
||||
func (g *Group) Wrap(f func() error) func() {
|
||||
g.wg.Add(1)
|
||||
return func() {
|
||||
defer g.wg.Done()
|
||||
|
||||
if err := f(); err != nil {
|
||||
g.errOnce.Do(func() {
|
||||
log.Printf("An error occurred in Group: %s", err)
|
||||
g.err = err
|
||||
if g.cancel != nil {
|
||||
log.Println("Group canceling its context due to error")
|
||||
g.cancel()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go wraps the provided function and executes it in a goroutine.
|
||||
func (g *Group) Go(f func() error) {
|
||||
wrapped := g.Wrap(f)
|
||||
go wrapped()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user