From ed96e88c75f235c877186e6ac7d0ff6b6c57a1c6 Mon Sep 17 00:00:00 2001 From: Erik Baranowski <39704712+erikbaranowski@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:02:56 -0500 Subject: [PATCH 01/11] Set permissions on the Grafana Agent [Flow] folder... (#6540) * Set permissions on the folder when installing via the windows installer rather than relying on the parent folder permissions. Signed-off-by: erikbaranowski <39704712+erikbaranowski@users.noreply.github.com> --------- Signed-off-by: erikbaranowski <39704712+erikbaranowski@users.noreply.github.com> (cherry picked from commit 9e4d3b500932fd0992252f1a9ad52b53715ab56e) --- .drone/drone.yml | 116 +++++++++--------- CHANGELOG.md | 3 + cmd/grafana-agent-operator/Dockerfile | 2 +- cmd/grafana-agent/Dockerfile | 2 +- cmd/grafana-agent/Dockerfile.windows | 2 +- cmd/grafana-agentctl/Dockerfile | 2 +- cmd/grafana-agentctl/Dockerfile.windows | 2 +- .../windows/install_script.nsis | 15 +++ .../grafana-agent/windows/install_script.nsis | 15 +++ tools/make/build-container.mk | 2 +- tools/make/packaging.mk | 4 +- 11 files changed, 99 insertions(+), 66 deletions(-) diff --git a/.drone/drone.yml b/.drone/drone.yml index f521c097fe5f..204767a96375 100644 --- a/.drone/drone.yml +++ b/.drone/drone.yml @@ -110,7 +110,7 @@ steps: - commands: - apt-get update -y && apt-get install -y libsystemd-dev - make lint - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Lint trigger: event: @@ -128,7 +128,7 @@ steps: - ERR_MSG="Dashboard definitions are out of date. Please run 'make generate-dashboards' and commit changes!" - if [ ! -z "$(git status --porcelain)" ]; then echo $ERR_MSG >&2; exit 1; fi - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Regenerate dashboards trigger: event: @@ -146,7 +146,7 @@ steps: - ERR_MSG="Custom Resource Definitions are out of date. Please run 'make generate-crds' and commit changes!" - if [ ! -z "$(git status --porcelain)" ]; then echo $ERR_MSG >&2; exit 1; fi - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Regenerate crds trigger: event: @@ -161,7 +161,7 @@ platform: steps: - commands: - make GO_TAGS="nodocker" test - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Run Go tests trigger: event: @@ -176,7 +176,7 @@ platform: steps: - commands: - K8S_USE_DOCKER_NETWORK=1 make test - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Run Go tests volumes: - name: docker @@ -199,7 +199,7 @@ platform: steps: - commands: - go test -tags="nodocker,nonetwork" ./... - image: grafana/agent-build-image:0.31.0-windows + image: grafana/agent-build-image:0.33.0-windows name: Run Go tests trigger: ref: @@ -214,7 +214,7 @@ platform: steps: - commands: - make agent-image - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build container volumes: - name: docker @@ -239,7 +239,7 @@ platform: steps: - commands: - make agentctl-image - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build container volumes: - name: docker @@ -264,7 +264,7 @@ platform: steps: - commands: - make operator-image - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build container volumes: - name: docker @@ -290,7 +290,7 @@ platform: steps: - commands: - '& "C:/Program Files/git/bin/bash.exe" ./tools/ci/docker-containers-windows agent' - image: grafana/agent-build-image:0.31.0-windows + image: grafana/agent-build-image:0.33.0-windows name: Build container volumes: - name: docker @@ -316,7 +316,7 @@ platform: steps: - commands: - '& "C:/Program Files/git/bin/bash.exe" ./tools/ci/docker-containers-windows agentctl' - image: grafana/agent-build-image:0.31.0-windows + image: grafana/agent-build-image:0.33.0-windows name: Build container volumes: - name: docker @@ -343,7 +343,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=amd64 GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -360,7 +360,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=arm64 GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -377,7 +377,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=ppc64le GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -394,7 +394,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=s390x GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -410,7 +410,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=amd64 GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -426,7 +426,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=arm64 GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -442,7 +442,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=windows GOARCH=amd64 GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -458,7 +458,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=freebsd GOARCH=amd64 GOARM= make agent - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -475,7 +475,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=amd64 GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -492,7 +492,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=arm64 GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -509,7 +509,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=ppc64le GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -526,7 +526,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=s390x GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -542,7 +542,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=amd64 GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -558,7 +558,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=arm64 GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -574,7 +574,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=windows GOARCH=amd64 GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -590,7 +590,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=freebsd GOARCH=amd64 GOARM= make agent-flow - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -607,7 +607,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=amd64 GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -624,7 +624,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=arm64 GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -641,7 +641,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=ppc64le GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -658,7 +658,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=s390x GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -674,7 +674,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=amd64 GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -690,7 +690,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=arm64 GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -706,7 +706,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=windows GOARCH=amd64 GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -722,7 +722,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=freebsd GOARCH=amd64 GOARM= make agentctl - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -739,7 +739,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=amd64 GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -756,7 +756,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=arm64 GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -773,7 +773,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=ppc64le GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -790,7 +790,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=s390x GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -806,7 +806,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=amd64 GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -822,7 +822,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=darwin GOARCH=arm64 GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -838,7 +838,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=windows GOARCH=amd64 GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -854,7 +854,7 @@ steps: - commands: - make generate-ui - GO_TAGS="builtinassets" GOOS=freebsd GOARCH=amd64 GOARM= make operator - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -871,7 +871,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=amd64 GOARM= GOEXPERIMENT=boringcrypto make agent-boringcrypto - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -888,7 +888,7 @@ steps: - make generate-ui - GO_TAGS="builtinassets promtail_journal_enabled" GOOS=linux GOARCH=arm64 GOARM= GOEXPERIMENT=boringcrypto make agent-boringcrypto - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Build trigger: event: @@ -904,7 +904,7 @@ steps: - commands: - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes failure: ignore - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Configure QEMU volumes: - name: docker @@ -924,7 +924,7 @@ steps: from_secret: docker_password GCR_CREDS: from_secret: gcr_admin - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Publish container volumes: - name: docker @@ -948,7 +948,7 @@ steps: - commands: - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes failure: ignore - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Configure QEMU volumes: - name: docker @@ -968,7 +968,7 @@ steps: from_secret: docker_password GCR_CREDS: from_secret: gcr_admin - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Publish container volumes: - name: docker @@ -992,7 +992,7 @@ steps: - commands: - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes failure: ignore - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Configure QEMU volumes: - name: docker @@ -1012,7 +1012,7 @@ steps: from_secret: docker_password GCR_CREDS: from_secret: gcr_admin - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Publish container volumes: - name: docker @@ -1036,7 +1036,7 @@ steps: - commands: - docker run --rm --privileged multiarch/qemu-user-static --reset -p yes failure: ignore - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Configure QEMU volumes: - name: docker @@ -1056,7 +1056,7 @@ steps: from_secret: docker_password GCR_CREDS: from_secret: gcr_admin - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Publish container volumes: - name: docker @@ -1085,7 +1085,7 @@ steps: from_secret: docker_login DOCKER_PASSWORD: from_secret: docker_password - image: grafana/agent-build-image:0.31.0-windows + image: grafana/agent-build-image:0.33.0-windows name: Build containers volumes: - name: docker @@ -1114,7 +1114,7 @@ steps: from_secret: docker_login DOCKER_PASSWORD: from_secret: docker_password - image: grafana/agent-build-image:0.31.0-windows + image: grafana/agent-build-image:0.33.0-windows name: Build containers volumes: - name: docker @@ -1231,7 +1231,7 @@ steps: from_secret: gpg_private_key GPG_PUBLIC_KEY: from_secret: gpg_public_key - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Publish release volumes: - name: docker @@ -1256,7 +1256,7 @@ steps: - DOCKER_OPTS="" make dist/grafana-agentctl-linux-amd64 - DOCKER_OPTS="" make dist.temp/grafana-agent-flow-linux-amd64 - DOCKER_OPTS="" make test-packages - image: grafana/agent-build-image:0.31.0 + image: grafana/agent-build-image:0.33.0 name: Test Linux system packages volumes: - name: docker @@ -1352,6 +1352,6 @@ kind: secret name: updater_private_key --- kind: signature -hmac: 2e439110a89f33a78d745a71635d47f9b1a99de6028bb84c258a0be9c09840f2 +hmac: 251627e59296f743a58112edccf6a03ba1e226a57d59720e3894d2ff9c7e520d ... diff --git a/CHANGELOG.md b/CHANGELOG.md index 48f592c8165a..4740c32e13e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ v0.40.1 (2024-02-27) ### Bugfixes +- Set permissions on the `Grafana Agent [Flow]` folder when installing via the + windows installer rather than relying on the parent folder permissions. (@erikbaranowski) + - Fix an issues where the logging config block would trigger an error when trying to send logs to components that were not running. (@wildum) - Fix an issue where a custom component might be wired to a local declare instead of an import declare when they have the same label. (@wildum) diff --git a/cmd/grafana-agent-operator/Dockerfile b/cmd/grafana-agent-operator/Dockerfile index a86af13209bb..6090efd5681f 100644 --- a/cmd/grafana-agent-operator/Dockerfile +++ b/cmd/grafana-agent-operator/Dockerfile @@ -4,7 +4,7 @@ # default when running `docker buildx build` or when DOCKER_BUILDKIT=1 is set # in environment variables. -FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.30.4 as build +FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.33.0 as build ARG BUILDPLATFORM ARG TARGETPLATFORM ARG TARGETOS diff --git a/cmd/grafana-agent/Dockerfile b/cmd/grafana-agent/Dockerfile index f151d43fd080..f602125dfb04 100644 --- a/cmd/grafana-agent/Dockerfile +++ b/cmd/grafana-agent/Dockerfile @@ -4,7 +4,7 @@ # default when running `docker buildx build` or when DOCKER_BUILDKIT=1 is set # in environment variables. -FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.30.4 as build +FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.33.0 as build ARG BUILDPLATFORM ARG TARGETPLATFORM ARG TARGETOS diff --git a/cmd/grafana-agent/Dockerfile.windows b/cmd/grafana-agent/Dockerfile.windows index 454c93450eea..6f99a6138fdb 100644 --- a/cmd/grafana-agent/Dockerfile.windows +++ b/cmd/grafana-agent/Dockerfile.windows @@ -1,4 +1,4 @@ -FROM grafana/agent-build-image:0.30.4-windows as builder +FROM grafana/agent-build-image:0.33.0-windows as builder ARG VERSION ARG RELEASE_BUILD=1 diff --git a/cmd/grafana-agentctl/Dockerfile b/cmd/grafana-agentctl/Dockerfile index d04f1816ef99..6f601fb7eed2 100644 --- a/cmd/grafana-agentctl/Dockerfile +++ b/cmd/grafana-agentctl/Dockerfile @@ -4,7 +4,7 @@ # default when running `docker buildx build` or when DOCKER_BUILDKIT=1 is set # in environment variables. -FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.30.4 as build +FROM --platform=$BUILDPLATFORM grafana/agent-build-image:0.33.0 as build ARG BUILDPLATFORM ARG TARGETPLATFORM ARG TARGETOS diff --git a/cmd/grafana-agentctl/Dockerfile.windows b/cmd/grafana-agentctl/Dockerfile.windows index 80d32f866736..8cf3c34a0ace 100644 --- a/cmd/grafana-agentctl/Dockerfile.windows +++ b/cmd/grafana-agentctl/Dockerfile.windows @@ -1,4 +1,4 @@ -FROM grafana/agent-build-image:0.30.4-windows as builder +FROM grafana/agent-build-image:0.33.0-windows as builder ARG VERSION ARG RELEASE_BUILD=1 diff --git a/packaging/grafana-agent-flow/windows/install_script.nsis b/packaging/grafana-agent-flow/windows/install_script.nsis index 469a2cbd97b0..b987e876d417 100644 --- a/packaging/grafana-agent-flow/windows/install_script.nsis +++ b/packaging/grafana-agent-flow/windows/install_script.nsis @@ -101,6 +101,8 @@ Section "install" # Auto-restart agent on failure. Reset failure counter after 60 seconds without failure nsExec::ExecToLog `sc failure "Grafana Agent Flow" reset= 60 actions= restart/5000 reboot= "Grafana Agent Flow has failed. Restarting in 5 seconds"` Pop $0 + + Call SetFolderPermissions SectionEnd Function CreateConfig @@ -164,6 +166,19 @@ Function InitializeRegistry Return FunctionEnd +Function SetFolderPermissions + # Set permissions on the install directory + SetOutPath $INSTDIR + AccessControl::DisableFileInheritance $INSTDIR + AccessControl::SetFileOwner $INSTDIR "Administrators" + AccessControl::ClearOnFile $INSTDIR "Administrators" "FullAccess" + AccessControl::SetOnFile $INSTDIR "SYSTEM" "FullAccess" + AccessControl::GrantOnFile $INSTDIR "Everyone" "ListDirectory" + AccessControl::GrantOnFile $INSTDIR "Everyone" "GenericExecute" + AccessControl::GrantOnFile $INSTDIR "Everyone" "GenericRead" + AccessControl::GrantOnFile $INSTDIR "Everyone" "ReadAttributes" +FunctionEnd + # Automatically called when uninstalling. Function un.onInit SetShellVarContext all diff --git a/packaging/grafana-agent/windows/install_script.nsis b/packaging/grafana-agent/windows/install_script.nsis index b08a8216c691..24c771745faa 100644 --- a/packaging/grafana-agent/windows/install_script.nsis +++ b/packaging/grafana-agent/windows/install_script.nsis @@ -155,6 +155,8 @@ Function Install # Auto-restart agent on failure. Reset failure counter after 60 seconds without failure nsExec::ExecToLog `sc failure "Grafana Agent" reset= 60 actions= restart/5000 reboot= "Grafana Agent has failed. Restarting in 5 seconds"` Pop $0 + + Call SetFolderPermissions FunctionEnd Function WriteConfig @@ -189,6 +191,19 @@ Function WriteConfig Return FunctionEnd +Function SetFolderPermissions + # Set permissions on the install directory + SetOutPath $INSTDIR + AccessControl::DisableFileInheritance $INSTDIR + AccessControl::SetFileOwner $INSTDIR "Administrators" + AccessControl::ClearOnFile $INSTDIR "Administrators" "FullAccess" + AccessControl::SetOnFile $INSTDIR "SYSTEM" "FullAccess" + AccessControl::GrantOnFile $INSTDIR "Everyone" "ListDirectory" + AccessControl::GrantOnFile $INSTDIR "Everyone" "GenericExecute" + AccessControl::GrantOnFile $INSTDIR "Everyone" "GenericRead" + AccessControl::GrantOnFile $INSTDIR "Everyone" "ReadAttributes" +FunctionEnd + # Uninstaller Function un.onInit SetShellVarContext all diff --git a/tools/make/build-container.mk b/tools/make/build-container.mk index be1d4be9ca49..409d284e1f10 100644 --- a/tools/make/build-container.mk +++ b/tools/make/build-container.mk @@ -34,7 +34,7 @@ # variable names should be passed through to the container. USE_CONTAINER ?= 0 -BUILD_IMAGE_VERSION ?= 0.31.0 +BUILD_IMAGE_VERSION ?= 0.33.0 BUILD_IMAGE ?= grafana/agent-build-image:$(BUILD_IMAGE_VERSION) DOCKER_OPTS ?= -it diff --git a/tools/make/packaging.mk b/tools/make/packaging.mk index c9421433e6ae..d150926e48e4 100644 --- a/tools/make/packaging.mk +++ b/tools/make/packaging.mk @@ -388,7 +388,7 @@ ifeq ($(USE_CONTAINER),1) else cp ./dist/grafana-agent-windows-amd64.exe ./packaging/grafana-agent/windows cp LICENSE ./packaging/grafana-agent/windows - # quotes around mkdir are manadory. ref: https://github.com/grafana/agent/pull/5664#discussion_r1378796371 + # quotes around mkdir are mandatory. ref: https://github.com/grafana/agent/pull/5664#discussion_r1378796371 "mkdir" -p dist makensis -V4 -DVERSION=$(VERSION) -DOUT="../../../dist/grafana-agent-installer.exe" ./packaging/grafana-agent/windows/install_script.nsis endif @@ -398,7 +398,7 @@ dist-agent-flow-installer: dist.temp/grafana-agent-flow-windows-amd64.exe dist.t ifeq ($(USE_CONTAINER),1) $(RERUN_IN_CONTAINER) else - # quotes around mkdir are manadory. ref: https://github.com/grafana/agent/pull/5664#discussion_r1378796371 + # quotes around mkdir are mandatory. ref: https://github.com/grafana/agent/pull/5664#discussion_r1378796371 "mkdir" -p dist makensis -V4 -DVERSION=$(VERSION) -DOUT="../../../dist/grafana-agent-flow-installer.exe" ./packaging/grafana-agent-flow/windows/install_script.nsis endif From 27ba56a677651db432fb7531f79d4f2887be9f81 Mon Sep 17 00:00:00 2001 From: William Dumont Date: Tue, 5 Mar 2024 17:22:43 +0100 Subject: [PATCH 02/11] Loader reuse existing nodes on reload (#6288) * Move UpdateBlock from componentNode interface to blockNode interface. This change means that all blockNodes have now the possibility to update their managed block with the update River block content. * Update the loader to update the managed block of a config node on reload if it already existed in the graph. With this optimization, we re-use existing nodes and update them instead of creating a new node. This is especially useful for modules. * add two new tests to check that on reload the config nodes behave as expected * add updateblock to declare node * update loader logic to detect duplicated blocks and reuse already defined blocks * add updateblock to import config node * update changelog * move function and remove unnecessary check (cherry picked from commit 2e9d5a292c33d79b1591718faa7852b01a4af353) --- CHANGELOG.md | 8 ++ pkg/flow/internal/controller/block_node.go | 9 +- .../internal/controller/component_node.go | 6 +- pkg/flow/internal/controller/loader.go | 89 +++++++----- pkg/flow/internal/controller/loader_test.go | 130 ++++++++++++++++-- .../controller/node_config_argument.go | 17 +++ .../internal/controller/node_config_export.go | 17 +++ .../internal/controller/node_config_import.go | 16 +++ .../controller/node_config_logging.go | 17 +++ .../controller/node_config_tracing.go | 17 +++ pkg/flow/internal/controller/node_declare.go | 18 +++ .../internal/controller/scheduler_test.go | 1 + pkg/flow/internal/importsource/import_file.go | 5 + pkg/flow/internal/importsource/import_git.go | 5 + pkg/flow/internal/importsource/import_http.go | 5 + .../internal/importsource/import_source.go | 2 + .../internal/importsource/import_string.go | 5 + pkg/flow/module_eval_test.go | 105 ++++++++++++++ pkg/flow/module_test.go | 4 +- 19 files changed, 421 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4740c32e13e9..0c6122510bdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ changes that impact end-user behavior are listed; changes to documentation or internal API changes are not present. +### Bugfixes + +- Set permissions on the `Grafana Agent [Flow]` folder when installing via the + windows installer rather than relying on the parent folder permissions. (@erikbaranowski) + +- Fix an issue where the import config node would not run after a config reload. (@wildum) + +- Fix an issue where Loki could reject a batch of logs when structured metadata feature is used. (@thampiotr) v0.40.1 (2024-02-27) -------------------- diff --git a/pkg/flow/internal/controller/block_node.go b/pkg/flow/internal/controller/block_node.go index 0bb20a33eb67..49ac08c971aa 100644 --- a/pkg/flow/internal/controller/block_node.go +++ b/pkg/flow/internal/controller/block_node.go @@ -11,14 +11,15 @@ import ( type BlockNode interface { dag.Node - // Block returns the current block of the managed config node. + // Block returns the current block managed by the node. Block() *ast.BlockStmt - // Evaluate updates the arguments for the managed component - // by re-evaluating its River block with the provided scope. The managed component - // will be built the first time Evaluate is called. + // Evaluate updates the arguments by re-evaluating the River block with the provided scope. // // Evaluate will return an error if the River block cannot be evaluated or if // decoding to arguments fails. Evaluate(scope *vm.Scope) error + + // UpdateBlock updates the River block used to construct arguments. + UpdateBlock(b *ast.BlockStmt) } diff --git a/pkg/flow/internal/controller/component_node.go b/pkg/flow/internal/controller/component_node.go index 1a6e41605316..1deb18df353a 100644 --- a/pkg/flow/internal/controller/component_node.go +++ b/pkg/flow/internal/controller/component_node.go @@ -1,8 +1,7 @@ package controller import ( - "github.com/grafana/agent/component" - "github.com/grafana/river/ast" + "github.com/grafana/agent/internal/component" ) // ComponentNode is a generic representation of a Flow component. @@ -27,9 +26,6 @@ type ComponentNode interface { // ID returns the component ID of the managed component from its River block. ID() ComponentID - // UpdateBlock updates the River block used to construct arguments for the managed component. - UpdateBlock(b *ast.BlockStmt) - // ModuleIDs returns the current list of modules managed by the component. ModuleIDs() []string } diff --git a/pkg/flow/internal/controller/loader.go b/pkg/flow/internal/controller/loader.go index 79779837cce9..0523ec93d44a 100644 --- a/pkg/flow/internal/controller/loader.go +++ b/pkg/flow/internal/controller/loader.go @@ -338,9 +338,15 @@ func (l *Loader) splitComponentBlocks(blocks []*ast.BlockStmt) (componentBlocks, } func (l *Loader) populateDeclareNodes(g *dag.Graph, declareBlocks []*ast.BlockStmt) diag.Diagnostics { - var diags diag.Diagnostics + var ( + diags diag.Diagnostics + node *DeclareNode + blockMap = make(map[string]*ast.BlockStmt, len(declareBlocks)) + ) l.declareNodes = map[string]*DeclareNode{} for _, declareBlock := range declareBlocks { + id := BlockComponentID(declareBlock).String() + if declareBlock.Label == declareType { diags.Add(diag.Diagnostic{ Severity: diag.SeverityLevelError, @@ -350,16 +356,18 @@ func (l *Loader) populateDeclareNodes(g *dag.Graph, declareBlocks []*ast.BlockSt }) continue } - // TODO: if node already exists in the graph, update the block - // instead of copying it. - node := NewDeclareNode(declareBlock) - if g.GetByID(node.NodeID()) != nil { - diags.Add(diag.Diagnostic{ - Severity: diag.SeverityLevelError, - Message: fmt.Sprintf("cannot add declare node %q; node with same ID already exists", node.NodeID()), - }) + + if diag, defined := blockAlreadyDefined(blockMap, id, declareBlock); defined { + diags = append(diags, diag) continue } + + if exist := l.graph.GetByID(id); exist != nil { + node = exist.(*DeclareNode) + node.UpdateBlock(declareBlock) + } else { + node = NewDeclareNode(declareBlock) + } l.componentNodeManager.customComponentReg.registerDeclare(declareBlock) l.declareNodes[node.label] = node g.Add(node) @@ -367,6 +375,21 @@ func (l *Loader) populateDeclareNodes(g *dag.Graph, declareBlocks []*ast.BlockSt return diags } +// blockAlreadyDefined returns (diag, true) if the given id is already in the provided blockMap. +// else it adds the block to the map and returns (empty diag, false). +func blockAlreadyDefined(blockMap map[string]*ast.BlockStmt, id string, block *ast.BlockStmt) (diag.Diagnostic, bool) { + if orig, redefined := blockMap[id]; redefined { + return diag.Diagnostic{ + Severity: diag.SeverityLevelError, + Message: fmt.Sprintf("block %s already declared at %s", id, ast.StartPos(orig).Position()), + StartPos: block.NamePos.Position(), + EndPos: block.NamePos.Add(len(id) - 1).Position(), + }, true + } + blockMap[id] = block + return diag.Diagnostic{}, false +} + // populateServiceNodes adds service nodes to the graph. func (l *Loader) populateServiceNodes(g *dag.Graph, serviceBlocks []*ast.BlockStmt) diag.Diagnostics { var diags diag.Diagnostics @@ -441,25 +464,33 @@ func (l *Loader) populateServiceNodes(g *dag.Graph, serviceBlocks []*ast.BlockSt // populateConfigBlockNodes adds any config blocks to the graph. func (l *Loader) populateConfigBlockNodes(args map[string]any, g *dag.Graph, configBlocks []*ast.BlockStmt) diag.Diagnostics { var ( - diags diag.Diagnostics - nodeMap = NewConfigNodeMap() + diags diag.Diagnostics + nodeMap = NewConfigNodeMap() + blockMap = make(map[string]*ast.BlockStmt, len(configBlocks)) ) for _, block := range configBlocks { - node, newConfigNodeDiags := NewConfigNode(block, l.globals) - diags = append(diags, newConfigNodeDiags...) - - if g.GetByID(node.NodeID()) != nil { - configBlockStartPos := ast.StartPos(block).Position() - diags.Add(diag.Diagnostic{ - Severity: diag.SeverityLevelError, - Message: fmt.Sprintf("%q block already declared at %s", node.NodeID(), configBlockStartPos), - StartPos: configBlockStartPos, - EndPos: ast.EndPos(block).Position(), - }) - + var ( + node BlockNode + newConfigNodeDiags diag.Diagnostics + ) + id := BlockComponentID(block).String() + if diag, defined := blockAlreadyDefined(blockMap, id, block); defined { + diags = append(diags, diag) continue } + // Check the graph from the previous call to Load to see we can copy an + // existing instance of BlockNode. + if exist := l.graph.GetByID(id); exist != nil { + node = exist.(BlockNode) + node.UpdateBlock(block) + } else { + node, newConfigNodeDiags = NewConfigNode(block, l.globals) + diags = append(diags, newConfigNodeDiags...) + if diags.HasErrors() { + continue + } + } nodeMapDiags := nodeMap.Append(node) diags = append(diags, nodeMapDiags...) @@ -502,18 +533,10 @@ func (l *Loader) populateComponentNodes(g *dag.Graph, componentBlocks []*ast.Blo ) for _, block := range componentBlocks { id := BlockComponentID(block).String() - - if orig, redefined := blockMap[id]; redefined { - diags.Add(diag.Diagnostic{ - Severity: diag.SeverityLevelError, - Message: fmt.Sprintf("Component %s already declared at %s", id, ast.StartPos(orig).Position()), - StartPos: block.NamePos.Position(), - EndPos: block.NamePos.Add(len(id) - 1).Position(), - }) + if diag, defined := blockAlreadyDefined(blockMap, id, block); defined { + diags = append(diags, diag) continue } - blockMap[id] = block - // Check the graph from the previous call to Load to see if we can copy an // existing instance of ComponentNode. if exist := l.graph.GetByID(id); exist != nil { diff --git a/pkg/flow/internal/controller/loader_test.go b/pkg/flow/internal/controller/loader_test.go index 703ad1480e65..af9825935c2c 100644 --- a/pkg/flow/internal/controller/loader_test.go +++ b/pkg/flow/internal/controller/loader_test.go @@ -84,14 +84,30 @@ func TestLoader(t *testing.T) { t.Run("New Graph", func(t *testing.T) { l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(testFile), []byte(testConfig)) + diags := applyFromContent(t, l, []byte(testFile), []byte(testConfig), nil) require.NoError(t, diags.ErrorOrNil()) requireGraph(t, l.Graph(), testGraphDefinition) }) + t.Run("Reload Graph New Config", func(t *testing.T) { + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, []byte(testFile), []byte(testConfig), nil) + require.NoError(t, diags.ErrorOrNil()) + requireGraph(t, l.Graph(), testGraphDefinition) + updatedTestConfig := ` + tracing { + sampling_fraction = 2 + } + ` + diags = applyFromContent(t, l, []byte(testFile), []byte(updatedTestConfig), nil) + require.NoError(t, diags.ErrorOrNil()) + // Expect the same graph because tracing is still there and logging will be added by default. + requireGraph(t, l.Graph(), testGraphDefinition) + }) + t.Run("New Graph No Config", func(t *testing.T) { l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(testFile), nil) + diags := applyFromContent(t, l, []byte(testFile), nil, nil) require.NoError(t, diags.ErrorOrNil()) requireGraph(t, l.Graph(), testGraphDefinition) }) @@ -109,11 +125,11 @@ func TestLoader(t *testing.T) { } ` l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(startFile), []byte(testConfig)) + diags := applyFromContent(t, l, []byte(startFile), []byte(testConfig), nil) origGraph := l.Graph() require.NoError(t, diags.ErrorOrNil()) - diags = applyFromContent(t, l, []byte(testFile), []byte(testConfig)) + diags = applyFromContent(t, l, []byte(testFile), []byte(testConfig), nil) require.NoError(t, diags.ErrorOrNil()) newGraph := l.Graph() @@ -128,8 +144,8 @@ func TestLoader(t *testing.T) { } ` l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(invalidFile), nil) - require.ErrorContains(t, diags.ErrorOrNil(), `cannot retrieve the definition of component name "doesnotexist`) + diags := applyFromContent(t, l, []byte(invalidFile), nil, nil) + require.ErrorContains(t, diags.ErrorOrNil(), `cannot find the definition of component name "doesnotexist`) }) t.Run("Load with component with empty label", func(t *testing.T) { @@ -139,7 +155,7 @@ func TestLoader(t *testing.T) { } ` l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(invalidFile), nil) + diags := applyFromContent(t, l, []byte(invalidFile), nil, nil) require.ErrorContains(t, diags.ErrorOrNil(), `component "testcomponents.tick" must have a label`) }) @@ -158,7 +174,7 @@ func TestLoader(t *testing.T) { } ` l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(invalidFile), nil) + diags := applyFromContent(t, l, []byte(invalidFile), nil, nil) require.Error(t, diags.ErrorOrNil()) requireGraph(t, l.Graph(), graphDefinition{ @@ -186,9 +202,94 @@ func TestLoader(t *testing.T) { } ` l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(invalidFile), nil) + diags := applyFromContent(t, l, []byte(invalidFile), nil, nil) require.Error(t, diags.ErrorOrNil()) }) + + t.Run("Config block redefined", func(t *testing.T) { + invalidFile := ` + logging {} + logging {} + ` + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, nil, []byte(invalidFile), nil) + require.ErrorContains(t, diags.ErrorOrNil(), `block logging already declared at TestLoader/Config_block_redefined:2:4`) + }) + + t.Run("Config block redefined after reload", func(t *testing.T) { + file := ` + logging {} + ` + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, nil, []byte(file), nil) + require.NoError(t, diags.ErrorOrNil()) + invalidFile := ` + logging {} + logging {} + ` + diags = applyFromContent(t, l, nil, []byte(invalidFile), nil) + require.ErrorContains(t, diags.ErrorOrNil(), `block logging already declared at TestLoader/Config_block_redefined_after_reload:2:4`) + }) + + t.Run("Component block redefined", func(t *testing.T) { + invalidFile := ` + testcomponents.tick "ticker" { + frequency = "1s" + } + testcomponents.tick "ticker" { + frequency = "1s" + } + ` + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, []byte(invalidFile), nil, nil) + require.ErrorContains(t, diags.ErrorOrNil(), `block testcomponents.tick.ticker already declared at TestLoader/Component_block_redefined:2:4`) + }) + + t.Run("Component block redefined after reload", func(t *testing.T) { + file := ` + testcomponents.tick "ticker" { + frequency = "1s" + } + ` + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, []byte(file), nil, nil) + require.NoError(t, diags.ErrorOrNil()) + invalidFile := ` + testcomponents.tick "ticker" { + frequency = "1s" + } + testcomponents.tick "ticker" { + frequency = "1s" + } + ` + diags = applyFromContent(t, l, []byte(invalidFile), nil, nil) + require.ErrorContains(t, diags.ErrorOrNil(), `block testcomponents.tick.ticker already declared at TestLoader/Component_block_redefined_after_reload:2:4`) + }) + + t.Run("Declare block redefined", func(t *testing.T) { + invalidFile := ` + declare "a" {} + declare "a" {} + ` + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, nil, nil, []byte(invalidFile)) + require.ErrorContains(t, diags.ErrorOrNil(), `block declare.a already declared at TestLoader/Declare_block_redefined:2:4`) + }) + + t.Run("Declare block redefined after reload", func(t *testing.T) { + file := ` + declare "a" {} + ` + l := controller.NewLoader(newLoaderOptions()) + diags := applyFromContent(t, l, nil, nil, []byte(file)) + require.NoError(t, diags.ErrorOrNil()) + invalidFile := ` + declare "a" {} + declare "a" {} + ` + diags = applyFromContent(t, l, nil, nil, []byte(invalidFile)) + require.ErrorContains(t, diags.ErrorOrNil(), `block declare.a already declared at TestLoader/Declare_block_redefined_after_reload:2:4`) + }) } // TestScopeWithFailingComponent is used to ensure that the scope is filled out, even if the component @@ -228,13 +329,13 @@ func TestScopeWithFailingComponent(t *testing.T) { } l := controller.NewLoader(newLoaderOptions()) - diags := applyFromContent(t, l, []byte(testFile), nil) + diags := applyFromContent(t, l, []byte(testFile), nil, nil) require.Error(t, diags.ErrorOrNil()) require.Len(t, diags, 1) require.True(t, strings.Contains(diags.Error(), `unrecognized attribute name "frequenc"`)) } -func applyFromContent(t *testing.T, l *controller.Loader, componentBytes []byte, configBytes []byte) diag.Diagnostics { +func applyFromContent(t *testing.T, l *controller.Loader, componentBytes []byte, configBytes []byte, declareBytes []byte) diag.Diagnostics { t.Helper() var ( @@ -256,6 +357,13 @@ func applyFromContent(t *testing.T, l *controller.Loader, componentBytes []byte, } } + if string(declareBytes) != "" { + declareBlocks, diags = fileToBlock(t, declareBytes) + if diags.HasErrors() { + return diags + } + } + applyOptions := controller.ApplyOptions{ ComponentBlocks: componentBlocks, ConfigBlocks: configBlocks, diff --git a/pkg/flow/internal/controller/node_config_argument.go b/pkg/flow/internal/controller/node_config_argument.go index 5b979503f805..23c57987cce0 100644 --- a/pkg/flow/internal/controller/node_config_argument.go +++ b/pkg/flow/internal/controller/node_config_argument.go @@ -2,6 +2,7 @@ package controller import ( "fmt" + "strings" "sync" "github.com/grafana/river/ast" @@ -85,3 +86,19 @@ func (cn *ArgumentConfigNode) Block() *ast.BlockStmt { // NodeID implements dag.Node and returns the unique ID for the config node. func (cn *ArgumentConfigNode) NodeID() string { return cn.nodeID } + +// UpdateBlock updates the River block used to construct arguments. +// The new block isn't used until the next time Evaluate is invoked. +// +// UpdateBlock will panic if the block does not match the component ID of the +// ArgumentConfigNode. +func (cn *ArgumentConfigNode) UpdateBlock(b *ast.BlockStmt) { + if !BlockComponentID(b).Equals(strings.Split(cn.nodeID, ".")) { + panic("UpdateBlock called with an River block with a different ID") + } + + cn.mut.Lock() + defer cn.mut.Unlock() + cn.block = b + cn.eval = vm.New(b.Body) +} diff --git a/pkg/flow/internal/controller/node_config_export.go b/pkg/flow/internal/controller/node_config_export.go index 027335e629b4..314e9a3dd983 100644 --- a/pkg/flow/internal/controller/node_config_export.go +++ b/pkg/flow/internal/controller/node_config_export.go @@ -2,6 +2,7 @@ package controller import ( "fmt" + "strings" "sync" "github.com/grafana/river/ast" @@ -74,3 +75,19 @@ func (cn *ExportConfigNode) Block() *ast.BlockStmt { // NodeID implements dag.Node and returns the unique ID for the config node. func (cn *ExportConfigNode) NodeID() string { return cn.nodeID } + +// UpdateBlock updates the River block used to construct arguments. +// The new block isn't used until the next time Evaluate is invoked. +// +// UpdateBlock will panic if the block does not match the component ID of the +// ExportConfigNode. +func (cn *ExportConfigNode) UpdateBlock(b *ast.BlockStmt) { + if !BlockComponentID(b).Equals(strings.Split(cn.nodeID, ".")) { + panic("UpdateBlock called with an River block with a different ID") + } + + cn.mut.Lock() + defer cn.mut.Unlock() + cn.block = b + cn.eval = vm.New(b.Body) +} diff --git a/pkg/flow/internal/controller/node_config_import.go b/pkg/flow/internal/controller/node_config_import.go index 10ef832a96b6..60e57c1a54e8 100644 --- a/pkg/flow/internal/controller/node_config_import.go +++ b/pkg/flow/internal/controller/node_config_import.go @@ -385,6 +385,22 @@ func (cn *ImportConfigNode) run(errChan chan error, updateTasks func() error) er } } +// UpdateBlock updates the River block used to construct arguments. +// The new block isn't used until the next time Evaluate is invoked. +// +// UpdateBlock will panic if the block does not match the component ID of the +// ImportConfigNode. +func (cn *ImportConfigNode) UpdateBlock(b *ast.BlockStmt) { + if !BlockComponentID(b).Equals(strings.Split(cn.nodeID, ".")) { + panic("UpdateBlock called with an River block with a different ID") + } + + cn.mut.Lock() + defer cn.mut.Unlock() + cn.block = b + cn.source.SetEval(vm.New(b.Body)) +} + func (cn *ImportConfigNode) Label() string { return cn.label } // Block implements BlockNode and returns the current block of the managed config node. diff --git a/pkg/flow/internal/controller/node_config_logging.go b/pkg/flow/internal/controller/node_config_logging.go index 74a35fe6612c..00405459b015 100644 --- a/pkg/flow/internal/controller/node_config_logging.go +++ b/pkg/flow/internal/controller/node_config_logging.go @@ -2,6 +2,7 @@ package controller import ( "fmt" + "strings" "sync" "github.com/go-kit/log" @@ -80,3 +81,19 @@ func (cn *LoggingConfigNode) Block() *ast.BlockStmt { // NodeID implements dag.Node and returns the unique ID for the config node. func (cn *LoggingConfigNode) NodeID() string { return cn.nodeID } + +// UpdateBlock updates the River block used to construct arguments. +// The new block isn't used until the next time Evaluate is invoked. +// +// UpdateBlock will panic if the block does not match the component ID of the +// LoggingConfigNode. +func (cn *LoggingConfigNode) UpdateBlock(b *ast.BlockStmt) { + if !BlockComponentID(b).Equals(strings.Split(cn.nodeID, ".")) { + panic("UpdateBlock called with an River block with a different ID") + } + + cn.mut.Lock() + defer cn.mut.Unlock() + cn.block = b + cn.eval = vm.New(b.Body) +} diff --git a/pkg/flow/internal/controller/node_config_tracing.go b/pkg/flow/internal/controller/node_config_tracing.go index 4fb70e92c9dd..d64f68fbc5b3 100644 --- a/pkg/flow/internal/controller/node_config_tracing.go +++ b/pkg/flow/internal/controller/node_config_tracing.go @@ -2,6 +2,7 @@ package controller import ( "fmt" + "strings" "sync" "github.com/grafana/agent/pkg/flow/tracing" @@ -84,3 +85,19 @@ func (cn *TracingConfigNode) Block() *ast.BlockStmt { // NodeID implements dag.Node and returns the unique ID for the config node. func (cn *TracingConfigNode) NodeID() string { return cn.nodeID } + +// UpdateBlock updates the River block used to construct arguments. +// The new block isn't used until the next time Evaluate is invoked. +// +// UpdateBlock will panic if the block does not match the component ID of the +// LoggingConfigNode. +func (cn *TracingConfigNode) UpdateBlock(b *ast.BlockStmt) { + if !BlockComponentID(b).Equals(strings.Split(cn.nodeID, ".")) { + panic("UpdateBlock called with an River block with a different ID") + } + + cn.mut.Lock() + defer cn.mut.Unlock() + cn.block = b + cn.eval = vm.New(b.Body) +} diff --git a/pkg/flow/internal/controller/node_declare.go b/pkg/flow/internal/controller/node_declare.go index b67350eb5540..0dec60283908 100644 --- a/pkg/flow/internal/controller/node_declare.go +++ b/pkg/flow/internal/controller/node_declare.go @@ -1,6 +1,9 @@ package controller import ( + "strings" + "sync" + "github.com/grafana/river/ast" "github.com/grafana/river/vm" ) @@ -10,6 +13,7 @@ type DeclareNode struct { label string nodeID string componentName string + mut sync.RWMutex block *ast.BlockStmt } @@ -42,3 +46,17 @@ func (cn *DeclareNode) Block() *ast.BlockStmt { // NodeID implements dag.Node and returns the unique ID for the config node. func (cn *DeclareNode) NodeID() string { return cn.nodeID } + +// UpdateBlock updates the managed River block. +// +// UpdateBlock will panic if the block does not match the component ID of the +// DeclareNode. +func (cn *DeclareNode) UpdateBlock(b *ast.BlockStmt) { + if !BlockComponentID(b).Equals(strings.Split(cn.nodeID, ".")) { + panic("UpdateBlock called with an River block with a different ID") + } + + cn.mut.Lock() + defer cn.mut.Unlock() + cn.block = b +} diff --git a/pkg/flow/internal/controller/scheduler_test.go b/pkg/flow/internal/controller/scheduler_test.go index c965d99c9db7..57c6c65c97d1 100644 --- a/pkg/flow/internal/controller/scheduler_test.go +++ b/pkg/flow/internal/controller/scheduler_test.go @@ -99,6 +99,7 @@ func (fr fakeRunnable) NodeID() string { return fr.ID } func (fr fakeRunnable) Run(ctx context.Context) error { return fr.Component.Run(ctx) } func (fr fakeRunnable) Block() *ast.BlockStmt { return nil } func (fr fakeRunnable) Evaluate(scope *vm.Scope) error { return nil } +func (fr fakeRunnable) UpdateBlock(b *ast.BlockStmt) {} type mockComponent struct { RunFunc func(ctx context.Context) error diff --git a/pkg/flow/internal/importsource/import_file.go b/pkg/flow/internal/importsource/import_file.go index bde2f635b6f9..97ce7a5c4085 100644 --- a/pkg/flow/internal/importsource/import_file.go +++ b/pkg/flow/internal/importsource/import_file.go @@ -96,3 +96,8 @@ func (im *ImportFile) Run(ctx context.Context) error { func (im *ImportFile) CurrentHealth() component.Health { return im.fileComponent.CurrentHealth() } + +// Update the evaluator. +func (im *ImportFile) SetEval(eval *vm.Evaluator) { + im.eval = eval +} diff --git a/pkg/flow/internal/importsource/import_git.go b/pkg/flow/internal/importsource/import_git.go index ba7a5aa3081f..f27c4ffc2edf 100644 --- a/pkg/flow/internal/importsource/import_git.go +++ b/pkg/flow/internal/importsource/import_git.go @@ -254,3 +254,8 @@ func (im *ImportGit) CurrentHealth() component.Health { defer im.healthMut.RUnlock() return im.health } + +// Update the evaluator. +func (im *ImportGit) SetEval(eval *vm.Evaluator) { + im.eval = eval +} diff --git a/pkg/flow/internal/importsource/import_http.go b/pkg/flow/internal/importsource/import_http.go index 1d0673445c70..9fae17db4f5d 100644 --- a/pkg/flow/internal/importsource/import_http.go +++ b/pkg/flow/internal/importsource/import_http.go @@ -101,3 +101,8 @@ func (im *ImportHTTP) Run(ctx context.Context) error { func (im *ImportHTTP) CurrentHealth() component.Health { return im.managedRemoteHTTP.CurrentHealth() } + +// Update the evaluator. +func (im *ImportHTTP) SetEval(eval *vm.Evaluator) { + im.eval = eval +} diff --git a/pkg/flow/internal/importsource/import_source.go b/pkg/flow/internal/importsource/import_source.go index f1ef6e72ac1a..aed03ca20406 100644 --- a/pkg/flow/internal/importsource/import_source.go +++ b/pkg/flow/internal/importsource/import_source.go @@ -32,6 +32,8 @@ type ImportSource interface { Run(ctx context.Context) error // CurrentHealth returns the current Health status of the running source. CurrentHealth() component.Health + // Update evaluator + SetEval(eval *vm.Evaluator) } // NewImportSource creates a new ImportSource depending on the type. diff --git a/pkg/flow/internal/importsource/import_string.go b/pkg/flow/internal/importsource/import_string.go index aae1ebc07040..826f3e096dc4 100644 --- a/pkg/flow/internal/importsource/import_string.go +++ b/pkg/flow/internal/importsource/import_string.go @@ -58,3 +58,8 @@ func (im *ImportString) CurrentHealth() component.Health { Health: component.HealthTypeHealthy, } } + +// Update the evaluator. +func (im *ImportString) SetEval(eval *vm.Evaluator) { + im.eval = eval +} diff --git a/pkg/flow/module_eval_test.go b/pkg/flow/module_eval_test.go index 81bd1b381fab..8e7b0f341313 100644 --- a/pkg/flow/module_eval_test.go +++ b/pkg/flow/module_eval_test.go @@ -209,6 +209,111 @@ func TestUpdates_TwoModules_SameCompNames(t *testing.T) { }, 3*time.Second, 10*time.Millisecond) } +func TestUpdates_ReloadConfig(t *testing.T) { + // We use this module in a Flow config below. + module := ` + argument "input" { + optional = false + } + + testcomponents.passthrough "pt" { + input = argument.input.value + lag = "1ms" + } + + export "output" { + value = testcomponents.passthrough.pt.output + } +` + + // We send the count increments via module and to the summation component and verify that the updates propagate. + config := ` + testcomponents.count "inc" { + frequency = "10ms" + max = 10 + } + + module.string "test" { + content = ` + strconv.Quote(module) + ` + arguments { + input = testcomponents.count.inc.count + } + } + + testcomponents.summation "sum" { + input = module.string.test.exports.output + } +` + + ctrl := flow.New(testOptions(t)) + f, err := flow.ParseSource(t.Name(), []byte(config)) + require.NoError(t, err) + require.NotNil(t, f) + + err = ctrl.LoadSource(f, nil) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + done := make(chan struct{}) + go func() { + ctrl.Run(ctx) + close(done) + }() + defer func() { + cancel() + <-done + }() + + require.Eventually(t, func() bool { + export := getExport[testcomponents.SummationExports](t, ctrl, "", "testcomponents.summation.sum") + return export.LastAdded == 10 + }, 3*time.Second, 10*time.Millisecond) + + // Reload with a new export. + module = ` + argument "input" { + optional = false + } + + testcomponents.passthrough "pt" { + input = argument.input.value + lag = "1ms" + } + + export "output" { + value = -10 + } +` + config = ` + testcomponents.count "inc" { + frequency = "10ms" + max = 10 + } + + module.string "test" { + content = ` + strconv.Quote(module) + ` + arguments { + input = testcomponents.count.inc.count + } + } + + testcomponents.summation "sum" { + input = module.string.test.exports.output + } +` + f, err = flow.ParseSource(t.Name(), []byte(config)) + require.NoError(t, err) + require.NotNil(t, f) + + err = ctrl.LoadSource(f, nil) + require.NoError(t, err) + + require.Eventually(t, func() bool { + export := getExport[testcomponents.SummationExports](t, ctrl, "", "testcomponents.summation.sum") + return export.LastAdded == -10 + }, 3*time.Second, 10*time.Millisecond) +} + func testOptions(t *testing.T) flow.Options { t.Helper() s, err := logging.New(os.Stderr, logging.DefaultOptions) diff --git a/pkg/flow/module_test.go b/pkg/flow/module_test.go index c5f4417c84c3..f35b18b80273 100644 --- a/pkg/flow/module_test.go +++ b/pkg/flow/module_test.go @@ -102,13 +102,13 @@ func TestModule(t *testing.T) { name: "Duplicate argument config", argumentModuleContent: argumentConfig + argumentConfig, exportModuleContent: exportStringConfig, - expectedErrorContains: "\"argument.username\" block already declared", + expectedErrorContains: "block argument.username already declared at t1:2:2", }, { name: "Duplicate export config", argumentModuleContent: argumentConfig, exportModuleContent: exportStringConfig + exportStringConfig, - expectedErrorContains: "\"export.username\" block already declared", + expectedErrorContains: "block export.username already declared at t1:7:2", }, { name: "Multiple exports but none are used but still exported", From 2fec7fc1f13c329e33821c77497fa027f14ba2de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BB=97=20Tr=E1=BB=8Dng=20H=E1=BA=A3i?= <41283691+hainenber@users.noreply.github.com> Date: Tue, 5 Mar 2024 23:24:09 +0700 Subject: [PATCH 03/11] fix(static/metrics/instance): fix duplicate metrics registration panic when recreating the instance (#6608) Signed-off-by: hainenber (cherry picked from commit 7a61067e0007b961f0e45a056990ba217033733d) --- CHANGELOG.md | 3 +++ pkg/metrics/instance/instance.go | 2 +- pkg/metrics/instance/instance_test.go | 5 +++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c6122510bdb..47d8edea0997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ internal API changes are not present. - Fix an issue where Loki could reject a batch of logs when structured metadata feature is used. (@thampiotr) +- Fix a duplicate metrics registration panic when recreating static + mode metric instance's write handler. (@rfratto, @hainenber) + v0.40.1 (2024-02-27) -------------------- diff --git a/pkg/metrics/instance/instance.go b/pkg/metrics/instance/instance.go index c81c8e620622..e4cc1113f7b1 100644 --- a/pkg/metrics/instance/instance.go +++ b/pkg/metrics/instance/instance.go @@ -409,7 +409,7 @@ func (i *Instance) initialize(ctx context.Context, reg prometheus.Registerer, cf return fmt.Errorf("error creating WAL: %w", err) } - i.writeHandler = remote.NewWriteHandler(i.logger, i.reg, i.wal) + i.writeHandler = remote.NewWriteHandler(i.logger, reg, i.wal) i.discovery, err = i.newDiscoveryManager(ctx, cfg) if err != nil { diff --git a/pkg/metrics/instance/instance_test.go b/pkg/metrics/instance/instance_test.go index e82117e797df..4ba6e4d3eb4d 100644 --- a/pkg/metrics/instance/instance_test.go +++ b/pkg/metrics/instance/instance_test.go @@ -258,7 +258,8 @@ func TestInstance_Recreate(t *testing.T) { cfg.RemoteFlushDeadline = time.Hour logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr)) - inst, err := New(prometheus.NewRegistry(), cfg, walDir, logger) + currentReg := prometheus.NewRegistry() + inst, err := New(currentReg, cfg, walDir, logger) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) @@ -278,7 +279,7 @@ func TestInstance_Recreate(t *testing.T) { // Recreate the instance, no panic should happen. require.NotPanics(t, func() { - inst, err := New(prometheus.NewRegistry(), cfg, walDir, logger) + inst, err := New(currentReg, cfg, walDir, logger) require.NoError(t, err) runInstance(t, inst) From a6328c2fab89a7ea704dc4905efa98f4ecf22179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BB=97=20Tr=E1=BB=8Dng=20H=E1=BA=A3i?= <41283691+hainenber@users.noreply.github.com> Date: Wed, 6 Mar 2024 01:32:13 +0700 Subject: [PATCH 04/11] chore(build): upgrade base image to frequently updated ECR-hosted Ubuntu (#6612) Signed-off-by: hainenber (cherry picked from commit fe513a4aaeeaa21a8dc05d2322a7950225d59691) --- cmd/grafana-agent-operator/Dockerfile | 2 +- cmd/grafana-agent/Dockerfile | 2 +- cmd/grafana-agentctl/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/grafana-agent-operator/Dockerfile b/cmd/grafana-agent-operator/Dockerfile index 6090efd5681f..6ba2a6218cd7 100644 --- a/cmd/grafana-agent-operator/Dockerfile +++ b/cmd/grafana-agent-operator/Dockerfile @@ -22,7 +22,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ RELEASE_BUILD=${RELEASE_BUILD} VERSION=${VERSION} \ make operator -FROM ubuntu:mantic +FROM public.ecr.aws/ubuntu/ubuntu:mantic LABEL org.opencontainers.image.source="https://github.com/grafana/agent" diff --git a/cmd/grafana-agent/Dockerfile b/cmd/grafana-agent/Dockerfile index f602125dfb04..132d1317495c 100644 --- a/cmd/grafana-agent/Dockerfile +++ b/cmd/grafana-agent/Dockerfile @@ -30,7 +30,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ GOEXPERIMENT=${GOEXPERIMENT} \ make agent -FROM ubuntu:mantic +FROM public.ecr.aws/ubuntu/ubuntu:mantic LABEL org.opencontainers.image.source="https://github.com/grafana/agent" diff --git a/cmd/grafana-agentctl/Dockerfile b/cmd/grafana-agentctl/Dockerfile index 6f601fb7eed2..67fe64c6f3bf 100644 --- a/cmd/grafana-agentctl/Dockerfile +++ b/cmd/grafana-agentctl/Dockerfile @@ -23,7 +23,7 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ GO_TAGS="netgo promtail_journal_enabled" \ make agentctl -FROM ubuntu:mantic +FROM public.ecr.aws/ubuntu/ubuntu:mantic LABEL org.opencontainers.image.source="https://github.com/grafana/agent" From 3707e6d9b8d567fffb5788bd08245656a780bf4a Mon Sep 17 00:00:00 2001 From: Robert Fratto Date: Tue, 5 Mar 2024 13:52:21 -0500 Subject: [PATCH 05/11] prepare for 0.40.2 release (#6619) (cherry picked from commit ed541483b8736af8b9af3e904bc960811447c4fe) --- CHANGELOG.md | 7 +++++++ docs/sources/_index.md | 2 +- pkg/operator/defaults.go | 2 +- tools/gen-versioned-files/agent-version.txt | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47d8edea0997..bd5e183a82cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ changes that impact end-user behavior are listed; changes to documentation or internal API changes are not present. +v0.40.2 (2024-03-05) +-------------------- + ### Bugfixes - Set permissions on the `Grafana Agent [Flow]` folder when installing via the @@ -20,6 +23,10 @@ internal API changes are not present. - Fix a duplicate metrics registration panic when recreating static mode metric instance's write handler. (@rfratto, @hainenber) +### Other changes + +- Change the Docker base image for Linux containers to `public.ecr.aws/ubuntu/ubuntu:mantic`. (@hainenber) + v0.40.1 (2024-02-27) -------------------- diff --git a/docs/sources/_index.md b/docs/sources/_index.md index 556ea167a769..6300bb5df2db 100644 --- a/docs/sources/_index.md +++ b/docs/sources/_index.md @@ -9,7 +9,7 @@ title: Grafana Agent description: Grafana Agent is a flexible, performant, vendor-neutral, telemetry collector weight: 350 cascade: - AGENT_RELEASE: v0.40.1 + AGENT_RELEASE: v0.40.2 OTEL_VERSION: v0.87.0 --- diff --git a/pkg/operator/defaults.go b/pkg/operator/defaults.go index e985937bb348..52005e52976a 100644 --- a/pkg/operator/defaults.go +++ b/pkg/operator/defaults.go @@ -2,7 +2,7 @@ package operator // Supported versions of the Grafana Agent. var ( - DefaultAgentVersion = "v0.40.1" + DefaultAgentVersion = "v0.40.2" DefaultAgentBaseImage = "grafana/agent" DefaultAgentImage = DefaultAgentBaseImage + ":" + DefaultAgentVersion ) diff --git a/tools/gen-versioned-files/agent-version.txt b/tools/gen-versioned-files/agent-version.txt index 01437515a7c3..1e24a0583af0 100644 --- a/tools/gen-versioned-files/agent-version.txt +++ b/tools/gen-versioned-files/agent-version.txt @@ -1 +1 @@ -v0.40.1 +v0.40.2 From aae826ea262fce8a727f49364d88ad0bc250453b Mon Sep 17 00:00:00 2001 From: Piotr <17101802+thampiotr@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:03:52 +0000 Subject: [PATCH 06/11] Port promtail changes part 1 (#6559) * Port promtail changes part 1 * changelog (cherry picked from commit 1a642cfd182af8db8ece56f3c1174ad4092fedb3) --- CHANGELOG.md | 2 + component/common/loki/client/batch.go | 14 ++- component/common/loki/client/batch_test.go | 3 +- component/common/loki/client/client.go | 2 +- component/common/loki/client/client_test.go | 12 +++ component/common/loki/client/queue_client.go | 2 +- web/ui/build/asset-manifest.json | 26 ++++++ web/ui/build/favicon.ico | Bin 0 -> 16958 bytes web/ui/build/index.html | 1 + web/ui/build/manifest.json | 15 ++++ web/ui/build/robots.txt | 3 + web/ui/build/static/css/main.d3ff49f0.css | 3 + web/ui/build/static/js/main.180d839c.js | 2 + .../static/js/main.180d839c.js.LICENSE.txt | 81 ++++++++++++++++++ ...e-v21-latin-500.3452777c99809dd85b2a.woff2 | Bin 0 -> 21792 bytes ...1-latin-regular.e662d57ce51fba1f46e3.woff2 | Bin 0 -> 21724 bytes .../logo.c578039fa12bc65fb40a9b7ee1391e66.svg | 1 + ...o-v30-latin-100.30fb0679553d179c3343.woff2 | Bin 0 -> 15764 bytes ...latin-100italic.d3935eb61aa8422388e2.woff2 | Bin 0 -> 17060 bytes ...o-v30-latin-300.c48fb6765a9fcb00b330.woff2 | Bin 0 -> 15740 bytes ...latin-300italic.1128daa312ec555266d5.woff2 | Bin 0 -> 17508 bytes ...o-v30-latin-500.f25d774ecfe0996f8eb5.woff2 | Bin 0 -> 15920 bytes ...latin-500italic.3a43b67e5bbdfb3ab0a6.woff2 | Bin 0 -> 17336 bytes ...o-v30-latin-700.227c93190fe7f82de3f8.woff2 | Bin 0 -> 15860 bytes ...latin-700italic.d92a5d1451f249359639.woff2 | Bin 0 -> 17032 bytes ...o-v30-latin-900.2e8becfcae330421664b.woff2 | Bin 0 -> 15752 bytes ...latin-900italic.5b387ea565e67898ca3a.woff2 | Bin 0 -> 17552 bytes ...30-latin-italic.e10742dbb1d4a0864ba8.woff2 | Bin 0 -> 17368 bytes ...0-latin-regular.b009a76ad6afe4ebd301.woff2 | Bin 0 -> 15744 bytes 29 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 web/ui/build/asset-manifest.json create mode 100644 web/ui/build/favicon.ico create mode 100644 web/ui/build/index.html create mode 100644 web/ui/build/manifest.json create mode 100644 web/ui/build/robots.txt create mode 100644 web/ui/build/static/css/main.d3ff49f0.css create mode 100644 web/ui/build/static/js/main.180d839c.js create mode 100644 web/ui/build/static/js/main.180d839c.js.LICENSE.txt create mode 100644 web/ui/build/static/media/fira-code-v21-latin-500.3452777c99809dd85b2a.woff2 create mode 100644 web/ui/build/static/media/fira-code-v21-latin-regular.e662d57ce51fba1f46e3.woff2 create mode 100644 web/ui/build/static/media/logo.c578039fa12bc65fb40a9b7ee1391e66.svg create mode 100644 web/ui/build/static/media/roboto-v30-latin-100.30fb0679553d179c3343.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-100italic.d3935eb61aa8422388e2.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-300.c48fb6765a9fcb00b330.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-300italic.1128daa312ec555266d5.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-500.f25d774ecfe0996f8eb5.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-500italic.3a43b67e5bbdfb3ab0a6.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-700.227c93190fe7f82de3f8.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-700italic.d92a5d1451f249359639.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-900.2e8becfcae330421664b.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-900italic.5b387ea565e67898ca3a.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-italic.e10742dbb1d4a0864ba8.woff2 create mode 100644 web/ui/build/static/media/roboto-v30-latin-regular.b009a76ad6afe4ebd301.woff2 diff --git a/CHANGELOG.md b/CHANGELOG.md index bd5e183a82cb..400537258226 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ v0.40.1 (2024-02-27) - Fix an issue where flow mode panics if the `logging` config block is given a `null` Loki receiver to write log entries to. (@rfratto) +- Fix an issue where Loki could reject a batch of logs when structured metadata feature is used. (@thampiotr) + v0.40.0 (2024-02-27) -------------------- diff --git a/component/common/loki/client/batch.go b/component/common/loki/client/batch.go index 66a2ac7859de..473ada73e831 100644 --- a/component/common/loki/client/batch.go +++ b/component/common/loki/client/batch.go @@ -61,7 +61,7 @@ func newBatch(maxStreams int, entries ...loki.Entry) *batch { // add an entry to the batch func (b *batch) add(entry loki.Entry) error { - b.totalBytes += len(entry.Line) + b.totalBytes += entrySize(entry.Entry) // Append the entry to an already existing stream (if any) labels := labelsMapToString(entry.Labels, ReservedLabelTenantID) @@ -150,8 +150,8 @@ func (b *batch) sizeBytes() int { // sizeBytesAfter returns the size of the batch after the input entry // will be added to the batch itself -func (b *batch) sizeBytesAfter(line string) int { - return b.totalBytes + len(line) +func (b *batch) sizeBytesAfter(entry logproto.Entry) int { + return b.totalBytes + entrySize(entry) } // age of the batch since its creation @@ -201,3 +201,11 @@ func (b *batch) reportAsSentData(h SentDataMarkerHandler) { h.UpdateSentData(seg, data) } } + +func entrySize(entry logproto.Entry) int { + structuredMetadataSize := 0 + for _, label := range entry.StructuredMetadata { + structuredMetadataSize += label.Size() + } + return len(entry.Line) + structuredMetadataSize +} diff --git a/component/common/loki/client/batch_test.go b/component/common/loki/client/batch_test.go index 2701f0a0c717..a495470cfc15 100644 --- a/component/common/loki/client/batch_test.go +++ b/component/common/loki/client/batch_test.go @@ -57,8 +57,9 @@ func TestBatch_add(t *testing.T) { inputEntries: []loki.Entry{ {Labels: model.LabelSet{}, Entry: logEntries[0].Entry}, {Labels: model.LabelSet{}, Entry: logEntries[1].Entry}, + {Labels: model.LabelSet{}, Entry: logEntries[7].Entry}, }, - expectedSizeBytes: len(logEntries[0].Entry.Line) + len(logEntries[1].Entry.Line), + expectedSizeBytes: entrySize(logEntries[0].Entry) + entrySize(logEntries[0].Entry) + entrySize(logEntries[7].Entry), }, "multiple streams with multiple log entries": { inputEntries: []loki.Entry{ diff --git a/component/common/loki/client/client.go b/component/common/loki/client/client.go index 5b426b4a1873..428066e862b9 100644 --- a/component/common/loki/client/client.go +++ b/component/common/loki/client/client.go @@ -308,7 +308,7 @@ func (c *client) run() { // If adding the entry to the batch will increase the size over the max // size allowed, we do send the current batch and then create a new one - if batch.sizeBytesAfter(e.Line) > c.cfg.BatchSize { + if batch.sizeBytesAfter(e.Entry) > c.cfg.BatchSize { c.sendBatch(tenantID, batch) batches[tenantID] = newBatch(c.maxStreams, e) diff --git a/component/common/loki/client/client_test.go b/component/common/loki/client/client_test.go index a253fdf61335..aad46e4fa1ea 100644 --- a/component/common/loki/client/client_test.go +++ b/component/common/loki/client/client_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "github.com/grafana/loki/pkg/push" + "github.com/go-kit/log" "github.com/grafana/dskit/backoff" "github.com/grafana/dskit/flagext" @@ -34,6 +36,16 @@ var logEntries = []loki.Entry{ {Labels: model.LabelSet{"__tenant_id__": "tenant-1"}, Entry: logproto.Entry{Timestamp: time.Unix(5, 0).UTC(), Line: "line5"}}, {Labels: model.LabelSet{"__tenant_id__": "tenant-2"}, Entry: logproto.Entry{Timestamp: time.Unix(6, 0).UTC(), Line: "line6"}}, {Labels: model.LabelSet{}, Entry: logproto.Entry{Timestamp: time.Unix(6, 0).UTC(), Line: "line0123456789"}}, + { + Labels: model.LabelSet{}, + Entry: logproto.Entry{ + Timestamp: time.Unix(7, 0).UTC(), + Line: "line7", + StructuredMetadata: push.LabelsAdapter{ + {Name: "trace_id", Value: "12345"}, + }, + }, + }, } func TestClient_Handle(t *testing.T) { diff --git a/component/common/loki/client/queue_client.go b/component/common/loki/client/queue_client.go index edd9c25bbd37..edb0bbf9a816 100644 --- a/component/common/loki/client/queue_client.go +++ b/component/common/loki/client/queue_client.go @@ -344,7 +344,7 @@ func (c *queueClient) appendSingleEntry(segmentNum int, lbs model.LabelSet, e lo // If adding the entry to the batch will increase the size over the max // size allowed, we do send the current batch and then create a new one - if batch.sizeBytesAfter(e.Line) > c.cfg.BatchSize { + if batch.sizeBytesAfter(e) > c.cfg.BatchSize { c.sendQueue.enqueue(queuedBatch{ TenantID: tenantID, Batch: batch, diff --git a/web/ui/build/asset-manifest.json b/web/ui/build/asset-manifest.json new file mode 100644 index 000000000000..2451e3a2051f --- /dev/null +++ b/web/ui/build/asset-manifest.json @@ -0,0 +1,26 @@ +{ + "files": { + "main.css": "./public/static/css/main.d3ff49f0.css", + "main.js": "./public/static/js/main.180d839c.js", + "static/media/fira-code-v21-latin-500.woff2": "./public/static/media/fira-code-v21-latin-500.3452777c99809dd85b2a.woff2", + "static/media/fira-code-v21-latin-regular.woff2": "./public/static/media/fira-code-v21-latin-regular.e662d57ce51fba1f46e3.woff2", + "static/media/roboto-v30-latin-900italic.woff2": "./public/static/media/roboto-v30-latin-900italic.5b387ea565e67898ca3a.woff2", + "static/media/roboto-v30-latin-300italic.woff2": "./public/static/media/roboto-v30-latin-300italic.1128daa312ec555266d5.woff2", + "static/media/roboto-v30-latin-italic.woff2": "./public/static/media/roboto-v30-latin-italic.e10742dbb1d4a0864ba8.woff2", + "static/media/roboto-v30-latin-500italic.woff2": "./public/static/media/roboto-v30-latin-500italic.3a43b67e5bbdfb3ab0a6.woff2", + "static/media/roboto-v30-latin-100italic.woff2": "./public/static/media/roboto-v30-latin-100italic.d3935eb61aa8422388e2.woff2", + "static/media/roboto-v30-latin-700italic.woff2": "./public/static/media/roboto-v30-latin-700italic.d92a5d1451f249359639.woff2", + "static/media/roboto-v30-latin-500.woff2": "./public/static/media/roboto-v30-latin-500.f25d774ecfe0996f8eb5.woff2", + "static/media/roboto-v30-latin-700.woff2": "./public/static/media/roboto-v30-latin-700.227c93190fe7f82de3f8.woff2", + "static/media/roboto-v30-latin-100.woff2": "./public/static/media/roboto-v30-latin-100.30fb0679553d179c3343.woff2", + "static/media/roboto-v30-latin-900.woff2": "./public/static/media/roboto-v30-latin-900.2e8becfcae330421664b.woff2", + "static/media/roboto-v30-latin-regular.woff2": "./public/static/media/roboto-v30-latin-regular.b009a76ad6afe4ebd301.woff2", + "static/media/roboto-v30-latin-300.woff2": "./public/static/media/roboto-v30-latin-300.c48fb6765a9fcb00b330.woff2", + "static/media/logo.svg": "./public/static/media/logo.c578039fa12bc65fb40a9b7ee1391e66.svg", + "index.html": "./public/index.html" + }, + "entrypoints": [ + "static/css/main.d3ff49f0.css", + "static/js/main.180d839c.js" + ] +} \ No newline at end of file diff --git a/web/ui/build/favicon.ico b/web/ui/build/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..497d0dd94739e199176c137b5273eecaa1f426bf GIT binary patch literal 16958 zcmeI4Yj9Q76@WLjBb})uwc{uqG*1$Ooz6Iws?%u)>yJ8pIGxTgt<_d-eL#3ed>{x3 z@`x6}pooBYc}SEf(kfO`Ud95N2ndKY)ha~kOn)fk=7xKd+BCc0+WYKt&po-XWa^CC z(D__v@3qf9XMKB}YyY59L-^lSS1JBkq$;jf>H?)y1u&&*K<3S#tCafsg%&%Zl-7EX zK?j39FxUfwJ@9|n1BGvP?F0?C6&~zThBt{xe(2?!19PhIFl(A&Z-NLd@P@|$;sI|j z*^|8rghO2gaCO1qu3y0vxYJ`w!4WejIawoXE#AH6*|L}HyWe}x>qO=Xj=|9s_A=J+ zqtLutcXPqpHu125ay(87|~Ldp5!P#kq5Eg!(xX7y-SYp$hE0Mwl}e|8nkq>%W-%czkX%POVq%U+*^_#bss=l1tCa%#Y{Z zi`mcinyX(N&@aZ(n_VM_y`JYPZ_ecL>H2Cd*W&p&=NH4FhKO+~d!Wr9RoyaywCbTqJWvQoEe}zC;0Q8$qYVdKI^sX(pF1ecd+VK;FT= ztMqG2LVD0SoyN8873mq*H*X|Xn>G6rC#WR`8a7E?MX$ncTVoM5!c@@E1K%)fnwa04 zm~G~9=c4CPTxKTe(m74WphsC39EYz{o!)ECPCUGxxDY<^oX;Sd^W=SPU(0V*bK)t_ z`QMA060M-&El@?fV0)Yh;^NiBQ=s7kGk%5nrbMkbC-X_HM{$`Q>(hG6a-G#<(6PAM z%RAYglwNq>>(@=DU!{&$K>Ai3y_PuSx!q5lvx|1ewP9C$SeSpA1IRA zcgKH1)O~0Q%*nNnaVviN5_FgAI+s(M|FP-MJ&F0IC#~Cs=G^RAN!)j3Y_`mX6=skJF_+&H&h z-@!p6oCx&m0pn^1HEoX<7yUVY7_?zKQIK(C{2#daCdj%Q%)HCHDDLvX`gNYu$6QW> z`Sf0|H+|X^zl2`>(DZL#mq&3^Zd}QkN^OmCRlF_!3-}1Mp)o!g2j=&HvE=KD8_9*> zUh!moIfuETbC)gV<21NN{O*X?nR@KED&O)1=rKLJGyV}h`%B};eGm3rRgu*9C&LD! zhNCj}yr|-rOfKT(bn(lq$%XTnErwi%-4@#(?2p@syfgLM-*EXY-yYxV_3Z|totNKw zDBgO;@*>ev&zy$8`Z>2|>zRnjy+q!CgO_q(U5d}la@Jbd@ih4aho0AFY9vom3*pO=~36qF1DC8FURZY zSvP0n7HUhSp0S2jfBp}wu|$YEE7qO(%T6Yb!TDT1gZZRW>Ct3g+v^t3x%75Qu4MBW z6{4Q8hSt!$tc#R9Pc9#DSmNRN6sPIQ<<#YKIhFhie51*Jb$#37^=y4OSJFWJsnj#p z(CW`W%Nk3BsMGQs^Z8=^isQcI<2JM=N1`q=feDtV?eOg(cNTK(K6 z)>y77*>t8BFEb3Ah=Lo318W4AcVicmJuAK2;`MAj(e<*8Pq9ZT&oI{T zmOsDIU$c<89%#+TMsk_3PQ`0(o@Pydu>IOY&n`55>%7>w2TvNF_I-Kz(si9G#0JK? zbbaRsFvQPoVBPx82uMzsZpaf{mU`e!yk=%2xqPtwDLtBwi0Mf=GwEyFd+!l7Z1Bcz zUX@0uE0qO|wa52L*N}fAX4kBx{MM~{PicMab3ckPpZ=h^NM$r^OD}a(s#bG zvlhQ9h^bF%Oj68s4`}!|j5GC%gC{%Jg3e0PopYEuX7ZSAK9}Ehyra}Etn2(44!ZrG zUEf(QPEuG+U45Bcx++7SEQ^II#D>66 zVJ=LEL!h(rc&r0oWz=W(8Toij_E8c`*Vs9np3Rz*0k0>`+!KMill5C?tJrfD4pKcQ zy(fG15YMiHYPgnXo@HFx@1ei-`|m#TF=|*Ii-69;$K=lE9hG42c{Da+Ct4LM$Gf2&jfKE+%wqwa-F&V z&6$l{Y3f!Zml2my|1zE}JQ5%|zL7dz-HJ7e@mA2#Y{oJt^^1q)vFqUH(i>)6M|>D0 zx;eMrjUS8M>R9HI_+T%RS_J3H$%v0#SmGLQ zjqz;GU;0V@oyh;s3uD&Go?+ZOE%u%*&tKB97<5{ecHB|M8hK~)?hmp4;f{s4(*d3{ zYuK|)kTrrlLvUlFD1NTBT?|&LJbbC>*mqQiQ2-F;=j=Af|N&R2N^&EH*YCJ0OxjEo8=vR7k z8n}M7y&LcvbS&2yYftZF4C}SegIwpPmo?+zC@ytcoKwlW>%|?VT#pZo#hoR&COPMF z4|R<3-1$9}b-V}%{o@4dbsuUwPL|bn9Dz1C4kzGWu+DQlk?S7#03?5$`5^Bzeiynx zyuJX(K(7DE+&jcJI07dj=|1W8c&J~){o8lEAgapx#}d|S3-7SNr=e`2=Tf4(t_}2< zc$RTC7In-?Yl@#P|e;+*Fo>Pd|q@M;JKg3 zyAF(I?$dp^kGcDzZOnhCd=`7>OYj|}RyhZWGCzmC=CY@A+&4BGZ{n`MWIK=Sxyv|9 zosn7OW<_6xrLX`NL2X86lM`k|A24fYM`xPx?C2hRTF=(4_ziOzb80}`)2_+~$f zCxRYzPrGK1{Fuo)AL^KyhHPHLxmnSP_{zV}LTg9e)vgB2-Q0U;`%2J;yNLNB-ZD_m zyiazoD{;y1%)l9N?atesIJl#|0dxv880Uj?mo27u+Az?*4c_-ZslN&b)7w{o&Po;e zdPIyaT9t>m6c?!_hbtIu)$;y_j0ZWvA+2UV~Iv_}JR z28_eeaI?PB^Y_K7Us0cRam(p36}M3Tt%i}*ZgY|sUthHPU0t_P+iwluC2EgL%$($s z-;H(fMLB=YboB4w##5G?PJMgyO{cWSXn+3Jz}ZU=d=cuW4paN})c)%fj*R}zsiU9_ zl9M&J1p44pu7B|Fe-8fr*TEhb?18}^_`mG|jz0fCg@w9psP67A9M+@M*eJ10si6{U z_zw*b&z1kO!1V6Ib0l8cT{v9g@a}WJCh;rNYc7>|&XAfSiC-Sl)+TZ2&<-0P?sv4W z?%x;n_VMDd=*?`e&K}k+L8(ICy1S4!?^S1Y7dEMCs<~(^73sEN1=UfB1;ccAFe>#W zC1bgr7?uC5!Z2c?j$SEon2t^-c5~bGLLzqBh&@BJt{F>|`-r^~t2KYcm_GzvgD;6q jN}VOK&1^3ZknPQlVmrY`)+ literal 0 HcmV?d00001 diff --git a/web/ui/build/index.html b/web/ui/build/index.html new file mode 100644 index 000000000000..06f88a55db36 --- /dev/null +++ b/web/ui/build/index.html @@ -0,0 +1 @@ +Grafana Agent
\ No newline at end of file diff --git a/web/ui/build/manifest.json b/web/ui/build/manifest.json new file mode 100644 index 000000000000..deb995a2d109 --- /dev/null +++ b/web/ui/build/manifest.json @@ -0,0 +1,15 @@ +{ + "short_name": "Grafana Agent", + "name": "Grafana Agent", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/web/ui/build/robots.txt b/web/ui/build/robots.txt new file mode 100644 index 000000000000..e9e57dc4d41b --- /dev/null +++ b/web/ui/build/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/web/ui/build/static/css/main.d3ff49f0.css b/web/ui/build/static/css/main.d3ff49f0.css new file mode 100644 index 000000000000..88c5c8534f23 --- /dev/null +++ b/web/ui/build/static/css/main.d3ff49f0.css @@ -0,0 +1,3 @@ +.Navbar_navbar__-GvMT{background-color:#fff;border-bottom:1px solid #e4e5e6;display:flex;height:30px;padding:10px 16px;position:relative}.Navbar_navbar__-GvMT header,.Navbar_navbar__-GvMT header img{display:block;height:26px;margin-top:1px}.Navbar_navbar__-GvMT header img:hover{cursor:pointer}.Navbar_navbar__-GvMT ul{display:flex;flex-direction:row;list-style-type:none;margin:0;padding-left:1.5em}.Navbar_navbar__-GvMT ul li{display:list-item;margin-right:1em}.Navbar_navbar__-GvMT a,.Navbar_navbar__-GvMT ul li{color:#25292e;font-family:Roboto,sans-serif;line-height:225%;text-decoration:none}.Table_table__eD24h{border-collapse:collapse;width:100%}.Table_table__eD24h td,.Table_table__eD24h th{border:none;padding:0 8px}.Table_table__eD24h tr:nth-child(odd){background-color:#f4f5f5}.Table_table__eD24h tr:nth-child(2n){background-color:#fff}.Table_table__eD24h tr:hover{background-color:#ddd}.Table_table__eD24h th{background-color:#f4f5f5;color:#24292ebf;padding:8px;text-align:left}.Table_table__eD24h td:first-child{width:25%}.PeerList_list__qS4-l{border:1px solid #e4e5e6;border-radius:3px;box-sizing:border-box;color:#24292ebf}.PeerList_list__qS4-l .PeerList_viewButton__hSIX9{background:none;background-color:#3885dc;border:1px solid #3885dc;border-radius:3px;color:#fff;font-size:.8em;line-height:24px;margin-left:auto;padding:0 15px;text-decoration:none}.PeerList_idColumn__lw0IS{align-items:center;display:flex;flex-wrap:wrap}.PeerList_idName__89ysn{word-wrap:break-word;display:inline-block;width:80%}div.Page_page__67sBm{display:flex;flex-direction:column;height:100%;margin-left:auto;margin-right:auto;max-width:1440px}div.Page_page__67sBm main{background-color:#fff;border:1px solid #e4e5e6;border-radius:3px;box-sizing:border-box;flex-grow:1;margin:0 16px 16px;overflow:auto;padding:8px}.Page_header__n4dYu{align-items:center;display:flex;font-family:Roboto,sans-serif;height:50px;padding:24px}.Page_header__n4dYu .Page_icon__2jrfd{margin-right:10px;width:50px}.Page_header__n4dYu .Page_icon__2jrfd svg{color:#24292ebf;height:35px;width:100%}.Page_header__n4dYu h1,.Page_header__n4dYu h2{margin:0;padding:0}.Page_header__n4dYu h1{color:#24292e;font-size:24px;font-weight:400;margin-bottom:4px}.Page_header__n4dYu h2{color:#24292ebf;font-size:14px;font-weight:400}.Table_table__2oeKX{border-collapse:collapse;table-layout:fixed;width:100%}.Table_table__2oeKX td,.Table_table__2oeKX th{border:none;padding:0 8px}.Table_table__2oeKX tr:nth-child(odd){background-color:#f4f5f5}.Table_table__2oeKX tr:nth-child(2n){background-color:#fff}.Table_table__2oeKX tr:hover{background-color:#ddd}.Table_table__2oeKX th{background-color:#f4f5f5;color:#24292ebf;padding:8px;text-align:left}.Table_table__2oeKX td:first-child{width:2%}.Table_table__2oeKX tr th[data-sort-order=desc]{box-shadow:none!important;cursor:pointer;&:before{content:"â–¼";float:right}}.Table_table__2oeKX tr th[data-sort-order=asc]{box-shadow:none!important;cursor:pointer;&:before{content:"â–²";float:right}}.ComponentView_page__gf0nL{display:flex;font-family:Roboto,sans-serif;height:100%}.ComponentView_page__gf0nL nav{border-radius:3px;font-size:.9em;margin:15px;min-width:250px;overflow-y:auto;width:250px}.ComponentView_page__gf0nL nav h1{color:#545556;font-size:.8em;font-weight:700;margin:0}.ComponentView_page__gf0nL nav ul{list-style-type:none;padding-left:16px}.ComponentView_page__gf0nL nav hr{border:none;border-top:1px solid #545556}.ComponentView_page__gf0nL nav a,.ComponentView_page__gf0nL nav li{color:#545556;margin:20px 0;text-decoration:none}.ComponentView_page__gf0nL nav a:focus,.ComponentView_page__gf0nL nav a:hover{text-decoration:underline}.ComponentView_page__gf0nL .ComponentView_content__t7uJn{margin-left:auto;margin-right:auto;max-width:1440px;overflow-y:auto;padding:20px}.ComponentView_content__t7uJn h1 .ComponentView_icon__XK\+wx{margin-right:5px}.ComponentView_content__t7uJn h1 span.ComponentView_healthLabel__5bkMr{position:relative;top:-3px}.ComponentView_content__t7uJn h1 span.ComponentView_healthLabel__5bkMr>*{transform:scale(.75)}.ComponentView_content__t7uJn h1 .ComponentView_icon__XK\+wx svg{color:#24292ebf;position:relative;top:2px;width:21px}.ComponentView_content__t7uJn h1,h2,h3,h4,h5,h6{color:#24292e;font-size:1.4em;font-weight:400;margin-bottom:8px}.ComponentView_content__t7uJn h2,h3,h4,h5,h6{font-size:1.2em}.ComponentView_content__t7uJn .ComponentView_docsLink__W1YK5{background-color:#3885dc;border:1px solid #3885dc;border-radius:3px;color:#fff;display:block;font-size:10px;height:-moz-fit-content;height:fit-content;padding:5px;width:-moz-fit-content;width:fit-content}.ComponentView_docsLink__W1YK5 a{color:#fff;text-decoration:none}.ComponentView_content__t7uJn blockquote{border:1px solid #e4e5e6;border-radius:3px;color:#555;margin:20px 0;padding:20px}.ComponentView_content__t7uJn blockquote h1{color:#555;font-size:12px;font-weight:700;margin:0}.ComponentView_content__t7uJn blockquote p{font-family:Fira Code,monospace;margin-bottom:0}.ComponentView_content__t7uJn div.ComponentView_sectionContent__fuwHV{background-color:#fff;border:1px solid #e4e5e6;border-radius:3px;padding:16px}.ComponentView_content__t7uJn section.ComponentView_nested__-EvB0{margin-left:32px}em.ComponentView_informative__CNCGB{color:#555;font-size:14px}.ComponentView_list__QIdqN{border:1px solid #e4e5e6;border-radius:3px;box-sizing:border-box;color:#24292ebf}td.ComponentView_nameColumn__DGBw9{color:#000;font-family:Fira Code,monospace;font-size:14px;padding:6px;vertical-align:top}.ComponentView_pre__S2vse{font-size:14px;margin:0}span.HealthLabel_health__Eu\+ej{background-color:#595c60;border:1px solid #595c60;border-radius:3px;color:#fff;display:inline-block;font-size:12px;font-weight:600;line-height:1.2em;min-width:64px;padding:4px 8px;text-align:center;text-transform:capitalize}span.HealthLabel_health__Eu\+ej.HealthLabel_state-ok__N9y\+C{background-color:#3b8160;border-color:#3b8160;color:#fff}span.HealthLabel_health__Eu\+ej.HealthLabel_state-error__1XT86{background-color:#d2476d;border-color:#d2476d;color:#fff}span.HealthLabel_health__Eu\+ej.HealthLabel_state-warn__FRpNr{background-color:#f5d65b;border-color:#f5d65b;color:#000}.ComponentList_list__edZFH{border:1px solid #e4e5e6;border-radius:3px;box-sizing:border-box;color:#24292ebf}.ComponentList_list__edZFH .ComponentList_viewButton__RgzV6{background:none;background-color:#3885dc;border:1px solid #3885dc;border-radius:3px;color:#fff;font-size:.8em;line-height:24px;margin-left:auto;padding:0 15px;text-decoration:none}.ComponentList_idColumn__Sh4hu{align-items:center;display:flex;flex-wrap:wrap}.ComponentList_idName__kQnvD{word-wrap:break-word;display:inline-block;width:80%}.App_app__zr1wm{display:flex;flex-direction:column;height:100%}.App_app__zr1wm main{flex-grow:1;overflow-y:hidden} + +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:initial;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:initial}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:initial}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:100;src:url(../../static/media/roboto-v30-latin-100.30fb0679553d179c3343.woff2) format("woff2")x}@font-face{font-display:swap;font-family:Roboto;font-style:italic;font-weight:100;src:url(../../static/media/roboto-v30-latin-100italic.d3935eb61aa8422388e2.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:300;src:url(../../static/media/roboto-v30-latin-300.c48fb6765a9fcb00b330.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:italic;font-weight:300;src:url(../../static/media/roboto-v30-latin-300italic.1128daa312ec555266d5.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:400;src:url(../../static/media/roboto-v30-latin-regular.b009a76ad6afe4ebd301.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:italic;font-weight:400;src:url(../../static/media/roboto-v30-latin-italic.e10742dbb1d4a0864ba8.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:500;src:url(../../static/media/roboto-v30-latin-500.f25d774ecfe0996f8eb5.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:italic;font-weight:500;src:url(../../static/media/roboto-v30-latin-500italic.3a43b67e5bbdfb3ab0a6.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:700;src:url(../../static/media/roboto-v30-latin-700.227c93190fe7f82de3f8.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:italic;font-weight:700;src:url(../../static/media/roboto-v30-latin-700italic.d92a5d1451f249359639.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:normal;font-weight:900;src:url(../../static/media/roboto-v30-latin-900.2e8becfcae330421664b.woff2) format("woff2")}@font-face{font-display:swap;font-family:Roboto;font-style:italic;font-weight:900;src:url(../../static/media/roboto-v30-latin-900italic.5b387ea565e67898ca3a.woff2) format("woff2")}@font-face{font-display:swap;font-family:Fira Code;font-style:normal;font-weight:400;src:url(../../static/media/fira-code-v21-latin-regular.e662d57ce51fba1f46e3.woff2) format("woff2")}@font-face{font-display:swap;font-family:Fira Code;font-style:normal;font-weight:500;src:url(../../static/media/fira-code-v21-latin-500.3452777c99809dd85b2a.woff2) format("woff2")}#root,body,html{height:100%}body{background-color:#f4f4f5;font-family:Roboto,sans-serif}.app-navbar{background-color:#fff;border-bottom:1px solid #e4e5e5}.app-navbar .navbar-brand img:hover{cursor:pointer}.app-navbar div[role=menu]{border:1px solid #e4e5e5}.app-navbar a{color:#25292e}code,pre{font-family:Fira Code,monospace} \ No newline at end of file diff --git a/web/ui/build/static/js/main.180d839c.js b/web/ui/build/static/js/main.180d839c.js new file mode 100644 index 000000000000..7c7195dad53d --- /dev/null +++ b/web/ui/build/static/js/main.180d839c.js @@ -0,0 +1,2 @@ +/*! For license information please see main.180d839c.js.LICENSE.txt */ +(()=>{var e={2047:(e,t)=>{"use strict";t.Q=function(e){var t,a=[],i=String(e||r),o=i.indexOf(n),s=0,l=!1;for(;!l;)-1===o&&(o=i.length,l=!0),!(t=i.slice(s,o).trim())&&l||a.push(t),s=o+1,o=i.indexOf(n,s);return a};var n=",",a=" ",r=""},3656:e=>{"use strict";e.exports=function(e,n){var a,r,i,o=e||"",s=n||"div",l={},u=0;for(;u{"use strict";var a=n(5971),r=n(695),i=n(3656),o=n(2954).Q,s=n(2047).Q;e.exports=function(e,t,n){var r=n?function(e){var t,n=e.length,a=-1,r={};for(;++a{"use strict";var a=n(3294),r=n(3389)(a,"div");r.displayName="html",e.exports=r},9762:(e,t,n)=>{"use strict";e.exports=n(9073)},7631:e=>{"use strict";e.exports=function(e){var t="string"===typeof e?e.charCodeAt(0):e;return t>=97&&t<=122||t>=65&&t<=90}},9319:(e,t,n)=>{"use strict";var a=n(7631),r=n(4597);e.exports=function(e){return a(e)||r(e)}},4597:e=>{"use strict";e.exports=function(e){var t="string"===typeof e?e.charCodeAt(0):e;return t>=48&&t<=57}},6422:e=>{"use strict";e.exports=function(e){var t="string"===typeof e?e.charCodeAt(0):e;return t>=97&&t<=102||t>=65&&t<=70||t>=48&&t<=57}},9718:e=>{"use strict";var t;e.exports=function(e){var n,a="&"+e+";";if((t=t||document.createElement("i")).innerHTML=a,59===(n=t.textContent).charCodeAt(n.length-1)&&"semi"!==e)return!1;return n!==a&&n}},7898:(e,t,n)=>{"use strict";var a=n(7452),r=n(3580),i=n(4597),o=n(6422),s=n(9319),l=n(9718);e.exports=function(e,t){var n,i,o={};t||(t={});for(i in p)n=t[i],o[i]=null===n||void 0===n?p[i]:n;(o.position.indent||o.position.start)&&(o.indent=o.position.indent||[],o.position=o.position.start);return function(e,t){var n,i,o,p,$,z,G,j,H,V,W,q,Y,K,X,Z,Q,J,ee,te=t.additional,ne=t.nonTerminated,ae=t.text,re=t.reference,ie=t.warning,oe=t.textContext,se=t.referenceContext,le=t.warningContext,ue=t.position,ce=t.indent||[],de=e.length,pe=0,fe=-1,me=ue.column||1,ge=ue.line||1,he="",be=[];"string"===typeof te&&(te=te.charCodeAt(0));Z=ye(),j=ie?ve:d,pe--,de++;for(;++pe65535&&(V+=c((z-=65536)>>>10|55296),z=56320|1023&z),z=V+c(z))):K!==A&&j(L,J)),z?(Ee(),Z=ye(),pe=ee-1,me+=ee-Y+1,be.push(z),(Q=ye()).offset++,re&&re.call(se,z,{start:Z,end:Q},e.slice(Y-1,ee)),Z=Q):(p=e.slice(Y-1,ee),he+=p,me+=p.length,pe=ee-1)}else 10===$&&(ge++,fe++,me=0),$===$?(he+=c($),me++):Ee();return be.join("");function ye(){return{line:ge,column:me,offset:pe+(ue.offset||0)}}function ve(e,t){var n=ye();n.column+=t,n.offset+=t,ie.call(le,F[e],n,e)}function Ee(){he&&(be.push(he),ae&&ae.call(oe,he,{start:Z,end:ye()}),he="")}}(e,o)};var u={}.hasOwnProperty,c=String.fromCharCode,d=Function.prototype,p={warning:null,reference:null,text:null,warningContext:null,referenceContext:null,textContext:null,position:{},additional:null,attribute:!1,nonTerminated:!0},f=9,m=10,g=12,h=32,b=38,y=59,v=60,E=61,S=35,w=88,_=120,T=65533,A="named",k="hexadecimal",I="decimal",x={};x[k]=16,x[I]=10;var N={};N[A]=s,N[I]=i,N[k]=o;var R=1,C=2,O=3,L=4,D=5,P=6,M=7,F={};function U(e){return e>=55296&&e<=57343||e>1114111}function B(e){return e>=1&&e<=8||11===e||e>=13&&e<=31||e>=127&&e<=159||e>=64976&&e<=65007||65535===(65535&e)||65534===(65535&e)}F[R]="Named character references must be terminated by a semicolon",F[C]="Numeric character references must be terminated by a semicolon",F[O]="Named character references cannot be empty",F[L]="Numeric character references cannot be empty",F[D]="Named character references must be known",F[P]="Numeric character references cannot be disallowed",F[M]="Numeric character references cannot be outside the permissible Unicode range"},1729:(e,t,n)=>{"use strict";var a=n(9165);function r(){}function i(){}i.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,i,o){if(o!==a){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:r};return n.PropTypes=n,n}},5192:(e,t,n)=>{e.exports=n(1729)()},9165:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},5971:(e,t,n)=>{"use strict";var a=n(695),r=n(9079),i=n(8018),o="data";e.exports=function(e,t){var n=a(t),p=t,f=i;if(n in e.normal)return e.property[e.normal[n]];n.length>4&&n.slice(0,4)===o&&s.test(t)&&("-"===t.charAt(4)?p=function(e){var t=e.slice(5).replace(l,d);return o+t.charAt(0).toUpperCase()+t.slice(1)}(t):t=function(e){var t=e.slice(4);if(l.test(t))return e;t=t.replace(u,c),"-"!==t.charAt(0)&&(t="-"+t);return o+t}(t),f=r);return new f(p,t)};var s=/^data[-\w.:]+$/i,l=/-[a-z]/g,u=/[A-Z]/g;function c(e){return"-"+e.toLowerCase()}function d(e){return e.charAt(1).toUpperCase()}},3294:(e,t,n)=>{"use strict";var a=n(5237),r=n(7848),i=n(9698),o=n(4720),s=n(2410),l=n(9403);e.exports=a([i,r,o,s,l])},2410:(e,t,n)=>{"use strict";var a=n(1210),r=n(3096),i=a.booleanish,o=a.number,s=a.spaceSeparated;e.exports=r({transform:function(e,t){return"role"===t?t:"aria-"+t.slice(4).toLowerCase()},properties:{ariaActiveDescendant:null,ariaAtomic:i,ariaAutoComplete:null,ariaBusy:i,ariaChecked:i,ariaColCount:o,ariaColIndex:o,ariaColSpan:o,ariaControls:s,ariaCurrent:null,ariaDescribedBy:s,ariaDetails:null,ariaDisabled:i,ariaDropEffect:s,ariaErrorMessage:null,ariaExpanded:i,ariaFlowTo:s,ariaGrabbed:i,ariaHasPopup:null,ariaHidden:i,ariaInvalid:null,ariaKeyShortcuts:null,ariaLabel:null,ariaLabelledBy:s,ariaLevel:o,ariaLive:null,ariaModal:i,ariaMultiLine:i,ariaMultiSelectable:i,ariaOrientation:null,ariaOwns:s,ariaPlaceholder:null,ariaPosInSet:o,ariaPressed:i,ariaReadOnly:i,ariaRelevant:null,ariaRequired:i,ariaRoleDescription:s,ariaRowCount:o,ariaRowIndex:o,ariaRowSpan:o,ariaSelected:i,ariaSetSize:o,ariaSort:null,ariaValueMax:o,ariaValueMin:o,ariaValueNow:o,ariaValueText:null,role:null}})},9403:(e,t,n)=>{"use strict";var a=n(1210),r=n(3096),i=n(3809),o=a.boolean,s=a.overloadedBoolean,l=a.booleanish,u=a.number,c=a.spaceSeparated,d=a.commaSeparated;e.exports=r({space:"html",attributes:{acceptcharset:"accept-charset",classname:"class",htmlfor:"for",httpequiv:"http-equiv"},transform:i,mustUseProperty:["checked","multiple","muted","selected"],properties:{abbr:null,accept:d,acceptCharset:c,accessKey:c,action:null,allow:null,allowFullScreen:o,allowPaymentRequest:o,allowUserMedia:o,alt:null,as:null,async:o,autoCapitalize:null,autoComplete:c,autoFocus:o,autoPlay:o,capture:o,charSet:null,checked:o,cite:null,className:c,cols:u,colSpan:null,content:null,contentEditable:l,controls:o,controlsList:c,coords:u|d,crossOrigin:null,data:null,dateTime:null,decoding:null,default:o,defer:o,dir:null,dirName:null,disabled:o,download:s,draggable:l,encType:null,enterKeyHint:null,form:null,formAction:null,formEncType:null,formMethod:null,formNoValidate:o,formTarget:null,headers:c,height:u,hidden:o,high:u,href:null,hrefLang:null,htmlFor:c,httpEquiv:c,id:null,imageSizes:null,imageSrcSet:d,inputMode:null,integrity:null,is:null,isMap:o,itemId:null,itemProp:c,itemRef:c,itemScope:o,itemType:c,kind:null,label:null,lang:null,language:null,list:null,loading:null,loop:o,low:u,manifest:null,max:null,maxLength:u,media:null,method:null,min:null,minLength:u,multiple:o,muted:o,name:null,nonce:null,noModule:o,noValidate:o,onAbort:null,onAfterPrint:null,onAuxClick:null,onBeforePrint:null,onBeforeUnload:null,onBlur:null,onCancel:null,onCanPlay:null,onCanPlayThrough:null,onChange:null,onClick:null,onClose:null,onContextMenu:null,onCopy:null,onCueChange:null,onCut:null,onDblClick:null,onDrag:null,onDragEnd:null,onDragEnter:null,onDragExit:null,onDragLeave:null,onDragOver:null,onDragStart:null,onDrop:null,onDurationChange:null,onEmptied:null,onEnded:null,onError:null,onFocus:null,onFormData:null,onHashChange:null,onInput:null,onInvalid:null,onKeyDown:null,onKeyPress:null,onKeyUp:null,onLanguageChange:null,onLoad:null,onLoadedData:null,onLoadedMetadata:null,onLoadEnd:null,onLoadStart:null,onMessage:null,onMessageError:null,onMouseDown:null,onMouseEnter:null,onMouseLeave:null,onMouseMove:null,onMouseOut:null,onMouseOver:null,onMouseUp:null,onOffline:null,onOnline:null,onPageHide:null,onPageShow:null,onPaste:null,onPause:null,onPlay:null,onPlaying:null,onPopState:null,onProgress:null,onRateChange:null,onRejectionHandled:null,onReset:null,onResize:null,onScroll:null,onSecurityPolicyViolation:null,onSeeked:null,onSeeking:null,onSelect:null,onSlotChange:null,onStalled:null,onStorage:null,onSubmit:null,onSuspend:null,onTimeUpdate:null,onToggle:null,onUnhandledRejection:null,onUnload:null,onVolumeChange:null,onWaiting:null,onWheel:null,open:o,optimum:u,pattern:null,ping:c,placeholder:null,playsInline:o,poster:null,preload:null,readOnly:o,referrerPolicy:null,rel:c,required:o,reversed:o,rows:u,rowSpan:u,sandbox:c,scope:null,scoped:o,seamless:o,selected:o,shape:null,size:u,sizes:null,slot:null,span:u,spellCheck:l,src:null,srcDoc:null,srcLang:null,srcSet:d,start:u,step:null,style:null,tabIndex:u,target:null,title:null,translate:null,type:null,typeMustMatch:o,useMap:null,value:l,width:u,wrap:null,align:null,aLink:null,archive:c,axis:null,background:null,bgColor:null,border:u,borderColor:null,bottomMargin:u,cellPadding:null,cellSpacing:null,char:null,charOff:null,classId:null,clear:null,code:null,codeBase:null,codeType:null,color:null,compact:o,declare:o,event:null,face:null,frame:null,frameBorder:null,hSpace:u,leftMargin:u,link:null,longDesc:null,lowSrc:null,marginHeight:u,marginWidth:u,noResize:o,noHref:o,noShade:o,noWrap:o,object:null,profile:null,prompt:null,rev:null,rightMargin:u,rules:null,scheme:null,scrolling:l,standby:null,summary:null,text:null,topMargin:u,valueType:null,version:null,vAlign:null,vLink:null,vSpace:u,allowTransparency:null,autoCorrect:null,autoSave:null,disablePictureInPicture:o,disableRemotePlayback:o,prefix:null,property:null,results:u,security:null,unselectable:null}})},3809:(e,t,n)=>{"use strict";var a=n(9717);e.exports=function(e,t){return a(e,t.toLowerCase())}},9717:e=>{"use strict";e.exports=function(e,t){return t in e?e[t]:t}},3096:(e,t,n)=>{"use strict";var a=n(695),r=n(1385),i=n(9079);e.exports=function(e){var t,n,o=e.space,s=e.mustUseProperty||[],l=e.attributes||{},u=e.properties,c=e.transform,d={},p={};for(t in u)n=new i(t,c(l,t),u[t],o),-1!==s.indexOf(t)&&(n.mustUseProperty=!0),d[t]=n,p[a(t)]=t,p[a(n.attribute)]=t;return new r(d,p,o)}},9079:(e,t,n)=>{"use strict";var a=n(8018),r=n(1210);e.exports=s,s.prototype=new a,s.prototype.defined=!0;var i=["boolean","booleanish","overloadedBoolean","number","commaSeparated","spaceSeparated","commaOrSpaceSeparated"],o=i.length;function s(e,t,n,s){var u,c=-1;for(l(this,"space",s),a.call(this,e,t);++c{"use strict";e.exports=n;var t=n.prototype;function n(e,t){this.property=e,this.attribute=t}t.space=null,t.attribute=null,t.property=null,t.boolean=!1,t.booleanish=!1,t.overloadedBoolean=!1,t.number=!1,t.commaSeparated=!1,t.spaceSeparated=!1,t.commaOrSpaceSeparated=!1,t.mustUseProperty=!1,t.defined=!1},5237:(e,t,n)=>{"use strict";var a=n(5307),r=n(1385);e.exports=function(e){var t,n,i=e.length,o=[],s=[],l=-1;for(;++l{"use strict";e.exports=n;var t=n.prototype;function n(e,t,n){this.property=e,this.normal=t,n&&(this.space=n)}t.space=null,t.normal={},t.property={}},1210:(e,t)=>{"use strict";var n=0;function a(){return Math.pow(2,++n)}t.boolean=a(),t.booleanish=a(),t.overloadedBoolean=a(),t.number=a(),t.spaceSeparated=a(),t.commaSeparated=a(),t.commaOrSpaceSeparated=a()},7848:(e,t,n)=>{"use strict";var a=n(3096);e.exports=a({space:"xlink",transform:function(e,t){return"xlink:"+t.slice(5).toLowerCase()},properties:{xLinkActuate:null,xLinkArcRole:null,xLinkHref:null,xLinkRole:null,xLinkShow:null,xLinkTitle:null,xLinkType:null}})},9698:(e,t,n)=>{"use strict";var a=n(3096);e.exports=a({space:"xml",transform:function(e,t){return"xml:"+t.slice(3).toLowerCase()},properties:{xmlLang:null,xmlBase:null,xmlSpace:null}})},4720:(e,t,n)=>{"use strict";var a=n(3096),r=n(3809);e.exports=a({space:"xmlns",attributes:{xmlnsxlink:"xmlns:xlink"},transform:r,properties:{xmlns:null,xmlnsXLink:null}})},695:e=>{"use strict";e.exports=function(e){return e.toLowerCase()}},534:(e,t,n)=>{"use strict";var a=n(7313),r=n(2224);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n