diff --git a/.drone.yml b/.drone.yml index 44416f8336a..c8f77eeae82 100644 --- a/.drone.yml +++ b/.drone.yml @@ -14,21 +14,18 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl - chmod +x bin/grabpl - ./bin/grabpl verify-drone - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -36,14 +33,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition oss @@ -53,7 +50,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition oss @@ -62,7 +59,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -71,35 +68,35 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --variants linux-x64,linux-x64-musl,osx64,win64,armv6 --no-pull-enterprise depends_on: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --no-install-deps --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition oss --no-install-deps depends_on: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version --build-id ${DRONE_BUILD_NUMBER} depends_on: @@ -110,14 +107,14 @@ steps: - shellcheck - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - . scripts/build/gpg-test-vars.sh && ./bin/grabpl package --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise --variants linux-x64,linux-x64-musl,osx64,win64,armv6 depends_on: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -137,7 +134,7 @@ steps: - end-to-end-tests-server - name: build-storybook - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn storybook:build - ./bin/grabpl verify-storybook @@ -161,7 +158,7 @@ steps: - end-to-end-tests-server - name: build-frontend-docs - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./scripts/ci-reference-docs-lint.sh ci depends_on: @@ -177,7 +174,7 @@ steps: - build-frontend-docs - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -194,11 +191,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -211,11 +208,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -265,15 +262,12 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl - chmod +x bin/grabpl - ./bin/grabpl verify-drone - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 @@ -291,7 +285,7 @@ steps: from_secret: drone_token - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -299,14 +293,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition oss @@ -316,7 +310,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition oss @@ -325,7 +319,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -334,21 +328,21 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --no-install-deps --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition oss --no-install-deps --sign --signing-admin environment: @@ -358,14 +352,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version --build-id ${DRONE_BUILD_NUMBER} depends_on: @@ -376,7 +370,7 @@ steps: - shellcheck - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise --sign environment: @@ -394,7 +388,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -414,7 +408,7 @@ steps: - end-to-end-tests-server - name: build-storybook - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn storybook:build - ./bin/grabpl verify-storybook @@ -451,7 +445,7 @@ steps: - end-to-end-tests-server - name: publish-frontend-metrics - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./scripts/ci-frontend-metrics.sh | ./bin/grabpl publish-metrics $${GRAFANA_MISC_STATS_API_KEY} environment: @@ -462,14 +456,14 @@ steps: - test-a11y-frontend - name: build-frontend-docs - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./scripts/ci-reference-docs-lint.sh ci depends_on: - build-frontend - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -500,11 +494,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -517,11 +511,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -533,7 +527,7 @@ steps: - test-frontend - name: release-canary-npm-packages - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./scripts/circle-release-canary-packages.sh environment: @@ -655,7 +649,7 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl @@ -743,22 +737,19 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl - chmod +x bin/grabpl - ./bin/grabpl verify-drone - ./bin/grabpl verify-version ${DRONE_TAG} - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -766,14 +757,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition oss @@ -783,7 +774,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition oss --tries 5 @@ -792,7 +783,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -801,7 +792,7 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition oss --github-token $${GITHUB_TOKEN} --no-pull-enterprise ${DRONE_TAG} environment: @@ -811,14 +802,14 @@ steps: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --github-token $${GITHUB_TOKEN} --no-install-deps --edition oss --no-pull-enterprise ${DRONE_TAG} depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition oss --no-install-deps --sign --signing-admin environment: @@ -828,14 +819,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version ${DRONE_TAG} depends_on: @@ -846,7 +837,7 @@ steps: - shellcheck - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition oss --github-token $${GITHUB_TOKEN} --no-pull-enterprise --sign ${DRONE_TAG} environment: @@ -864,7 +855,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -884,7 +875,7 @@ steps: - end-to-end-tests-server - name: build-storybook - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn storybook:build - ./bin/grabpl verify-storybook @@ -894,7 +885,7 @@ steps: - package - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -925,11 +916,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -942,11 +933,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -994,7 +985,7 @@ steps: - end-to-end-tests - name: release-npm-packages - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./scripts/build/release-packages.sh ${DRONE_TAG} environment: @@ -1095,7 +1086,7 @@ steps: - echo $DRONE_RUNNER_NAME - name: clone - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl @@ -1108,7 +1099,7 @@ steps: from_secret: github_token - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mv bin/grabpl /tmp/ - rmdir bin @@ -1119,9 +1110,6 @@ steps: - mv /tmp/grabpl bin/ - ./bin/grabpl verify-drone - ./bin/grabpl verify-version ${DRONE_TAG} - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 @@ -1129,7 +1117,7 @@ steps: - clone - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -1137,14 +1125,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition enterprise @@ -1154,7 +1142,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition enterprise --tries 5 @@ -1163,7 +1151,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -1172,7 +1160,7 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition enterprise --github-token $${GITHUB_TOKEN} --no-pull-enterprise ${DRONE_TAG} environment: @@ -1182,14 +1170,14 @@ steps: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --github-token $${GITHUB_TOKEN} --no-install-deps --edition enterprise --no-pull-enterprise ${DRONE_TAG} depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition enterprise --no-install-deps --sign --signing-admin environment: @@ -1199,14 +1187,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: lint-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition enterprise2 @@ -1216,7 +1204,7 @@ steps: - initialize - name: test-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition enterprise2 --tries 5 @@ -1225,7 +1213,7 @@ steps: - lint-backend - name: build-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition enterprise2 --github-token $${GITHUB_TOKEN} --no-pull-enterprise ${DRONE_TAG} environment: @@ -1235,7 +1223,7 @@ steps: - test-backend-enterprise2 - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version ${DRONE_TAG} depends_on: @@ -1248,7 +1236,7 @@ steps: - test-backend-enterprise2 - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition enterprise --github-token $${GITHUB_TOKEN} --no-pull-enterprise --sign ${DRONE_TAG} environment: @@ -1266,7 +1254,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -1288,7 +1276,7 @@ steps: - end-to-end-tests-server - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -1319,11 +1307,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -1336,11 +1324,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -1352,9 +1340,9 @@ steps: - test-frontend - name: redis-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - - ./bin/dockerize -wait tcp://redis:6379/0 -timeout 120s + - dockerize -wait tcp://redis:6379/0 -timeout 120s - ./bin/grabpl integration-tests environment: REDIS_URL: redis://redis:6379/0 @@ -1363,9 +1351,9 @@ steps: - test-frontend - name: memcached-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - - ./bin/dockerize -wait tcp://memcached:11211 -timeout 120s + - dockerize -wait tcp://memcached:11211 -timeout 120s - ./bin/grabpl integration-tests environment: MEMCACHED_HOSTS: memcached:11211 @@ -1398,7 +1386,7 @@ steps: - memcached-integration-tests - name: package-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition enterprise2 --github-token $${GITHUB_TOKEN} --no-pull-enterprise --sign ${DRONE_TAG} environment: @@ -1416,7 +1404,7 @@ steps: - gen-version - name: end-to-end-tests-server-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -1581,7 +1569,7 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl @@ -1689,22 +1677,19 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl - chmod +x bin/grabpl - ./bin/grabpl verify-drone - ./bin/grabpl verify-version v7.3.0-test - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -1712,14 +1697,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition oss @@ -1729,7 +1714,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition oss --tries 5 @@ -1738,7 +1723,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -1747,7 +1732,7 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition oss --github-token $${GITHUB_TOKEN} --no-pull-enterprise v7.3.0-test environment: @@ -1757,14 +1742,14 @@ steps: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --github-token $${GITHUB_TOKEN} --no-install-deps --edition oss --no-pull-enterprise v7.3.0-test depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition oss --no-install-deps --sign --signing-admin environment: @@ -1774,14 +1759,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version v7.3.0-test depends_on: @@ -1792,7 +1777,7 @@ steps: - shellcheck - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition oss --github-token $${GITHUB_TOKEN} --no-pull-enterprise --sign v7.3.0-test environment: @@ -1810,7 +1795,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -1830,7 +1815,7 @@ steps: - end-to-end-tests-server - name: build-storybook - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn storybook:build - ./bin/grabpl verify-storybook @@ -1840,7 +1825,7 @@ steps: - package - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -1865,11 +1850,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -1882,11 +1867,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -1931,7 +1916,7 @@ steps: - end-to-end-tests - name: release-npm-packages - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 environment: GITHUB_PACKAGE_TOKEN: from_secret: github_package_token @@ -2030,7 +2015,7 @@ steps: - echo $DRONE_RUNNER_NAME - name: clone - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl @@ -2043,7 +2028,7 @@ steps: from_secret: github_token - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mv bin/grabpl /tmp/ - rmdir bin @@ -2054,9 +2039,6 @@ steps: - mv /tmp/grabpl bin/ - ./bin/grabpl verify-drone - ./bin/grabpl verify-version v7.3.0-test - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 @@ -2064,7 +2046,7 @@ steps: - clone - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -2072,14 +2054,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition enterprise @@ -2089,7 +2071,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition enterprise --tries 5 @@ -2098,7 +2080,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -2107,7 +2089,7 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition enterprise --github-token $${GITHUB_TOKEN} --no-pull-enterprise v7.3.0-test environment: @@ -2117,14 +2099,14 @@ steps: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --github-token $${GITHUB_TOKEN} --no-install-deps --edition enterprise --no-pull-enterprise v7.3.0-test depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition enterprise --no-install-deps --sign --signing-admin environment: @@ -2134,14 +2116,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: lint-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition enterprise2 @@ -2151,7 +2133,7 @@ steps: - initialize - name: test-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition enterprise2 --tries 5 @@ -2160,7 +2142,7 @@ steps: - lint-backend - name: build-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition enterprise2 --github-token $${GITHUB_TOKEN} --no-pull-enterprise v7.3.0-test environment: @@ -2170,7 +2152,7 @@ steps: - test-backend-enterprise2 - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version v7.3.0-test depends_on: @@ -2183,7 +2165,7 @@ steps: - test-backend-enterprise2 - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition enterprise --github-token $${GITHUB_TOKEN} --no-pull-enterprise --sign v7.3.0-test environment: @@ -2201,7 +2183,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -2223,7 +2205,7 @@ steps: - end-to-end-tests-server - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -2248,11 +2230,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -2265,11 +2247,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -2281,9 +2263,9 @@ steps: - test-frontend - name: redis-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - - ./bin/dockerize -wait tcp://redis:6379/0 -timeout 120s + - dockerize -wait tcp://redis:6379/0 -timeout 120s - ./bin/grabpl integration-tests environment: REDIS_URL: redis://redis:6379/0 @@ -2292,9 +2274,9 @@ steps: - test-frontend - name: memcached-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - - ./bin/dockerize -wait tcp://memcached:11211 -timeout 120s + - dockerize -wait tcp://memcached:11211 -timeout 120s - ./bin/grabpl integration-tests environment: MEMCACHED_HOSTS: memcached:11211 @@ -2327,7 +2309,7 @@ steps: - memcached-integration-tests - name: package-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition enterprise2 --github-token $${GITHUB_TOKEN} --no-pull-enterprise --sign v7.3.0-test environment: @@ -2345,7 +2327,7 @@ steps: - gen-version - name: end-to-end-tests-server-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -2510,7 +2492,7 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl @@ -2618,21 +2600,18 @@ steps: - echo $DRONE_RUNNER_NAME - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl - chmod +x bin/grabpl - ./bin/grabpl verify-drone - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -2640,14 +2619,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition oss @@ -2657,7 +2636,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition oss @@ -2666,7 +2645,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -2675,21 +2654,21 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --no-install-deps --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition oss --no-install-deps --sign --signing-admin environment: @@ -2699,14 +2678,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version --build-id ${DRONE_BUILD_NUMBER} depends_on: @@ -2717,7 +2696,7 @@ steps: - shellcheck - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition oss --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise --sign environment: @@ -2735,7 +2714,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -2755,7 +2734,7 @@ steps: - end-to-end-tests-server - name: build-storybook - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn storybook:build - ./bin/grabpl verify-storybook @@ -2765,7 +2744,7 @@ steps: - package - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -2790,11 +2769,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -2807,11 +2786,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -2930,7 +2909,7 @@ steps: - echo $DRONE_RUNNER_NAME - name: clone - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mkdir -p bin - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v2.4.6/grabpl @@ -2943,7 +2922,7 @@ steps: from_secret: github_token - name: initialize - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - mv bin/grabpl /tmp/ - rmdir bin @@ -2953,9 +2932,6 @@ steps: - mkdir bin - mv /tmp/grabpl bin/ - ./bin/grabpl verify-drone - - curl -fLO https://github.com/jwilder/dockerize/releases/download/v$${DOCKERIZE_VERSION}/dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - tar -C bin -xzvf dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - - rm dockerize-linux-amd64-v$${DOCKERIZE_VERSION}.tar.gz - yarn install --frozen-lockfile --no-progress environment: DOCKERIZE_VERSION: 0.6.1 @@ -2963,7 +2939,7 @@ steps: - clone - name: codespell - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "echo -e \"unknwon\nreferer\nerrorstring\neror\niam\nwan\" > words_to_ignore.txt" - codespell -I words_to_ignore.txt docs/ @@ -2971,14 +2947,14 @@ steps: - initialize - name: shellcheck - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl shellcheck depends_on: - initialize - name: lint-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition enterprise @@ -2988,7 +2964,7 @@ steps: - initialize - name: test-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition enterprise @@ -2997,7 +2973,7 @@ steps: - lint-backend - name: test-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn run ci:test-frontend environment: @@ -3006,21 +2982,21 @@ steps: - lint-backend - name: build-backend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-backend - name: build-frontend - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-frontend --jobs 8 --no-install-deps --edition enterprise --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise depends_on: - test-frontend - name: build-plugins - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-plugins --jobs 8 --edition enterprise --no-install-deps --sign --signing-admin environment: @@ -3030,14 +3006,14 @@ steps: - lint-backend - name: validate-scuemata - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/linux-amd64/grafana-cli cue validate-schema --grafana-root . depends_on: - build-backend - name: lint-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - make gen-go - ./bin/grabpl lint-backend --edition enterprise2 @@ -3047,7 +3023,7 @@ steps: - initialize - name: test-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - "[ $(grep FocusConvey -R pkg | wc -l) -eq \"0\" ] || exit 1" - ./bin/grabpl test-backend --edition enterprise2 @@ -3056,14 +3032,14 @@ steps: - lint-backend - name: build-backend-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl build-backend --jobs 8 --edition enterprise2 --build-id ${DRONE_BUILD_NUMBER} --variants linux-x64 --no-pull-enterprise depends_on: - test-backend-enterprise2 - name: gen-version - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl gen-version --build-id ${DRONE_BUILD_NUMBER} depends_on: @@ -3076,7 +3052,7 @@ steps: - test-backend-enterprise2 - name: package - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition enterprise --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise --sign environment: @@ -3094,7 +3070,7 @@ steps: - gen-version - name: end-to-end-tests-server - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -3116,7 +3092,7 @@ steps: - end-to-end-tests-server - name: build-storybook - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - yarn storybook:build - ./bin/grabpl verify-storybook @@ -3126,7 +3102,7 @@ steps: - package - name: copy-packages-for-docker - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ls dist/*.tar.gz* - cp dist/*.tar.gz* packaging/docker/ @@ -3151,11 +3127,11 @@ steps: - copy-packages-for-docker - name: postgres-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq postgresql-client - - ./bin/dockerize -wait tcp://postgres:5432 -timeout 120s + - dockerize -wait tcp://postgres:5432 -timeout 120s - psql -p 5432 -h postgres -U grafanatest -d grafanatest -f devenv/docker/blocks/postgres_tests/setup.sql - go clean -testcache - ./bin/grabpl integration-tests --database postgres @@ -3168,11 +3144,11 @@ steps: - test-frontend - name: mysql-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - apt-get update - apt-get install -yq default-mysql-client - - ./bin/dockerize -wait tcp://mysql:3306 -timeout 120s + - dockerize -wait tcp://mysql:3306 -timeout 120s - cat devenv/docker/blocks/mysql_tests/setup.sql | mysql -h mysql -P 3306 -u root -prootpass - go clean -testcache - ./bin/grabpl integration-tests --database mysql @@ -3184,9 +3160,9 @@ steps: - test-frontend - name: redis-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - - ./bin/dockerize -wait tcp://redis:6379/0 -timeout 120s + - dockerize -wait tcp://redis:6379/0 -timeout 120s - ./bin/grabpl integration-tests environment: REDIS_URL: redis://redis:6379/0 @@ -3195,9 +3171,9 @@ steps: - test-frontend - name: memcached-integration-tests - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - - ./bin/dockerize -wait tcp://memcached:11211 -timeout 120s + - dockerize -wait tcp://memcached:11211 -timeout 120s - ./bin/grabpl integration-tests environment: MEMCACHED_HOSTS: memcached:11211 @@ -3230,7 +3206,7 @@ steps: - memcached-integration-tests - name: package-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 commands: - ./bin/grabpl package --jobs 8 --edition enterprise2 --build-id ${DRONE_BUILD_NUMBER} --no-pull-enterprise --variants linux-x64 --sign environment: @@ -3248,7 +3224,7 @@ steps: - gen-version - name: end-to-end-tests-server-enterprise2 - image: grafana/build-container:1.4.2 + image: grafana/build-container:1.4.3 detach: true commands: - ./e2e/start-server @@ -3492,6 +3468,6 @@ get: --- kind: signature -hmac: 9211e316cd24660667ba57b860129d2f06b0a4a669aa4d5c1f13156667ae027f +hmac: 9d5ee57b9eff4ba3df8f70c8f7625c2ff1e07c2ce438182a97f81e6e8dbbb1dc ... diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dd3a74d2b4c..b0de23f73e7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -40,14 +40,14 @@ go.sum @grafana/backend-platform /pkg/tsdb/zipkin @grafana/observability-squad /pkg/tsdb/tempo @grafana/observability-squad -# Unified Alerting -/pkg/services/ngalert @grafana/alerting-squad -/pkg/services/sqlstore/migrations/ualert @grafana/alerting-squad - # Database migrations /pkg/services/sqlstore/migrations @grafana/backend-platform @grafana/hosted-grafana-team *_mig.go @grafana/backend-platform @grafana/hosted-grafana-team +# Unified Alerting +/pkg/services/ngalert @grafana/alerting-squad +/pkg/services/sqlstore/migrations/ualert @grafana/alerting-squad + # Backend code docs /contribute/style-guides/backend.md @grafana/backend-platform /contribute/architecture/backend @grafana/backend-platform diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5db8a102626..289ad906fee 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,19 @@ updates: directory: "/" schedule: interval: "weekly" + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + ignore: + # ignore minor/patch updates for now + - dependency-name: "*" + update-types: ["version-update:semver-minor", "version-update:semver-patch"] + # things that will probably need some thinking + - dependency-name: "d3" + - dependency-name: "husky" + - dependency-name: "slate" + - dependency-name: "slate-plain-serializer" + reviewers: + - "grafana/frontend-ops" + versioning-strategy: "increase-if-necessary" diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index f84ef266956..3df75d3171b 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: # This is a basic workflow to help you get started with Actions - - uses: actions-ecosystem/action-regex-match@v2 + - uses: actions-ecosystem/action-regex-match@v2.0.1 id: regex-match with: text: ${{ github.event.inputs.version }} @@ -53,7 +53,7 @@ jobs: repository: "grafana/grafana-github-actions" path: ./actions ref: main - - uses: actions/setup-node@v2.1.5 + - uses: actions/setup-node@v2.4.0 with: node-version: '14' - name: Install Actions diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0eb6325b764..031dc2b969b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,7 +21,7 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} - name: generate-packages-docs - uses: actions/setup-node@v2.1.5 + uses: actions/setup-node@v2.4.0 id: generate-docs with: node-version: '14' diff --git a/.pa11yci-pr.conf.js b/.pa11yci-pr.conf.js index 9e5f55daaa2..55c9cc0d27a 100644 --- a/.pa11yci-pr.conf.js +++ b/.pa11yci-pr.conf.js @@ -2,6 +2,7 @@ var config = { defaults: { concurrency: 1, runners: ['axe'], + useIncognitoBrowserContext: false, chromeLaunchConfig: { args: ['--no-sandbox'], }, @@ -10,79 +11,99 @@ var config = { urls: [ { url: '${HOST}/login', + wait: 500, + rootElement: '.main-view', + }, + { + url: '${HOST}/login', + wait: 500, actions: [ + "wait for element input[name='user'] to be added", "set field input[name='user'] to admin", "set field input[name='password'] to admin", "click element button[aria-label='Login button']", "wait for element [aria-label='Skip change password button'] to be visible", ], - threshold: 2, + threshold: 1, + rootElement: '.main-view', }, { url: '${HOST}/?orgId=1', + wait: 500, threshold: 7, }, { url: '${HOST}/d/O6f11TZWk/panel-tests-bar-gauge', - hideElements: '.sidemenu', + wait: 500, + rootElement: '.main-view', threshold: 2, }, { url: '${HOST}/d/O6f11TZWk/panel-tests-bar-gauge?orgId=1&editview=settings', - rootElement: '.dashboard-settings', + wait: 500, + rootElement: '.main-view', threshold: 10, }, { url: '${HOST}/?orgId=1&search=open', + wait: 500, rootElement: '.main-view', - threshold: 15, + threshold: 14, }, { url: '${HOST}/alerting/list', + wait: 500, rootElement: '.main-view', - threshold: 7, + threshold: 6, }, { url: '${HOST}/datasources', + wait: 500, rootElement: '.main-view', - threshold: 36, + threshold: 35, }, { url: '${HOST}/org/users', + wait: 500, rootElement: '.main-view', - threshold: 4, + threshold: 3, }, { url: '${HOST}/org/teams', + wait: 500, rootElement: '.main-view', threshold: 1, }, { url: '${HOST}/plugins', + wait: 500, rootElement: '.main-view', - threshold: 41, + threshold: 40, }, { url: '${HOST}/org', + wait: 500, rootElement: '.main-view', threshold: 2, }, { url: '${HOST}/org/apikeys', + wait: 500, rootElement: '.main-view', - threshold: 5, + threshold: 3, }, { url: '${HOST}/dashboards', + wait: 500, rootElement: '.main-view', - threshold: 11, + threshold: 7, }, ], }; function myPa11yCiConfiguration(urls, defaults) { const HOST_SERVER = process.env.HOST || 'localhost'; - const PORT_SERVER = process.env.PORT || '3000'; + const PORT_SERVER = process.env.PORT || '3001'; for (var idx = 0; idx < urls.length; idx++) { urls[idx] = { ...urls[idx], url: urls[idx].url.replace('${HOST}', `${HOST_SERVER}:${PORT_SERVER}`) }; } diff --git a/.pa11yci.conf.js b/.pa11yci.conf.js index 1fdd9360ece..6b872fcf390 100644 --- a/.pa11yci.conf.js +++ b/.pa11yci.conf.js @@ -2,6 +2,7 @@ var config = { defaults: { concurrency: 1, runners: ['axe'], + useIncognitoBrowserContext: false, chromeLaunchConfig: { args: ['--no-sandbox'], }, @@ -10,58 +11,78 @@ var config = { urls: [ { url: '${HOST}/login', + wait: 500, + rootElement: '.main-view', + }, + { + url: '${HOST}/login', //skip password and login actions: [ + "wait for element input[name='user'] to be added", "set field input[name='user'] to admin", "set field input[name='password'] to admin", "click element button[aria-label='Login button']", "wait for element [aria-label='Skip change password button'] to be visible", ], + wait: 500, + rootElement: '.main-view', }, { url: '${HOST}/?orgId=1', + wait: 500, }, { url: '${HOST}/d/O6f11TZWk/panel-tests-bar-gauge', - hideElements: '.sidemenu', + wait: 500, + rootElement: '.main-view', }, { url: '${HOST}/d/O6f11TZWk/panel-tests-bar-gauge?orgId=1&editview=settings', - rootElement: '.dashboard-settings', + wait: 500, + rootElement: '.main-view', }, { url: '${HOST}/?orgId=1&search=open', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/alerting/list', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/datasources', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/org/users', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/org/teams', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/plugins', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/org', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/org/apikeys', + wait: 500, rootElement: '.main-view', }, { url: '${HOST}/dashboards', + wait: 500, rootElement: '.main-view', }, ], @@ -69,11 +90,10 @@ var config = { function myPa11yCiConfiguration(urls, defaults) { const HOST_SERVER = process.env.HOST || 'localhost'; - const PORT_SERVER = process.env.PORT || '3000'; + const PORT_SERVER = process.env.PORT || '3001'; for (var idx = 0; idx < urls.length; idx++) { urls[idx] = { ...urls[idx], url: urls[idx].url.replace('${HOST}', `${HOST_SERVER}:${PORT_SERVER}`) }; } - return { defaults: defaults, urls: urls, diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aa6f988762..ca09fd666f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,3 @@ - # 8.2.0-beta1 (2021-09-16) @@ -58,20 +57,17 @@ ### Breaking changes - The `monaco-editor` dependency in `grafana-ui` has been updated to a newer version (`0.27.0`), which is not completely backward compatible with the old version (`0.21.2`). The backward incompatible changes are fairly small, but they do exist, so if your code accesses the raw monaco-objects through the `grafana-ui` package, please check the [monaco-editor changelog](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md) and apply any necessary changes. Issue [#39027](https://github.com/grafana/grafana/issues/39027) - -The mandatory `css` prop in `grafana/ui` components has been removed. +The mandatory `css` prop in `grafana/ui` components has been removed. Previous versions of `grafana/ui` components were typed incorrectly due to a dependency mismatch between emotion 10 and 11 causing a `css` prop to be added to components that extended react types. - Issue [#38078](https://github.com/grafana/grafana/issues/38078) +Issue [#38078](https://github.com/grafana/grafana/issues/38078) -Panel queries and/or annotation queries that used more than one statistic will be converted into one query/annotation per statistic. In case an alerting rule was based on a query row that had more than one statistic, it would now be based only on the first statistic for that query row. New alerting rules will not be created for migrated queries. Please note that in most cases it would not make sense to have an alerting rule that is based on multiple statistics anyway. Issue [#36925](https://github.com/grafana/grafana/issues/36925) +Panel and annotation queries using more than one statistic now converts into one query/annotation per statistic. Alerting rules based on a query row with multiple statistics now considers only the first statistic from that query row. New alerting rules are not created for migrated queries. Usually, it does not make sense to have an alerting rule based on multiple statistics. Issue [#36925](https://github.com/grafana/grafana/issues/36925) ### Deprecations - `getHighlighterExpressions` in datasource APIs ( used to highlight logs while editing queries) has been deprecated and will be removed in a future release. # Deprecation notice @@ -84,6 +80,16 @@ Panel queries and/or annotation queries that used more than one statistic will b + + +# 8.1.5 (2021-09-21) + +### Bug fixes + +- **BarChart:** Fixes panel error that happens on second refresh. [#39304](https://github.com/grafana/grafana/pull/39304), [@DanCech](https://github.com/DanCech) + + + # 8.1.4 (2021-09-16) diff --git a/Makefile b/Makefile index 605a3f7fd6a..d848615bd08 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ golangci-lint: scripts/go/bin/golangci-lint --config ./scripts/go/configs/.golangci.toml \ $(GO_FILES) -lint-go: golangci-lint # Run all code checks for backend. +lint-go: golangci-lint ## Run all code checks for backend. You can use GO_FILES to specify exact files to check # with disabled SC1071 we are ignored some TCL,Expect `/usr/bin/env expect` scripts shellcheck: $(SH_FILES) ## Run checks for shell scripts. diff --git a/README.md b/README.md index a5ac19a0c57..f4873c5b0e4 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,8 @@ The Grafana documentation is available at [grafana.com/docs](https://grafana.com If you're interested in contributing to the Grafana project: -- Start by reading the [Contributing guide](/CONTRIBUTING.md). -- Learn how to set up your local environment, in our [Developer guide](/contribute/developer-guide.md). +- Start by reading the [Contributing guide](https://github.com/grafana/grafana/blob/HEAD/CONTRIBUTING.md). +- Learn how to set up your local environment, in our [Developer guide](https://github.com/grafana/grafana/blob/HEAD/contribute/developer-guide.md). - Explore our [beginner-friendly issues](https://github.com/grafana/grafana/issues?q=is%3Aopen+is%3Aissue+label%3A%22beginner+friendly%22). - Look through our [style guide and Storybook](https://developers.grafana.com/ui/latest/index.html). @@ -40,8 +40,8 @@ If you're interested in contributing to the Grafana project: - Follow [@grafana on Twitter](https://twitter.com/grafana/). - Read and subscribe to the [Grafana blog](https://grafana.com/blog/). - If you have a specific question, check out our [discussion forums](https://community.grafana.com/). -- For general discussions, join us on the [official Slack](http://slack.raintank.io/) team. +- For general discussions, join us on the [official Slack](https://slack.grafana.com) team. ## License -Grafana is distributed under [AGPL-3.0-only](LICENSE). For Apache-2.0 exceptions, see [LICENSING.md](LICENSING.md). +Grafana is distributed under [AGPL-3.0-only](LICENSE). For Apache-2.0 exceptions, see [LICENSING.md](https://github.com/grafana/grafana/blob/HEAD/LICENSING.md). diff --git a/contribute/create-pull-request.md b/contribute/create-pull-request.md index b8009c2b94d..4762289ce37 100644 --- a/contribute/create-pull-request.md +++ b/contribute/create-pull-request.md @@ -62,7 +62,7 @@ We use [pa11y-ci](https://github.com/pa11y/pa11y-ci) to collect accessibility er If the contribution introduces new a11y errors, our continuous integration will fail, preventing you to merge on the main branch. In those cases there are two alternatives for moving forward: - Check the error log on the pipeline step `test-a11y-frontend-pr`, identify what was the error, and fix it. -- Locally run the command `yarn test:accessibility-report` that generates an HTML accessibility report, then go to the URL that contains your change, identify the error, and fix it. Keep in mind, a local Grafana instance needs to be running on `http://localhost:3000`. +- Locally run the command `yarn test:accessibility-report` that generates an HTML accessibility report, then go to the URL that contains your change, identify the error, and fix it. Keep in mind, a local e2e Grafana instance is going to be running on `http://localhost:3001`. You can also prevent introducing a11y errors by installing an a11y plugin in your browser, for example, axe DevTools, Accessibility Insights for Web among others. diff --git a/devenv/dev-dashboards/panel-table/table_tests_new.json b/devenv/dev-dashboards/panel-table/table_tests_new.json index 31e7d074e25..11c6c8c0eb8 100644 --- a/devenv/dev-dashboards/panel-table/table_tests_new.json +++ b/devenv/dev-dashboards/panel-table/table_tests_new.json @@ -132,7 +132,7 @@ } ] }, - "pluginVersion": "7.5.0-pre", + "pluginVersion": "", "targets": [ { "refId": "A", @@ -263,7 +263,7 @@ } ] }, - "pluginVersion": "7.5.0-pre", + "pluginVersion": "", "targets": [ { "refId": "A", @@ -351,7 +351,7 @@ "showHeader": true, "sortBy": [] }, - "pluginVersion": "7.5.0-pre", + "pluginVersion": "", "targets": [ { "refId": "A", @@ -387,7 +387,7 @@ }, { "collapsed": false, - "datasource": null, + "datasource": "gdev-testdata", "gridPos": { "h": 1, "w": 24, @@ -460,7 +460,7 @@ "value": [ { "title": "Details", - "url": "http://detail?serverLabel=${__field.labels.server}&valueNumeric=${__value.numeric}" + "url": "http://detail?serverLabel=${__field.labels.server}&valueNumeric=${__value.numeric}" } ] } @@ -479,7 +479,7 @@ "options": { "showHeader": true }, - "pluginVersion": "7.5.0-pre", + "pluginVersion": "", "targets": [ { "alias": "S1", @@ -571,7 +571,7 @@ } ] }, - "pluginVersion": "7.5.0-pre", + "pluginVersion": "", "targets": [ { "refId": "A", @@ -604,6 +604,55 @@ } ], "type": "table" + }, + { + "datasource": "gdev-testdata", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": 0 + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 12, + "options": { + "footer": { + "show": true, + "fields": "", + "reducer": [ + "sum" + ] + }, + "showHeader": true + }, + "pluginVersion": "", + "title": "Footer", + "type": "table" } ], "schemaVersion": 27, @@ -635,5 +684,5 @@ "timezone": "", "title": "Panel Tests - React Table", "uid": "U_bZIMRMk", - "version": 1 + "version": 6 } \ No newline at end of file diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md index 20be5059a01..5c3a1e291bc 100644 --- a/docs/sources/administration/configuration.md +++ b/docs/sources/administration/configuration.md @@ -8,19 +8,15 @@ weight = 150 # Configuration -Grafana has a number of configuration options that you can specify in a `.ini` configuration file or specified using environment variables. +Grafana has default and custom configuration files. You can customize your Grafana instance by modifying the custom configuration file or by using environment variables. To see the list of settings for a Grafana instance, refer to [View server settings]({{< relref "view-server/view-server-settings.md" >}}). -> **Note:** You must restart Grafana for any configuration changes to take effect. +> **Note:** After you add custom options, [uncomment](#remove-comments-in-the-ini-files) the relevant sections of the configuration file. Restart Grafana for your changes to take effect. -To see all settings currently applied to the Grafana server, refer to [View server settings]({{< relref "view-server/view-server-settings.md" >}}). +## Configuration file location -## Config file locations +The default settings for a Grafana instance are stored in the `$WORKING_DIR/conf/defaults.ini` file. _Do not_ change the location in this file. -_Do not_ change `defaults.ini`! Grafana defaults are stored in this file. Depending on your OS, make all configuration changes in either `custom.ini` or `grafana.ini`. - -- Default configuration from `$WORKING_DIR/conf/defaults.ini` -- Custom configuration from `$WORKING_DIR/conf/custom.ini` -- The custom configuration file path can be overridden using the `--config` parameter +Depending on your OS, your custom configuration file is either the `$WORKING_DIR/conf/defaults.ini` file or the `/usr/local/etc/grafana/grafana.ini` file. The custom configuration file path can be overridden using the `--config` parameter. ### Linux @@ -32,25 +28,23 @@ Refer to [Configure a Grafana Docker image]({{< relref "configure-docker.md" >}} ### Windows -`sample.ini` is in the same directory as `defaults.ini` and contains all the settings commented out. Copy `sample.ini` and name it `custom.ini`. +On Windows, the `sample.ini` file is located in the same directory as `defaults.ini` file. It contains all the settings commented out. Copy `sample.ini` and name it `custom.ini`. ### macOS -By default, the configuration file is located at `/usr/local/etc/grafana/grafana.ini`. For a Grafana instance installed using Homebrew, edit the `grafana.ini` file directly. Otherwise, add a configuration file named `custom.ini` to the `conf` folder to override any of the settings defined in `conf/defaults.ini`. +By default, the configuration file is located at `/usr/local/etc/grafana/grafana.ini`. For a Grafana instance installed using Homebrew, edit the `grafana.ini` file directly. Otherwise, add a configuration file named `custom.ini` to the `conf` folder to override the settings defined in `conf/defaults.ini`. -## Comments in .ini Files +## Remove comments in the .ini files -Semicolons (the `;` char) are the standard way to comment out lines in a `.ini` file. If you want to change a setting, you must delete the semicolon (`;`) in front of the setting before it will work. +Grafana uses semicolons (the `;` char) to comment out lines in a `.ini` file. You must uncomment each line in the `custom.ini` or the `grafana.ini` file that you are modify by removing `;` from the beginning of that line. Otherwise your changes will be ignored. -**Example** +For example: ``` # The HTTP port to use ;http_port = 3000 ``` -A common problem is forgetting to uncomment a line in the `custom.ini` (or `grafana.ini`) file which causes the configuration option to be ignored. - ## Configure with environment variables All options in the configuration file can be overridden using environment variables using the syntax: diff --git a/docs/sources/alerting/old-alerting/notifications.md b/docs/sources/alerting/old-alerting/notifications.md index 61de7d33a9c..4a1b06d7069 100644 --- a/docs/sources/alerting/old-alerting/notifications.md +++ b/docs/sources/alerting/old-alerting/notifications.md @@ -51,26 +51,26 @@ These examples show how often and when reminders are sent for a triggered alert. ## List of supported notifiers | Name | Type | Supports images | Supports alert rule tags | -| --------------------------------------------- | ------------------------- | ------------------ | ----------------------- | -| [DingDing](#dingdingdingtalk) | `dingding` | yes, external only | no | -| [Discord](#discord) | `discord` | yes | no | -| [Email](#email) | `email` | yes | no | -| [Google Hangouts Chat](#google-hangouts-chat) | `googlechat` | yes, external only | no | -| Hipchat | `hipchat` | yes, external only | no | -| [Kafka](#kafka) | `kafka` | yes, external only | no | -| Line | `line` | yes, external only | no | -| Microsoft Teams | `teams` | yes, external only | no | -| [Opsgenie](#opsgenie) | `opsgenie` | yes, external only | yes | -| [Pagerduty](#pagerduty) | `pagerduty` | yes, external only | yes | -| Prometheus Alertmanager | `prometheus-alertmanager` | yes, external only | yes | -| [Pushover](#pushover) | `pushover` | yes | no | -| Sensu | `sensu` | yes, external only | no | -| [Sensu Go](#sensu-go) | `sensugo` | yes, external only | no | -| [Slack](#slack) | `slack` | yes | no | -| Telegram | `telegram` | yes | no | -| Threema | `threema` | yes, external only | no | -| VictorOps | `victorops` | yes, external only | yes | -| [Webhook](#webhook) | `webhook` | yes, external only | yes | +| --------------------------------------------- | ------------------------- | ------------------ | ------------------------ | +| [DingDing](#dingdingdingtalk) | `dingding` | yes, external only | no | +| [Discord](#discord) | `discord` | yes | no | +| [Email](#email) | `email` | yes | no | +| [Google Hangouts Chat](#google-hangouts-chat) | `googlechat` | yes, external only | no | +| Hipchat | `hipchat` | yes, external only | no | +| [Kafka](#kafka) | `kafka` | yes, external only | no | +| Line | `line` | yes, external only | no | +| Microsoft Teams | `teams` | yes, external only | no | +| [Opsgenie](#opsgenie) | `opsgenie` | yes, external only | yes | +| [Pagerduty](#pagerduty) | `pagerduty` | yes, external only | yes | +| Prometheus Alertmanager | `prometheus-alertmanager` | yes, external only | yes | +| [Pushover](#pushover) | `pushover` | yes | no | +| Sensu | `sensu` | yes, external only | no | +| [Sensu Go](#sensu-go) | `sensugo` | yes, external only | no | +| [Slack](#slack) | `slack` | yes | no | +| Telegram | `telegram` | yes | no | +| Threema | `threema` | yes, external only | no | +| VictorOps | `victorops` | yes, external only | yes | +| [Webhook](#webhook) | `webhook` | yes, external only | yes | ### Email diff --git a/docs/sources/datasources/aws-cloudwatch/_index.md b/docs/sources/datasources/aws-cloudwatch/_index.md index 635bc61cb2e..9a2226da954 100644 --- a/docs/sources/datasources/aws-cloudwatch/_index.md +++ b/docs/sources/datasources/aws-cloudwatch/_index.md @@ -55,6 +55,7 @@ Here is a minimal policy example: "cloudwatch:ListMetrics", "cloudwatch:GetMetricStatistics", "cloudwatch:GetMetricData" + "cloudwatch:GetInsightRuleReport" ], "Resource": "*" }, diff --git a/docs/sources/enterprise/usage-insights/export-logs.md b/docs/sources/enterprise/usage-insights/export-logs.md index 9080f69f05b..418d3b2134b 100644 --- a/docs/sources/enterprise/usage-insights/export-logs.md +++ b/docs/sources/enterprise/usage-insights/export-logs.md @@ -48,8 +48,6 @@ Logs of usage insights contain the following fields, where the fields followed b ## Configuration -The following procedure assumes that you have installed Loki. Refer to [Install Loki](/docs/loki/latest/installation/). - To export your logs, enable the usage insights feature and [configure]({{< relref "../../administration/configuration.md" >}}) an export location in the configuration file: ```ini @@ -58,7 +56,16 @@ To export your logs, enable the usage insights feature and [configure]({{< relre enabled = true # Storage type storage = loki +``` +The options for storage type are `loki` and `logger` (added in Grafana Enterprise 8.2). + +If the storage type is set to `loki` you'll need to also configure Grafana +to export to a Loki ingestion server. To do this, you'll need Loki installed. +Refer to [Install Loki](/docs/loki/latest/installation/) for instructions +on how to install Loki. + +```ini [usage_insights.export.storage.loki] # Set the communication protocol to use with Loki (can be grpc or http) type = grpc @@ -68,9 +75,12 @@ url = localhost:9095 tls = true ``` +Using `logger` will print usage insights to your [Grafana server log]({{< relref "../../administration/configuration.md#log" >}}). +There is no option for configuring the `logger` storage type. + ## Visualize Loki usage insights in Grafana -Now that your logs are exported into Loki, you can build Grafana dashboards to understand your Grafana instance usage. +If you export logs into Loki, you can build Grafana dashboards to understand your Grafana instance usage. 1. Add Loki as a data source. Refer to [Grafana fundamentals tutorial](/tutorials/grafana-fundamentals/#6). 1. Import one of the following dashboards: diff --git a/docs/sources/http_api/dashboard.md b/docs/sources/http_api/dashboard.md index aeb1253af60..a404e9e82f0 100644 --- a/docs/sources/http_api/dashboard.md +++ b/docs/sources/http_api/dashboard.md @@ -22,7 +22,7 @@ The uid can have a maximum length of 40 characters. `POST /api/dashboards/db` -Creates a new dashboard or updates an existing dashboard. +Creates a new dashboard or updates an existing dashboard. When updating existing dashboards, if you do not define the `folderId` and `folderUid` properties, then the dashboard(s) are moved to the `General` folder. **Example Request for new dashboard**: diff --git a/docs/sources/release-notes/_index.md b/docs/sources/release-notes/_index.md index 4d9a99a1cf5..80e33b1eec4 100644 --- a/docs/sources/release-notes/_index.md +++ b/docs/sources/release-notes/_index.md @@ -9,6 +9,7 @@ Here you can find detailed release notes that list everything that is included i about deprecations, breaking changes as well as changes that relate to plugin development. - [Release notes for 8.2.0-beta1]({{< relref "release-notes-8-2-0-beta1" >}}) +- [Release notes for 8.1.5]({{< relref "release-notes-8-1-5" >}}) - [Release notes for 8.1.4]({{< relref "release-notes-8-1-4" >}}) - [Release notes for 8.1.3]({{< relref "release-notes-8-1-3" >}}) - [Release notes for 8.1.2]({{< relref "release-notes-8-1-2" >}}) diff --git a/docs/sources/release-notes/release-notes-8-1-4.md b/docs/sources/release-notes/release-notes-8-1-4.md index b3d9134e38c..acc0e5df0df 100644 --- a/docs/sources/release-notes/release-notes-8-1-4.md +++ b/docs/sources/release-notes/release-notes-8-1-4.md @@ -22,4 +22,3 @@ list = false - **InfluxDB:** Fix regex to identify `/` as separator. [#39185](https://github.com/grafana/grafana/pull/39185), [@dsotirakis](https://github.com/dsotirakis) - **LibraryPanels:** Fix update issues related to library panels in rows. [#38963](https://github.com/grafana/grafana/pull/38963), [@hugohaggmark](https://github.com/hugohaggmark) - **Variables:** Fix variables not updating inside a Panel when the preceding Row uses "Repeat For". [#38935](https://github.com/grafana/grafana/pull/38935), [@axelavargas](https://github.com/axelavargas) - diff --git a/docs/sources/release-notes/release-notes-8-1-5.md b/docs/sources/release-notes/release-notes-8-1-5.md new file mode 100644 index 00000000000..0747f76d53d --- /dev/null +++ b/docs/sources/release-notes/release-notes-8-1-5.md @@ -0,0 +1,13 @@ ++++ +title = "Release notes for Grafana 8.1.5" +[_build] +list = false ++++ + + + +# Release notes for Grafana 8.1.5 + +### Bug fixes + +- **BarChart:** Fixes panel error that happens on second refresh. [#39304](https://github.com/grafana/grafana/pull/39304), [@DanCech](https://github.com/DanCech) diff --git a/docs/sources/release-notes/release-notes-8-2-0-beta1.md b/docs/sources/release-notes/release-notes-8-2-0-beta1.md index 938bba76314..da302f6c73f 100644 --- a/docs/sources/release-notes/release-notes-8-2-0-beta1.md +++ b/docs/sources/release-notes/release-notes-8-2-0-beta1.md @@ -63,20 +63,17 @@ list = false ### Breaking changes - The `monaco-editor` dependency in `grafana-ui` has been updated to a newer version (`0.27.0`), which is not completely backward compatible with the old version (`0.21.2`). The backward incompatible changes are fairly small, but they do exist, so if your code accesses the raw monaco-objects through the `grafana-ui` package, please check the [monaco-editor changelog](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md) and apply any necessary changes. Issue [#39027](https://github.com/grafana/grafana/issues/39027) - -The mandatory `css` prop in `grafana/ui` components has been removed. +The mandatory `css` prop in `grafana/ui` components has been removed. Previous versions of `grafana/ui` components were typed incorrectly due to a dependency mismatch between emotion 10 and 11 causing a `css` prop to be added to components that extended react types. - Issue [#38078](https://github.com/grafana/grafana/issues/38078) +Issue [#38078](https://github.com/grafana/grafana/issues/38078) -Panel queries and/or annotation queries that used more than one statistic will be converted into one query/annotation per statistic. In case an alerting rule was based on a query row that had more than one statistic, it would now be based only on the first statistic for that query row. New alerting rules will not be created for migrated queries. Please note that in most cases it would not make sense to have an alerting rule that is based on multiple statistics anyway. Issue [#36925](https://github.com/grafana/grafana/issues/36925) +Panel queries and/or annotation queries that used more than one statistic will be converted into one query/annotation per statistic. In case an alerting rule was based on a query row that had more than one statistic, it would now be based only on the first statistic for that query row. New alerting rules will not be created for migrated queries. Please note that in most cases it would not make sense to have an alerting rule that is based on multiple statistics anyway. Issue [#36925](https://github.com/grafana/grafana/issues/36925) ### Deprecations - `getHighlighterExpressions` in datasource APIs ( used to highlight logs while editing queries) has been deprecated and will be removed in a future release. # Deprecation notice diff --git a/docs/sources/whatsnew/whats-new-in-v8-2.md b/docs/sources/whatsnew/whats-new-in-v8-2.md index e45659dd606..a7a0ad5f5cf 100644 --- a/docs/sources/whatsnew/whats-new-in-v8-2.md +++ b/docs/sources/whatsnew/whats-new-in-v8-2.md @@ -12,7 +12,7 @@ list = false > **Note:** This topic will be updated frequently between now and the final release. Additionally, not all features listed here may be present in all the beta releases. -Grafana 8.2 continues to build on the foundation laid out in Grafana 8.0 & 8.1. We’ve continued to extend the GeoMap panel and bring new features to the Time Series panel. Grafana 8.2 also marks the start of our work to bring Grafana closer to all users with a focus on increasing Grafana’s accessibility, part of its continuing mission to democratize metrics *for everyone*. +Grafana 8.2 continues to build on the foundation laid out in Grafana 8.0 & 8.1. We’ve continued to extend the GeoMap panel and bring new features to the Time Series panel. Grafana 8.2 also marks the start of our work to bring Grafana closer to all users with a focus on increasing Grafana’s accessibility, part of its continuing mission to democratize metrics _for everyone_. We’ve summarized what’s new in the release here, but you might also be interested in the announcement blog post as well. If you’d like all the details you can checkout the complete [CHANGELOG.md](https://github.com/grafana/grafana/blob/master/CHANGELOG.md). @@ -34,7 +34,7 @@ A number of new visualizations and features are included in Grafana 8.2 includin ### XY Chart [beta] -The XY Chart panel, aka. scatter panel, is available in beta form. This chart is all about first-class support for data where x does not equate to time. +The XY Chart panel, aka. scatter panel, is available in beta form. This chart is all about first-class support for data where x does not equate to time. {{< figure src="/static/img/docs/scatter-panel/scatter-placeholder.png" max-width="1200px" caption="Scatter Panel" >}} @@ -62,8 +62,6 @@ Usage Insights Logs contain valuable information about user dashboard visits, qu Reports are a powerful way to deliver insights directly to people’s email inboxes. Now you can create a report directly from any dashboard, using the Share button. This is especially useful combined with fine-grained access control, which you can use to grant Editors or Viewers the ability to create reports in Grafana. Learn more about Reporting in the [docs](​​https://grafana.com/docs/grafana/latest/enterprise/reporting/). - ## Image Renderer performance improvements and measurement You can use Grafana’s image renderer to generate JPEG and PDF images of panels and dashboards. These images are used for alert notifications, PDF exports, and reports sent by Grafana. We’ve added additional metrics to the image renderer to help you diagnose its performance, and included guidance in our documentation to help you configure it for the best mix of performance and resource usage. In our tests, we were able to reduce image load time from a 95th percentile of 10 seconds to less than 3 seconds under normal load. - diff --git a/e2e/run-suite b/e2e/run-suite index c72e715cf87..f9fad1f8da3 100755 --- a/e2e/run-suite +++ b/e2e/run-suite @@ -17,7 +17,7 @@ SUITE=${SUITE:-$DEFAULT_SUITE} if [ "$1" == "debug" ]; then echo -e "Debug mode" SLOWMO=1 - PARAMS="--headed --no-exit" + PARAMS="--no-exit" fi if [ "$1" == "dev" ]; then @@ -28,5 +28,5 @@ fi cd packages/grafana-e2e yarn $CMD --env BASE_URL=$URL,SLOWMO=$SLOWMO \ - --config defaultCommandTimeout=30000,integrationFolder=../../e2e/$SUITE/specs,screenshotsFolder=../../e2e/$SUITE/screenshots,videosFolder=../../e2e/$SUITE/videos,fileServerFolder=./cypress,viewportWidth=1920,viewportHeight=1080,trashAssetsBeforeRuns=false \ + --config defaultCommandTimeout=30000,integrationFolder=../../e2e/$SUITE/specs,screenshotsFolder=../../e2e/$SUITE/screenshots,videosFolder=../../e2e/$SUITE/videos,fileServerFolder=./cypress,viewportWidth=1920,viewportHeight=1080,trashAssetsBeforeRuns=false,videoUploadOnPasses=false \ $PARAMS diff --git a/go.mod b/go.mod index d5c55101620..ab9cb2af023 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/BurntSushi/toml v0.3.1 github.com/Masterminds/semver v1.5.0 github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f - github.com/aws/aws-sdk-go v1.40.11 + github.com/aws/aws-sdk-go v1.40.37 github.com/beevik/etree v1.1.0 github.com/benbjohnson/clock v1.1.0 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b @@ -27,14 +27,15 @@ require ( github.com/cortexproject/cortex v1.8.2-0.20210428155238-d382e1d80eaf github.com/crewjam/saml v0.4.6-0.20201227203850-bca570abb2ce github.com/davecgh/go-spew v1.1.1 - github.com/denisenkom/go-mssqldb v0.0.0-20200910202707-1e08a3fab204 + github.com/denisenkom/go-mssqldb v0.10.0 github.com/dop251/goja v0.0.0-20210804101310-32956a348b49 github.com/fatih/color v1.10.0 github.com/gchaincl/sqlhooks v1.3.0 github.com/getsentry/sentry-go v0.10.0 github.com/go-kit/kit v0.11.0 github.com/go-macaron/binding v0.0.0-20190806013118-0b4f37bab25b - github.com/go-openapi/strfmt v0.20.1 + github.com/go-openapi/strfmt v0.20.2 + github.com/go-redis/redis/v8 v8.11.3 github.com/go-sourcemap/sourcemap v2.1.3+incompatible github.com/go-sql-driver/mysql v1.6.0 github.com/go-stack/stack v1.8.0 @@ -49,14 +50,14 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/gosimple/slug v1.9.0 github.com/grafana/grafana-aws-sdk v0.7.0 - github.com/grafana/grafana-plugin-sdk-go v0.113.0 + github.com/grafana/grafana-plugin-sdk-go v0.114.0 github.com/grafana/loki v1.6.2-0.20210520072447-15d417efe103 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/hashicorp/go-hclog v0.16.1 github.com/hashicorp/go-plugin v1.4.2 github.com/hashicorp/go-version v1.3.0 github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec - github.com/influxdata/influxdb-client-go/v2 v2.2.3 + github.com/influxdata/influxdb-client-go/v2 v2.3.1-0.20210518120617-5d1fff431040 github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 github.com/jmespath/go-jmespath v0.4.0 github.com/json-iterator/go v1.1.11 @@ -68,20 +69,20 @@ require ( github.com/magefile/mage v1.11.0 github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-sqlite3 v1.14.7 - github.com/matttproud/golang_protobuf_extensions v1.0.1 + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f github.com/opentracing/opentracing-go v1.2.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982 // indirect github.com/pkg/errors v0.9.1 - github.com/prometheus/alertmanager v0.23.0-rc.0.0.20210906104939-8da517524a87 + github.com/prometheus/alertmanager v0.23.1-0.20210914172521-e35efbddb66a github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_model v0.2.0 github.com/prometheus/common v0.30.0 - github.com/prometheus/prometheus v1.8.2-0.20210621150501-ff58416a0b02 + github.com/prometheus/prometheus v1.8.2-0.20210915140241-bd217c58a735 github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 github.com/robfig/cron/v3 v3.0.1 - github.com/russellhaering/goxmldsig v1.1.0 + github.com/russellhaering/goxmldsig v1.1.1 github.com/smartystreets/goconvey v1.6.4 github.com/spyzhov/ajson v0.4.2 github.com/stretchr/testify v1.7.0 @@ -98,13 +99,13 @@ require ( go.opentelemetry.io/collector/model v0.31.0 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e golang.org/x/exp v0.0.0-20210220032938-85be41e4509f // indirect - golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 - golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a + golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f + golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac golang.org/x/tools v0.1.5 gonum.org/v1/gonum v0.9.1 - google.golang.org/api v0.54.0 + google.golang.org/api v0.56.0 google.golang.org/grpc v1.40.0 google.golang.org/protobuf v1.27.1 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect @@ -112,16 +113,16 @@ require ( gopkg.in/ldap.v3 v3.1.0 gopkg.in/macaron.v1 v1.4.0 gopkg.in/mail.v2 v2.3.1 - gopkg.in/redis.v5 v5.2.9 gopkg.in/square/go-jose.v2 v2.5.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + xorm.io/builder v0.3.6 xorm.io/core v0.7.3 xorm.io/xorm v0.8.2 ) require ( - cloud.google.com/go v0.90.0 // indirect + cloud.google.com/go v0.93.3 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 // indirect github.com/FZambia/eagle v0.0.1 // indirect github.com/FZambia/sentinel v1.1.0 // indirect @@ -136,11 +137,13 @@ require ( github.com/cenkalti/backoff/v4 v4.1.1 // indirect github.com/centrifugal/protocol v0.7.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cheekybits/genny v1.0.0 // indirect github.com/cockroachdb/apd/v2 v2.0.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/deepmap/oapi-codegen v1.3.13 // indirect + github.com/deepmap/oapi-codegen v1.6.0 // indirect + github.com/dennwc/varint v1.0.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect @@ -148,7 +151,7 @@ require ( github.com/emicklei/proto v1.6.15 // indirect github.com/felixge/httpsnoop v1.0.2 // indirect github.com/go-kit/log v0.1.0 // indirect - github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-openapi/analysis v0.20.1 // indirect github.com/go-openapi/errors v0.20.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect @@ -165,8 +168,8 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/flatbuffers v1.12.0 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/google/flatbuffers v2.0.0+incompatible // indirect + github.com/googleapis/gax-go/v2 v2.1.0 // indirect github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect @@ -183,7 +186,6 @@ require ( github.com/jonboulle/clockwork v0.2.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/klauspost/cpuid/v2 v2.0.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -191,7 +193,7 @@ require ( github.com/mattetti/filebuffer v1.0.1 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/miekg/dns v1.1.42 // indirect + github.com/miekg/dns v1.1.43 // indirect github.com/mitchellh/go-testing-interface v1.14.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mna/redisc v1.2.1 // indirect @@ -230,14 +232,12 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/goleak v1.1.10 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.4.2 // indirect - golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 // indirect + golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 // indirect golang.org/x/text v0.3.6 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67 // indirect + google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 // indirect gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect - xorm.io/builder v0.3.6 // indirect ) replace github.com/apache/thrift => github.com/apache/thrift v0.14.1 diff --git a/go.sum b/go.sum index 97ab66c9002..ebecf886343 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= @@ -26,8 +27,9 @@ cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0 h1:MjvSkUq8RuAb+2JLDi5VQmmExRJPUQ3JLCWpRB6fmdw= cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3 h1:wPBktZFzYBcCZVARvwVKqH1uEj+aLXofJEtrb4oOsio= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -68,6 +70,7 @@ github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9a github.com/Azure/azure-pipeline-go v0.1.9/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v23.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v36.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v37.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= @@ -81,8 +84,9 @@ github.com/Azure/azure-sdk-for-go v46.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v48.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v51.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v52.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v55.2.0+incompatible h1:TL2/vJWJEPOrmv97nHcbvjXES0Ntlb9P95hqGA1J2dU= github.com/Azure/azure-sdk-for-go v55.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v57.1.0+incompatible h1:TKQ3ieyB0vVKkF6t9dsWbMjq56O1xU3eh3Ec09v6ajM= +github.com/Azure/azure-sdk-for-go v57.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0 h1:lhSJz9RMbJcTgxifR1hUNJnn6CNYtbgEDtQV22/9RBA= github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.10.0 h1:jq5Urf8QJK6h0wr8CMiwggo4OSMkXwpArQlkSjSpaBk= @@ -94,6 +98,7 @@ github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxw github.com/Azure/azure-storage-queue-go v0.0.0-20181215014128-6ed74e755687/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8= github.com/Azure/go-amqp v0.12.6/go.mod h1:qApuH6OFTSKZFmCOxccvAv5rLizBQf4v8pRmG138DPo= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v11.2.8+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= @@ -108,8 +113,9 @@ github.com/Azure/go-autorest/autorest v0.11.4/go.mod h1:JFgpikqFJ/MleTTxwepExTKn github.com/Azure/go-autorest/autorest v0.11.10/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.11/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.19 h1:7/IqD2fEYVha1EPeaiytVKhzmPV223pfkRIQUGOK2IE= github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest v0.11.20 h1:s8H1PbCZSqg/DH7JMlOz6YMig6htWLNPsjDdlLqCx3M= +github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.1-0.20191028180845-3492b2aff503/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= @@ -120,8 +126,9 @@ github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQW github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.14 h1:G8hexQdV5D4khOXrWG2YuLCFKhWYmWD8bHYaXN5ophk= github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.15 h1:X+p2GF0GWyOiSmqohIaEeuNFNDY4I4EOlVuUQvFdWMk= +github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= @@ -163,8 +170,9 @@ github.com/FZambia/eagle v0.0.1/go.mod h1:xq6u/JeNZ5/8mrAQ76MMhzNTodASh9FavQlCgg github.com/FZambia/sentinel v1.1.0 h1:qrCBfxc8SvJihYNjBWgwUI93ZCvFe/PJIPTHKmlp8a8= github.com/FZambia/sentinel v1.1.0/go.mod h1:ytL1Am/RLlAoAXG6Kj5LNuw/TRRQrv2rt2FT26vP5gI= github.com/HdrHistogram/hdrhistogram-go v0.9.0/go.mod h1:nxrse8/Tzg2tg3DZcZjm6qEclQKK70g0KxO61gFFZD4= -github.com/HdrHistogram/hdrhistogram-go v1.0.1 h1:GX8GAYDuhlFQnI2fRDHQhTlkHMz8bEn0jTI6LJU0mpw= github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM= +github.com/HdrHistogram/hdrhistogram-go v1.1.0 h1:6dpdDPTRoo78HxAJ6T1HfMiKSnqhgRRqzCuPshRkQ7I= +github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -181,8 +189,23 @@ github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyv github.com/Microsoft/go-winio v0.4.9/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.18/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= @@ -200,6 +223,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.27.1/go.mod h1:g5s5osgELxgM+Md9Qni9rzo7Rbt+vvFQI4bt/Mc93II= github.com/Shopify/sarama v1.29.1/go.mod h1:mdtqvCSg8JOxk8PmpTNGyo6wzd4BMm4QXSfDnTXmgkE= @@ -223,6 +247,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4= github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= github.com/aliyun/aliyun-oss-go-sdk v2.0.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= @@ -261,6 +286,7 @@ github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-lambda-go v1.17.0/go.mod h1:FEwgPLE6+8wcGBTe5cJN3JWurd1Ztm9zN4jsXsjzKKw= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.22.4/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -284,8 +310,9 @@ github.com/aws/aws-sdk-go v1.38.3/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.38.60/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.40.11 h1:iIRx5w2FbiaEKnCFcai+NSnYa9zKFe6Lzt6aLLUh61A= github.com/aws/aws-sdk-go v1.40.11/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go v1.40.37 h1:I+Q6cLctkFyMMrKukcDnj+i2kjrQ37LGiOM6xmsxC48= +github.com/aws/aws-sdk-go v1.40.37/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4= github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.5.0/go.mod h1:acH3+MQoiMzozT/ivU+DbRg7Ooo2298RdRaWcOv+4vM= @@ -300,6 +327,7 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI= github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -307,9 +335,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmatcuk/doublestar v1.2.2/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= @@ -318,7 +349,12 @@ github.com/bonitoo-io/go-sql-bigquery v0.3.4-1.4.0/go.mod h1:J4Y6YJm0qTWB9aFziB7 github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bsm/sarama-cluster v2.1.13+incompatible/go.mod h1:r7ao+4tTNXvWm+VRpRJchr2kQhqxgmAp2iEX5W96gMM= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee h1:BnPxIde0gjtTnc9Er7cxvBk8DHLWhEux0SxayC8dP6I= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= @@ -346,8 +382,10 @@ github.com/cespare/xxhash v0.0.0-20181017004759-096ff4a8a059/go.mod h1:XrSqR1Vqq github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chromedp/cdproto v0.0.0-20200116234248-4da64dd111ac/go.mod h1:PfAWWKJqjlGFYJEidUM6aVIWPr0EpobeyVWEEmplX7g= @@ -356,6 +394,10 @@ github.com/chromedp/chromedp v0.5.3/go.mod h1:YLdPtndaHQ4rCpSpBG+IPpy9JvX0VD+7aa github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/cisco-ie/nx-telemetry-proto v0.0.0-20190531143454-82441e232cf6/go.mod h1:ugEfq4B8T8ciw/h5mCkgdiDRFS4CkqqhH2dymDB4knc= @@ -365,6 +407,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200313221541-5f7e5dd04533/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= @@ -378,25 +421,108 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3 h1:ijQT13JedHSHrQGWFcGEwzcNKrAGIiZ+jSD5QQG07SY= github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.4 h1:uPF0og3ByFzDnaStfiQj3fVGTEtaSNyU+bW7GR/nqGA= +github.com/containerd/containerd v1.5.4/go.mod h1:sx18RgvW6ABJ4iYUw7Q5x7bgFOAB9B6G7+yO0XBc4zw= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/coredns/coredns v1.1.2/go.mod h1:zASH/MVDgR6XZTbxvOnsZfffS+31vg6Ackf/wo1+AM0= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -430,6 +556,7 @@ github.com/crewjam/saml v0.4.6-0.20201227203850-bca570abb2ce/go.mod h1:/gCaeLf13 github.com/crossdock/crossdock-go v0.0.0-20160816171116-049aabb0122b/go.mod h1:v9FBN7gdVTpiD/+LZ7Po0UKvROyT87uLVxTHVky/dlQ= github.com/cucumber/godog v0.8.1/go.mod h1:vSh3r/lM+psC1BPXvdkSEuNjmXfpVqrMGYAElF6hxnA= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= @@ -440,6 +567,10 @@ github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -447,20 +578,25 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4= -github.com/deepmap/oapi-codegen v1.3.13 h1:9HKGCsdJqE4dnrQ8VerFS0/1ZOJPmAhN+g8xgp8y3K4= -github.com/deepmap/oapi-codegen v1.3.13/go.mod h1:WAmG5dWY8/PYHt4vKxlt90NsbHMAOCiteYKZMiIRfOo= +github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= +github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= +github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= +github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger/v3 v3.2103.0/go.mod h1:GHMCYxuDWyzbHkh4k3yyg4PM61tJPFfEGSMbE3Vd5QE= github.com/dgraph-io/ristretto v0.0.4-0.20210309073149-3836124cdc5a/go.mod h1:MIonLggsKgZLUSt414ExgwNtlOL5MuEoAJP514mwGe8= github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -476,15 +612,18 @@ github.com/digitalocean/godo v1.46.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2x github.com/digitalocean/godo v1.52.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= github.com/digitalocean/godo v1.57.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= github.com/digitalocean/godo v1.58.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= -github.com/digitalocean/godo v1.62.0 h1:7Gw2KFsWkxl36qJa0s50tgXaE0Cgm51JdRP+MFQvNnM= github.com/digitalocean/godo v1.62.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= +github.com/digitalocean/godo v1.65.0 h1:3SywGJBC18HaYtPQF+T36jYzXBi+a6eIMonSjDll7TA= +github.com/digitalocean/godo v1.65.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.6.0-rc.1.0.20170726174610-edc3ab29cdff+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -493,17 +632,23 @@ github.com/docker/docker v17.12.0-ce-rc1.0.20200706150819-a40b877fbb9e+incompati github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= +github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-plugins-helpers v0.0.0-20181025120712-1e6269c305b8/go.mod h1:LFyLie6XcDbyKGeVK6bHe+9aJTYCxWLBg5IrJZOaXKA= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libnetwork v0.8.0-dev.2.0.20181012153825-d7b61745d166/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dop251/goja v0.0.0-20210804101310-32956a348b49 h1:CtSi0QlA2Hy+nOh8JAZoiEBLW5pliAiKJ3l1Iq1472I= @@ -531,6 +676,7 @@ github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkg github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/ema/qdisc v0.0.0-20190904071900-b82c76788043/go.mod h1:ix4kG2zvdUd8kEKSW0ZTr1XLks0epFpI4j745DXxlNE= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/proto v1.6.15 h1:XbpwxmuOPrdES97FrSfpyy67SSCV/wBIKXqgJzh6hNw= github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= @@ -542,7 +688,11 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.9 h1:vQLjymTobffN2R0F8eTqw6q7iozfRO5Z0m+/4Vw+/uA= +github.com/envoyproxy/go-control-plane v0.9.9/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.1 h1:4CF52PCseTFt4bE+Yk3dIpdVi7XWuPVMhPtm4FaIJPM= +github.com/envoyproxy/protoc-gen-validate v0.6.1/go.mod h1:txg5va2Qkip90uYoSKH+nkAAmXrb2j3iq4FLwdrCbXQ= github.com/ericchiang/k8s v1.2.0/go.mod h1:/OmBgSq2cd9IANnsGHGlEz27nwMZV2YxlpXuQtU3Bz4= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc= @@ -567,7 +717,6 @@ github.com/fluent/fluent-bit-go v0.0.0-20190925192703-ea13c021720c/go.mod h1:WQX github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/foxcpp/go-mockdns v0.0.0-20201212160233-ede2f9158d15/go.mod h1:tPg4cp4nseejPd+UKxtCVQ2hUxNTZ7qQZJa7CLriIeo= @@ -580,12 +729,14 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gchaincl/sqlhooks v1.3.0 h1:yKPXxW9a5CjXaVf2HkQn6wn7TZARvbAOAelr3H8vK2Y= github.com/gchaincl/sqlhooks v1.3.0/go.mod h1:9BypXnereMT0+Ys8WGWHqzgkkOfHIhyeUCqXC24ra34= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= -github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw= +github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/sentry-go v0.10.0 h1:6gwY+66NHKqyZrdi6O2jGdo7wGdo9b3B69E01NFgT5g= github.com/getsentry/sentry-go v0.10.0/go.mod h1:kELm/9iCblqUYh+ZRML7PNdCvEuw24wBvJPYyi86cws= @@ -603,8 +754,8 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= -github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.1.0+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= @@ -614,6 +765,7 @@ github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmn github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= @@ -626,8 +778,9 @@ github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= @@ -728,8 +881,9 @@ github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= -github.com/go-openapi/strfmt v0.20.1 h1:1VgxvehFne1mbChGeCmZ5pc0LxUf6yaACVSIYAR91Xc= github.com/go-openapi/strfmt v0.20.1/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= +github.com/go-openapi/strfmt v0.20.2 h1:6XZL+fF4VZYFxKQGLAUB358hOrRh/wS51uWEtlONADE= +github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.17.2/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= @@ -759,9 +913,12 @@ github.com/go-openapi/validate v0.20.2 h1:AhqDegYV3J3iQkMPJSXkvzymHKMTw0BST3RK3h github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZIVCbJBpTUoY0= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v8 v8.0.0-beta.10.0.20200905143926-df7fe4e2ce72/go.mod h1:CJP1ZIHwhosNYwIdaHPZK9vHsM3+roNBaZ7U9Of1DXc= github.com/go-redis/redis/v8 v8.2.3/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw= +github.com/go-redis/redis/v8 v8.11.3 h1:GCjoYp8c+yQTJfc0n69iwSiHjvuAdruxl7elnZCxgt8= +github.com/go-redis/redis/v8 v8.11.3/go.mod h1:xNJ9xDG09FsIPwh3bWdk+0oDWHbtF9rPN0F/oD9XeKc= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 h1:JVrqSeQfdhYRFk24TvhTZWU0q8lfCojxZQFi3Ou7+uY= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= @@ -773,6 +930,7 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= @@ -814,7 +972,10 @@ github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhD github.com/gocql/gocql v0.0.0-20200121121104-95d072f1b5bb/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= github.com/gocql/gocql v0.0.0-20200228163523-cd4b606dd2fb/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= github.com/gocql/gocql v0.0.0-20200526081602-cd04bd7f22a7/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190402143921-271e53dc4968/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= @@ -823,6 +984,8 @@ github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -837,6 +1000,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/status v1.0.3 h1:WkVBY59mw7qUNTr/bLwO7J2vesJ0rQ2C3tMXrTd3w5M= github.com/gogo/status v1.0.3/go.mod h1:SavQ51ycCLnc7dGyJxp8YAmudx8xqiVrRf+6IXRsugc= +github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-migrate/migrate/v4 v4.7.0/go.mod h1:Qvut3N4xKWjoH3sokBccML6WyHSnggXm/DvMMnTsQIc= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -901,8 +1066,9 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v1.12.0 h1:/PtAHvnBY4Kqnx/xCQ3OIV9uYcSFGScBsWI3Oogeh6w= github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI= +github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -955,6 +1121,7 @@ github.com/google/pprof v0.0.0-20210323184331-8eee2492667d/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210827144239-02619b876842/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs= @@ -962,6 +1129,7 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= @@ -969,8 +1137,9 @@ github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1 github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww= github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= @@ -993,16 +1162,19 @@ github.com/gophercloud/gophercloud v0.13.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPU github.com/gophercloud/gophercloud v0.14.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM= github.com/gophercloud/gophercloud v0.15.0/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM= github.com/gophercloud/gophercloud v0.16.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= -github.com/gophercloud/gophercloud v0.18.0 h1:V6hcuMPmjXg+js9flU8T3RIHDCjV7F5CG5GD0MRhP/w= github.com/gophercloud/gophercloud v0.18.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= +github.com/gophercloud/gophercloud v0.20.0 h1:1+4jrsjVhdX5omlAo4jkmFc6ftLbuXLzgFo4i6lH+Gk= +github.com/gophercloud/gophercloud v0.20.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU= github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -1020,8 +1192,8 @@ github.com/grafana/go-mssqldb v0.0.0-20210326084033-d0ce3c521036/go.mod h1:xbL0r github.com/grafana/grafana-aws-sdk v0.7.0 h1:D+Lhxi3P/7vpyDHUK/fdX9bL2mRz8hLG04ucNf1E02o= github.com/grafana/grafana-aws-sdk v0.7.0/go.mod h1:+pPo5U+pX0zWimR7YBc7ASeSQfbRkcTyQYqMiAj7G5U= github.com/grafana/grafana-plugin-sdk-go v0.79.0/go.mod h1:NvxLzGkVhnoBKwzkst6CFfpMFKwAdIUZ1q8ssuLeF60= -github.com/grafana/grafana-plugin-sdk-go v0.113.0 h1:X46np4UNgM0YLhxC0oLa2q7WOHdU5T/oppZ+XlYusMk= -github.com/grafana/grafana-plugin-sdk-go v0.113.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk= +github.com/grafana/grafana-plugin-sdk-go v0.114.0 h1:9I55IXw7mOT71tZ/pdqCaWGz8vxfz31CXjaDtBV9ZBo= +github.com/grafana/grafana-plugin-sdk-go v0.114.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk= github.com/grafana/loki v1.6.2-0.20210520072447-15d417efe103 h1:qCmofFVwQR9QnsinstVqI1NPLMVl33jNCnOCXEAVn6E= github.com/grafana/loki v1.6.2-0.20210520072447-15d417efe103/go.mod h1:GHIsn+EohCChsdu5YouNZewqLeV9L2FNw4DEJU3P9qE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -1058,14 +1230,17 @@ github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT github.com/hashicorp/consul/api v1.5.0/go.mod h1:LqwrLNW876eYSuUOo4ZLHBcdKc038txr/IMfbLPATa4= github.com/hashicorp/consul/api v1.6.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn6r2DXKhuDNFg= github.com/hashicorp/consul/api v1.7.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn6r2DXKhuDNFg= -github.com/hashicorp/consul/api v1.8.1 h1:BOEQaMWoGMhmQ29fC26bi0qb7/rId9JzZP2V0Xmx7m8= github.com/hashicorp/consul/api v1.8.1/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= +github.com/hashicorp/consul/api v1.10.1 h1:MwZJp86nlnL+6+W1Zly4JUuVn9YHhMggBirMpHGD7kw= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/consul/sdk v0.5.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/consul/sdk v0.6.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/consul/sdk v0.7.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= @@ -1097,6 +1272,7 @@ github.com/hashicorp/go-memdb v1.3.0/go.mod h1:Mluclgwib3R93Hk5fxEfiRhB+6Dar64wW github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= @@ -1174,13 +1350,15 @@ github.com/hetznercloud/hcloud-go v1.21.1/go.mod h1:xng8lbDUg+xM1dgc0yGHX5EeqbwI github.com/hetznercloud/hcloud-go v1.22.0/go.mod h1:xng8lbDUg+xM1dgc0yGHX5EeqbwIq7UYlMWMTx3SQVg= github.com/hetznercloud/hcloud-go v1.23.1/go.mod h1:xng8lbDUg+xM1dgc0yGHX5EeqbwIq7UYlMWMTx3SQVg= github.com/hetznercloud/hcloud-go v1.24.0/go.mod h1:3YmyK8yaZZ48syie6xpm3dt26rtB6s65AisBHylXYFA= -github.com/hetznercloud/hcloud-go v1.26.2 h1:fI8BXAGJI4EFeCDd2a/I4EhqyK32cDdxGeWfYMGUi50= github.com/hetznercloud/hcloud-go v1.26.2/go.mod h1:2C5uMtBiMoFr3m7lBFPf7wXTdh33CevmZpQIIDPGYJI= +github.com/hetznercloud/hcloud-go v1.32.0 h1:7zyN2V7hMlhm3HZdxOarmOtvzKvkcYKjM0hcwYMQZz0= +github.com/hetznercloud/hcloud-go v1.32.0/go.mod h1:XX/TQub3ge0yWR2yHWmnDVIrB+MQbda1pHxkUmDlUME= github.com/hodgesds/perf-utils v0.0.8/go.mod h1:F6TfvsbtrF88i++hou29dTXlI2sfsJv+gRZDtmTJkAs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/igm/sockjs-go/v3 v3.0.0 h1:4wLoB9WCnQ8RI87cmqUH778ACDFVmRpkKRCWBeuc+Ww= @@ -1188,6 +1366,8 @@ github.com/igm/sockjs-go/v3 v3.0.0/go.mod h1:UqchsOjeagIBFHvd+RZpLaVRbCwGilEC08E github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -1197,6 +1377,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/influxdata/flux v0.65.0/go.mod h1:BwN2XG2lMszOoquQaFdPET8FRQfrXiZsWmcMO9rkaVY= github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= github.com/influxdata/flux v0.113.0/go.mod h1:3TJtvbm/Kwuo5/PEo5P6HUzwVg4bXWkb2wPQHPtQdlU= +github.com/influxdata/flux v0.120.1/go.mod h1:pGSAvyAA5d3et7SSzajaYShWYXmnRnJJq2qWi+WWZ2I= github.com/influxdata/go-syslog/v2 v2.0.1/go.mod h1:hjvie1UTaD5E1fTnDmxaCw8RRDrT4Ve+XHr5O2dKSCo= github.com/influxdata/go-syslog/v3 v3.0.1-0.20201128200927-a1889d947b48/go.mod h1:aXdIdfn2OcGnMhOTojXmwZqXKgC3MU5riiNvzwwG9OY= github.com/influxdata/httprouter v1.3.1-0.20191122104820-ee83e2772f69/go.mod h1:pwymjR6SrP3gD3pRj9RJwdl1j5s3doEEV8gS4X9qSzA= @@ -1207,8 +1388,9 @@ github.com/influxdata/influxdb v1.8.2/go.mod h1:SIzcnsjaHRFpmlxpJ4S3NT64qtEKYweN github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= github.com/influxdata/influxdb v1.8.4/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= github.com/influxdata/influxdb v1.9.2/go.mod h1:UEe3MeD9AaP5rlPIes102IhYua3FhIWZuOXNHxDjSrI= -github.com/influxdata/influxdb-client-go/v2 v2.2.3 h1:082jdJ5t1CFeo0rpGQvKAK1mONVSbFhL4finWA5bRM8= -github.com/influxdata/influxdb-client-go/v2 v2.2.3/go.mod h1:fa/d1lAdUHxuc1jedx30ZfNG573oQTQmUni3N6pcW+0= +github.com/influxdata/influxdb v1.9.3/go.mod h1:xD4ZjAgEJQO9/bX3NhFrssKtdNPi+ki1kjrttJRDhGc= +github.com/influxdata/influxdb-client-go/v2 v2.3.1-0.20210518120617-5d1fff431040 h1:MBLCfcSsUyFPDJp6T7EoHp/Ph3Jkrm4EuUKLD2rUWHg= +github.com/influxdata/influxdb-client-go/v2 v2.3.1-0.20210518120617-5d1fff431040/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxql v1.1.0/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo= @@ -1234,6 +1416,7 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/ github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= @@ -1253,6 +1436,7 @@ github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -1287,7 +1471,6 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= @@ -1324,6 +1507,7 @@ github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= @@ -1344,8 +1528,9 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.0.0/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= @@ -1360,6 +1545,7 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LE github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= +github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/laher/mergefs v0.1.1 h1:nV2bTS57vrmbMxeR6uvJpI8LyGl3QHj4bLBZO3aUV58= github.com/laher/mergefs v0.1.1/go.mod h1:FSY1hYy94on4Tz60waRMGdO1awwS23BacqJlqf9lJ9Q= @@ -1383,12 +1569,14 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/linkedin/goavro/v2 v2.10.0 h1:eTBIRoInBM88gITGXYtUSqqxLTFXfOsJBiX8ZMW0o4U= github.com/linkedin/goavro/v2 v2.10.0/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA= github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= -github.com/linode/linodego v0.28.5 h1:JaCziTxHJ7a01MYyjHqskRc8zXQxXOddwrDeoQ2rBnw= github.com/linode/linodego v0.28.5/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM= +github.com/linode/linodego v0.32.0 h1:IK04cx2b/IwAAd6XLruf1Dl/n3dRXj87Uw/5qo6afVU= +github.com/linode/linodego v0.32.0/go.mod h1:BR0gVkCJffEdIGJSl6bHR80Ty+Uvg/2jkjmrWaFectM= github.com/lovoo/gcloud-opentracing v0.3.0/go.mod h1:ZFqk2y38kMDDikZPAK7ynTTGuyt17nSPdS3K5e+ZTBY= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/iostat v1.1.0/go.mod h1:rEPNA0xXgjHQjuI5Cy05sLlS2oRcSlWHRLrvh/AQ+Pg= +github.com/lyft/protoc-gen-star v0.5.1/go.mod h1:9toiA3cC7z5uVbODF7kEQ91Xn7XNFkVUl+SrEe+ZORU= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/m3db/prometheus_remote_client_golang v0.4.4 h1:DsAIjVKoCp7Ym35tAOFL1OuMLIdIikAEHeNPHY+yyM8= github.com/m3db/prometheus_remote_client_golang v0.4.4/go.mod h1:wHfVbA3eAK6dQvKjCkHhusWYegCk3bDGkA15zymSHdc= @@ -1412,6 +1600,7 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= @@ -1424,6 +1613,7 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= @@ -1446,6 +1636,7 @@ github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= @@ -1454,8 +1645,9 @@ github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4f github.com/mattn/go-xmlrpc v0.0.3/go.mod h1:mqc2dz7tP5x5BKlCahN/n+hs7OSZKJkS9JsHNBRlrxA= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mdlayher/apcupsd v0.0.0-20200608131503-2bf01da7bf1b/go.mod h1:WYK/Z/aXq9cbMFIL5ihcA4sX/r/3/WCas/Qvs/2fXcA= github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= @@ -1476,8 +1668,10 @@ github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7 github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.38/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY= github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= @@ -1487,6 +1681,7 @@ github.com/minio/minio-go/v6 v6.0.56/go.mod h1:KQMM+/44DSlSGSQWSfRrAZ12FVMmpWNuX github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6JUMSQ2zAns= github.com/minio/minio-go/v7 v7.0.10/go.mod h1:td4gW1ldOsj1PbSNS+WYK43j+P1XVhX/8W8awaYlBFo= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= @@ -1510,6 +1705,7 @@ github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/pointerstructure v1.0.0/go.mod h1:k4XwG94++jLVsSiTxo7qdIfXA9pj9EAeo0QsNNJOLZ8= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -1518,7 +1714,12 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mjibson/esc v0.2.0/go.mod h1:9Hw9gxxfHulMF5OJKCyhYD7PzlSdhzXyaGEBRPH1OPs= github.com/mna/redisc v1.2.1 h1:7rI/qv2sa0OT8rsxDbKg7XPysr5AIDeXwL0T0vFOvlM= github.com/mna/redisc v1.2.1/go.mod h1:OxLEDNNDFOYJBo7MuSC+SEoP3k8bZY2dFW7T12TzX4c= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -1537,9 +1738,11 @@ github.com/mozillazg/go-cos v0.13.0/go.mod h1:Zp6DvvXn0RUOXGJ2chmWt2bLEqRAnJnS3D github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto= github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/multiplay/go-ts3 v1.0.0/go.mod h1:14S6cS3fLNT3xOytrA/DkRyAFNuQLMLEqOYAsf87IbQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1561,14 +1764,16 @@ github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1t github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/ncw/swift v1.0.50/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/ncw/swift v1.0.52/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/newrelic/newrelic-telemetry-sdk-go v0.2.0/go.mod h1:G9MqE/cHGv3Hx3qpYhfuyFUsGx2DpVcGi1iJIqTg+JQ= github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= @@ -1584,6 +1789,7 @@ github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FW github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic v6.2.35+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1594,8 +1800,10 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1604,15 +1812,34 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= +github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/openconfig/gnmi v0.0.0-20180912164834-33a1865c3029/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= github.com/opentracing-contrib/go-grpc v0.0.0-20180928155321-4b5a12d3ff02/go.mod h1:JNdpVEzCpXBgIiv4ds+TzhN1hrtxq6ClLrTlT9OQRSc= github.com/opentracing-contrib/go-grpc v0.0.0-20191001143057-db30781987df/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg= @@ -1646,6 +1873,7 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -1666,6 +1894,7 @@ github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982 h1:TdFv+3Gr3GaghJ/o80a github.com/pkg/browser v0.0.0-20210904010418-6d279e18f982/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1677,6 +1906,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/prometheus/alertmanager v0.18.0/go.mod h1:WcxHBl40VSPuOaqWae6l6HpnEOVRIycEJ7i9iYkadEE= @@ -1688,8 +1918,10 @@ github.com/prometheus/alertmanager v0.21.1-0.20201106142418-c39b78780054/go.mod github.com/prometheus/alertmanager v0.21.1-0.20210310093010-0f9cab6991e6/go.mod h1:MTqVn+vIupE0dzdgo+sMcNCp37SCAi8vPrvKTTnTz9g= github.com/prometheus/alertmanager v0.21.1-0.20210422101724-8176f78a70e1/go.mod h1:gsEqwD5BHHW9RNKvCuPOrrTMiP5I+faJUyLXvnivHik= github.com/prometheus/alertmanager v0.22.2/go.mod h1:rYinOWxFuCnNssc3iOjn2oMTlhLaPcUuqV5yk5JKUAE= -github.com/prometheus/alertmanager v0.23.0-rc.0.0.20210906104939-8da517524a87 h1:98dGpT8+lYi0ADl1oN/JHPbr5pyzSA9M4id68zFkh3Y= -github.com/prometheus/alertmanager v0.23.0-rc.0.0.20210906104939-8da517524a87/go.mod h1:U7pGu+z7A9ZKhK8lq1MvIOp5GdVlZjwOYk+S0h3LSbA= +github.com/prometheus/alertmanager v0.23.0/go.mod h1:0MLTrjQI8EuVmvykEhcfr/7X0xmaDAZrqMgxIq3OXHk= +github.com/prometheus/alertmanager v0.23.1-0.20210914172521-e35efbddb66a h1:qroc/F4ygaQ0uc2S+Pyk/exMwnSpokGyN1QjfZ1DiWU= +github.com/prometheus/alertmanager v0.23.1-0.20210914172521-e35efbddb66a/go.mod h1:U7pGu+z7A9ZKhK8lq1MvIOp5GdVlZjwOYk+S0h3LSbA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= @@ -1711,6 +1943,7 @@ github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3e github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1718,6 +1951,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= @@ -1750,12 +1984,14 @@ github.com/prometheus/exporter-toolkit v0.6.1 h1:Aqk75wQD92N9CqmTlZwjKwq6272nOGr github.com/prometheus/exporter-toolkit v0.6.1/go.mod h1:ZUBIj498ePooX9t/2xtDjeQYwvRpiPP2lh5u4iblj2g= github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289 h1:dTUS1vaLWq+Y6XKOTnrFpoVsQKLCbCp1OLj24TDi7oM= github.com/prometheus/node_exporter v1.0.0-rc.0.0.20200428091818-01054558c289/go.mod h1:FGbBv5OPKjch+jNUJmEQpMZytIdyW0NdBtWFcfSKusc= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190425082905-87a4384529e0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -1784,8 +2020,9 @@ github.com/prometheus/prometheus v1.8.2-0.20210215121130-6f488061dfb4/go.mod h1: github.com/prometheus/prometheus v1.8.2-0.20210315220929-1cba1741828b/go.mod h1:MS/bpdil77lPbfQeKk6OqVQ9OLnpN3Rszd0hka0EOWE= github.com/prometheus/prometheus v1.8.2-0.20210324152458-c7a62b95cea0/go.mod h1:sf7j/iAbhZahjeC0s3wwMmp5dksrJ/Za1UKdR+j6Hmw= github.com/prometheus/prometheus v1.8.2-0.20210421143221-52df5ef7a3be/go.mod h1:WbIKsp4vWCoPHis5qQfd0QimLOR7qe79roXN5O8U8bs= -github.com/prometheus/prometheus v1.8.2-0.20210621150501-ff58416a0b02 h1:waKRn/b6LBaXHjQ3dlZd+0li1nIykM34r5XEYr4lTBM= github.com/prometheus/prometheus v1.8.2-0.20210621150501-ff58416a0b02/go.mod h1:fC6ROpjS/2o+MQTO7X8NSZLhLBSNlDzxaeDMqQm+TUM= +github.com/prometheus/prometheus v1.8.2-0.20210915140241-bd217c58a735 h1:3g2VpIiQiSsxeppTZ4DTrQS3GV/bdE1x/vlHngEbDKs= +github.com/prometheus/prometheus v1.8.2-0.20210915140241-bd217c58a735/go.mod h1:02eURgmH1YsgJ2TtWNUGMQMCnLxmtHH9nOgvYxIjGAo= github.com/prometheus/statsd_exporter v0.20.0/go.mod h1:YL3FWCG8JBBtaUSxAg4Gz2ZYu22bS84XM89ZQXXTWmQ= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= @@ -1811,6 +2048,7 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= @@ -1819,8 +2057,9 @@ github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so= github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/russellhaering/goxmldsig v1.1.0 h1:lK/zeJie2sqG52ZAlPNn1oBBqsIsEKypUUBGpYYF6lk= github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o= +github.com/russellhaering/goxmldsig v1.1.1 h1:vI0r2osGF1A9PLvsGdPUAGwEIrKa4Pj5sesSBsebIxM= +github.com/russellhaering/goxmldsig v1.1.1/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -1829,6 +2068,7 @@ github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfF github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20190810000440-0ceca61e4d75/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= @@ -1847,6 +2087,7 @@ github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06q github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/securego/gosec v0.0.0-20200203094520-d13bb6d2420c/go.mod h1:gp0gaHj0WlmPh9BdsTmo1aq6C27yIPWdxCKGFGdVKBE= github.com/segmentio/encoding v0.2.19 h1:Kshkmoz080qvUtdtakR8Bjk2sIlLS8wSvijFMEHRGow= github.com/segmentio/encoding v0.2.19/go.mod h1:7E68jTSWMnNoYhHi1JbLd7NBSB6XfE4vzqhR88hDBQc= @@ -1876,6 +2117,7 @@ github.com/shurcooL/vfsgen v0.0.0-20200627165143-92b8a710ab6c/go.mod h1:TrYk7fJV github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745/go.mod h1:G81aIFAMS9ECrwBYR9YxhlPjWgrItd+Kje78O6+uqm8= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -1909,9 +2151,12 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.3.4/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -1921,6 +2166,7 @@ github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t6 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -1931,6 +2177,7 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spyzhov/ajson v0.4.2 h1:JMByd/jZApPKDvNsmO90X2WWGbmT2ahDFp73QhZbg3s= github.com/spyzhov/ajson v0.4.2/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/streadway/amqp v0.0.0-20180528204448-e5adc2ada8b8/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1938,12 +2185,14 @@ github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3 github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1953,7 +2202,11 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tbrandon/mbserver v0.0.0-20170611213546-993e1772cc62/go.mod h1:qUzPVlSj2UgxJkVbH0ZwuuiR46U8RBMDT5KLY78Ifpw= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tedsuo/ifrit v0.0.0-20191009134036-9a97d0632f00/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= github.com/tent/http-link-go v0.0.0-20130702225549-ac974c61c2f9/go.mod h1:RHkNRtSLfOK7qBTHaeSX1D6BNpI3qw7NTxsmNr4RvN8= @@ -2001,6 +2254,7 @@ github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.24.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.29.1+incompatible h1:R9ec3zO3sGpzs0abd43Y+fBZRJ9uiH6lXyR/+u6brW4= github.com/uber/jaeger-client-go v2.29.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.5.1-0.20181102163054-1fc5c315e03c/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= @@ -2014,9 +2268,11 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= @@ -2025,12 +2281,17 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vektra/mockery v0.0.0-20181123154057-e78b021dcbb5/go.mod h1:ppEjwdhyy7Y31EnHRDm1JkChoC7LXIJ7Ex0VYLWtZtQ= github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vjeantet/grok v1.0.0/go.mod h1:/FWYEVYekkm+2VjcFmO9PufDU5FgXHUz9oy2EGqmQBo= github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/govmomi v0.19.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= @@ -2047,6 +2308,8 @@ github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZG github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/wvanbergen/kafka v0.0.0-20171203153745-e2edea948ddf/go.mod h1:nxx7XRXbR9ykhnC8lXqQyJS0rfvJGxKyKw/sT1YOttg= github.com/wvanbergen/kazoo-go v0.0.0-20180202103751-f72d8611297a/go.mod h1:vQQATAGxVK20DC1rRubTJbZDDhhpA4QfU02pMdPxGO4= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= @@ -2060,6 +2323,7 @@ github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0 github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= @@ -2083,6 +2347,9 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/gopher-lua v0.0.0-20180630135845-46796da1b0b4/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU= github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zenazn/goji v0.9.1-0.20160507202103-64eb34159fe5/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= @@ -2102,6 +2369,7 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20190709142735-eb7dd97135a5/go.mod h1:N0RPWo9FXJYZQI4BTkDtQylrstIigYHeR18ONnyTufk= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200520232829-54ba9589114f/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= @@ -2127,6 +2395,7 @@ go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4S go.mongodb.org/mongo-driver v1.5.1/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= go.mongodb.org/mongo-driver v1.5.2 h1:AsxOLoJTgP6YNM0fXWw4OjdluYmWzQYp+lFJL7xu9fU= go.mongodb.org/mongo-driver v1.5.2/go.mod h1:gRXCHX4Jo7J0IJ1oDQyUxF7jfy19UfxniMS4xxMmUqw= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -2182,9 +2451,11 @@ go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2225,6 +2496,7 @@ golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -2284,7 +2556,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2292,6 +2563,7 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2310,6 +2582,7 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -2356,13 +2629,15 @@ golang.org/x/net v0.0.0-20210324051636-2c4c8ecb7826/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2381,8 +2656,9 @@ golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a h1:4Kd8OPUx1xgUwrHDaviWZO8MsgoZTZYC3g+8m16RBww= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2426,10 +2702,14 @@ golang.org/x/sys v0.0.0-20190425145619-16072639606e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2437,6 +2717,7 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2458,12 +2739,14 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2485,21 +2768,27 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201008064518-c1f3e3309c71/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2526,8 +2815,10 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -2634,6 +2925,7 @@ golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200513154647-78b527d18275/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200603131246-cc40288be839/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200612220849-54c614fe050c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -2652,6 +2944,7 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201119054027-25dc3e1ccc3c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201226215659-b1c90890d22a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -2682,6 +2975,7 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPj gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -2714,8 +3008,9 @@ google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59t google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0 h1:ECJUVngj71QI6XEm7b1sAf8BljU5inEhMbKPR8Lxhhk= google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.56.0 h1:08F9XVYTLOGeSQb3xI9C0gXMuQanhdGed0cWFhDozbI= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2727,6 +3022,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180608181217-32ee49c4dd80/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -2735,6 +3031,7 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= @@ -2748,6 +3045,7 @@ google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -2776,6 +3074,7 @@ google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2795,8 +3094,13 @@ google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+n google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67 h1:VmMSf20ssFK0+u1dscyTH9bU4/M4y+X/xNfkvD6kGtM= google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83 h1:3V2dxSZpz4zozWWUq36vUxXEKnSYitEH2LdsAx+RUmg= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -2858,6 +3162,7 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2897,10 +3202,10 @@ gopkg.in/ldap.v3 v3.1.0/go.mod h1:dQjCc0R0kfyFjIlWNMH1DORwUASZyDxo2Ry1B51dXaQ= gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/olivere/elastic.v5 v5.0.70/go.mod h1:FylZT6jQWtfHsicejzOm3jIMVPOAksa80i3o+6qtQRk= -gopkg.in/redis.v5 v5.2.9 h1:MNZYOLPomQzZMfpN3ZtD1uyJ2IDonTTlxYiV/pEApiw= -gopkg.in/redis.v5 v5.2.9/go.mod h1:6gtv0/+A4iM08kdRfocWYB3bLX2tebpNtfKlFT6H4mY= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -2952,8 +3257,11 @@ k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI= k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY= k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.5/go.mod h1:FQjAceXnVaWDeov2YUWhOb6Yt+5UjErkp6UO3nczO1Y= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s= k8s.io/api v0.22.1 h1:ISu3tD/jRhYfSW8jI/Q1e+lRxkR7w9UwQEZ7FgslrwY= @@ -2969,14 +3277,27 @@ k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCk k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.5/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/apimachinery v0.21.1/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= k8s.io/apimachinery v0.22.1 h1:DTARnyzmdHMz7bFWFDDm22AM4pLWTQECMpRTFu2d2OM= k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= k8s.io/client-go v0.22.1 h1:jW0ZSHi8wW260FvcXHkIa0NLxFBQszTlhiAVsU5mopw= k8s.io/client-go v0.22.1/go.mod h1:BquC5A4UOo4qVDUtoc04/+Nxp1MeHcVc1HJm1KmG8kk= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= @@ -2991,8 +3312,9 @@ k8s.io/klog/v2 v2.3.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.10.0 h1:R2HDMDJsHVTHA2n4RjwbeYXdOcBymXdX/JRb1v0VGhE= +k8s.io/klog/v2 v2.10.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20190722073852-5e22f3d471e6/go.mod h1:RZvgC8MSN6DjiMV6oIfEE9pDL9CYXokkfaCKZeHm3nc= k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= @@ -3003,9 +3325,11 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190809000727-6c36bc71fc4a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9 h1:imL9YgXQ9p7xmPzHFm/vVd/cF78jad+n4wK1ABwYtMM= k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= @@ -3019,6 +3343,8 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE= @@ -3026,6 +3352,7 @@ sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= diff --git a/latest.json b/latest.json index ab11b5dd853..832a4adae32 100644 --- a/latest.json +++ b/latest.json @@ -1,4 +1,4 @@ { - "stable": "8.1.4", + "stable": "8.1.5", "testing": "8.2.0-beta1" } diff --git a/lerna.json b/lerna.json index 62487c06fca..feff3a7f8d2 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "npmClient": "yarn", "useWorkspaces": true, "packages": ["packages/*"], - "version": "8.2.0-pre" + "version": "8.3.0-pre" } diff --git a/package.json b/package.json index 665f63b80e3..3ab1b04c9c4 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "license": "AGPL-3.0-only", "private": true, "name": "grafana", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "repository": "github:grafana/grafana", "scripts": { "api-tests": "jest --notify --watch --config=devenv/e2e-api-tests/jest.js", @@ -191,7 +191,7 @@ "mutationobserver-shim": "0.3.3", "ngtemplate-loader": "2.1.0", "nodemon": "2.0.2", - "pa11y-ci": "2.4.2", + "pa11y-ci": "pa11y/pa11y-ci#5c842cf1b9fe2867b70ff5354851d985be8d71c4", "postcss": "8.3.6", "postcss-loader": "6.1.1", "postcss-reporter": "7.0.2", @@ -213,8 +213,8 @@ "testing-library-selector": "^0.1.3", "ts-jest": "26.4.4", "ts-node": "9.0.0", - "tslib": "2.2.0", - "typescript": "4.3.4", + "tslib": "2.3.1", + "typescript": "4.4.3", "wait-on": "6.0.0", "webpack": "5.51.1", "webpack-bundle-analyzer": "4.4.2", @@ -222,8 +222,7 @@ "webpack-cli": "4.8.0", "webpack-dev-server": "4.0.0", "webpack-merge": "5.8.0", - "worker-loader": "^3.0.8", - "zone.js": "0.7.8" + "worker-loader": "^3.0.8" }, "dependencies": { "@emotion/css": "11.1.3", @@ -289,7 +288,7 @@ "ol": "6.7.0", "papaparse": "5.3.0", "pluralize": "^8.0.0", - "prismjs": "1.24.0", + "prismjs": "1.25.0", "prop-types": "15.7.2", "rc-cascader": "1.5.0", "re-resizable": "^6.2.0", @@ -328,7 +327,6 @@ "whatwg-fetch": "3.1.0" }, "resolutions": { - "caniuse-db": "1.0.30000772", "underscore": "1.12.1" }, "workspaces": { diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index ce0eac5e0ae..ecd4a35abbf 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/data", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana Data Library", "keywords": [ "typescript" @@ -23,7 +23,7 @@ }, "dependencies": { "@braintree/sanitize-url": "5.0.2", - "@grafana/schema": "8.2.0-pre", + "@grafana/schema": "8.3.0-pre", "@types/d3-interpolate": "^1.3.1", "date-fns": "2.21.3", "eventemitter3": "4.0.7", @@ -55,7 +55,7 @@ "rollup-plugin-visualizer": "4.2.0", "sinon": "8.1.1", "tinycolor2": "1.4.1", - "typescript": "4.3.4" + "typescript": "4.4.3" }, "volta": { "extends": "../../package.json" diff --git a/packages/grafana-data/src/panel/PanelPlugin.test.tsx b/packages/grafana-data/src/panel/PanelPlugin.test.tsx index 2e238e6af57..9b705d01fae 100644 --- a/packages/grafana-data/src/panel/PanelPlugin.test.tsx +++ b/packages/grafana-data/src/panel/PanelPlugin.test.tsx @@ -182,6 +182,27 @@ describe('PanelPlugin', () => { expect(panel.fieldConfigDefaults.defaults.custom).toEqual(expectedDefaults); }); + test('throw error with array fieldConfigs', () => { + const panel = new PanelPlugin(() => { + return
Panel
; + }); + + panel.useFieldConfig({ + useCustomConfig: (builder) => { + builder.addCustomEditor({ + id: 'somethingUnique', + path: 'numericOption[0]', + name: 'Option editor', + description: 'Option editor description', + defaultValue: 10, + } as any); + }, + }); + expect(() => panel.fieldConfigRegistry).toThrowErrorMatchingInlineSnapshot( + `"[undefined] Field config paths do not support arrays: custom.somethingUnique"` + ); + }); + test('default values for nested paths', () => { const panel = new PanelPlugin(() => { return
Panel
; diff --git a/packages/grafana-data/src/panel/registryFactories.ts b/packages/grafana-data/src/panel/registryFactories.ts index 7583df57e82..df811a35e20 100644 --- a/packages/grafana-data/src/panel/registryFactories.ts +++ b/packages/grafana-data/src/panel/registryFactories.ts @@ -75,6 +75,13 @@ export function createFieldConfigRegistry( } } + // assert that field configs do not use array path syntax + for (const item of registry.list()) { + if (item.path.indexOf('[') > 0) { + throw new Error(`[${pluginName}] Field config paths do not support arrays: ${item.id}`); + } + } + return registry; } diff --git a/packages/grafana-e2e-selectors/package.json b/packages/grafana-e2e-selectors/package.json index c1697d2e033..794ac85bcc8 100644 --- a/packages/grafana-e2e-selectors/package.json +++ b/packages/grafana-e2e-selectors/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e-selectors", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana End-to-End Test Selectors Library", "keywords": [ "cli", @@ -43,7 +43,7 @@ "@grafana/tsconfig": "^1.0.0-rc1", "commander": "5.0.0", "execa": "4.0.0", - "typescript": "4.3.4", + "typescript": "4.4.3", "yaml": "^1.8.3" }, "volta": { diff --git a/packages/grafana-e2e/cypress/plugins/typescriptPreprocessor.js b/packages/grafana-e2e/cypress/plugins/typescriptPreprocessor.js index ed596a1769c..8de33d53e2f 100644 --- a/packages/grafana-e2e/cypress/plugins/typescriptPreprocessor.js +++ b/packages/grafana-e2e/cypress/plugins/typescriptPreprocessor.js @@ -22,6 +22,9 @@ const webpackOptions = { use: [ { loader: 'ts-loader', + options: { + transpileOnly: true, + }, }, ], }, diff --git a/packages/grafana-e2e/package.json b/packages/grafana-e2e/package.json index 1831a8ddc73..64f23aefdd1 100644 --- a/packages/grafana-e2e/package.json +++ b/packages/grafana-e2e/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/e2e", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana End-to-End Test Library", "keywords": [ "cli", @@ -25,7 +25,7 @@ "clean": "rimraf ./dist ./compiled", "docsExtract": "mkdir -p ../../reports/docs && api-extractor run 2>&1 | tee ../../reports/docs/$(basename $(pwd)).log", "open": "cypress open", - "start": "cypress run --headless --browser chrome", + "start": "cypress run --browser=chrome", "test": "pushd test && node ../dist/bin/grafana-e2e.js run", "typecheck": "tsc --noEmit" }, @@ -44,18 +44,18 @@ }, "types": "src/index.ts", "dependencies": { - "@cypress/webpack-preprocessor": "5.9.0", - "@grafana/e2e-selectors": "8.2.0-pre", + "@cypress/webpack-preprocessor": "5.9.1", + "@grafana/e2e-selectors": "8.3.0-pre", "@grafana/tsconfig": "^1.0.0-rc1", "@mochajs/json-file-reporter": "^1.2.0", "blink-diff": "1.0.13", "commander": "5.0.0", - "cypress": "7.5.0", - "cypress-file-upload": "5.0.7", + "cypress": "8.4.1", + "cypress-file-upload": "5.0.8", "execa": "4.0.0", "resolve-as-bin": "2.1.0", "ts-loader": "6.2.1", - "typescript": "4.3.4", + "typescript": "4.4.3", "yaml": "^1.8.3" }, "volta": { diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index c05de015613..157bfade0c3 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/runtime", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana Runtime Library", "keywords": [ "grafana", @@ -22,9 +22,9 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@grafana/data": "8.2.0-pre", - "@grafana/e2e-selectors": "8.2.0-pre", - "@grafana/ui": "8.2.0-pre", + "@grafana/data": "8.3.0-pre", + "@grafana/e2e-selectors": "8.3.0-pre", + "@grafana/ui": "8.3.0-pre", "history": "4.10.1", "systemjs": "0.20.19", "systemjs-plugin-css": "0.1.37" @@ -44,7 +44,7 @@ "rollup-plugin-terser": "7.0.2", "rollup-plugin-typescript2": "0.29.0", "rollup-plugin-visualizer": "4.2.0", - "typescript": "4.3.4" + "typescript": "4.4.3" }, "types": "src/index.ts", "volta": { diff --git a/packages/grafana-schema/package.json b/packages/grafana-schema/package.json index b8336498d0d..bb102310f5d 100644 --- a/packages/grafana-schema/package.json +++ b/packages/grafana-schema/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/schema", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana Schema Library", "keywords": [ "typescript" @@ -33,7 +33,7 @@ "rollup-plugin-terser": "7.0.2", "rollup-plugin-typescript2": "0.29.0", "rollup-plugin-visualizer": "4.2.0", - "typescript": "4.3.4" + "typescript": "4.4.3" }, "volta": { "extends": "../../package.json" diff --git a/packages/grafana-schema/src/schema/graph.cue b/packages/grafana-schema/src/schema/graph.cue index 3a1d9f13d1f..c015e954f00 100644 --- a/packages/grafana-schema/src/schema/graph.cue +++ b/packages/grafana-schema/src/schema/graph.cue @@ -1,13 +1,12 @@ package schema AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(kind="enum") -PointVisibility: "auto" | "never" | "always" @cuetsy(kind="enum") +VisibilityMode: "auto" | "never" | "always" @cuetsy(kind="enum") DrawStyle: "line" | "bars" | "points" @cuetsy(kind="enum") LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(kind="enum") ScaleDistribution: "linear" | "log" @cuetsy(kind="enum") GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(kind="enum") StackingMode: "none" | "normal" | "percent" @cuetsy(kind="enum") -BarValueVisibility: "auto" | "never" | "always" @cuetsy(kind="enum") BarAlignment: -1 | 0 | 1 @cuetsy(kind="enum",memberNames="Before|Center|After") ScaleOrientation: 0 | 1 @cuetsy(kind="enum",memberNames="Horizontal|Vertical") ScaleDirection: 1 | 1 | -1 | -1 @cuetsy(kind="enum",memberNames="Up|Right|Down|Left") @@ -33,7 +32,7 @@ FillConfig: { fillBelowTo?: string } @cuetsy(kind="interface") PointsConfig: { - showPoints?: PointVisibility + showPoints?: VisibilityMode pointSize?: number pointColor?: string pointSymbol?: string diff --git a/packages/grafana-schema/src/schema/graph.gen.ts b/packages/grafana-schema/src/schema/graph.gen.ts index 081fb369005..fc38add7062 100644 --- a/packages/grafana-schema/src/schema/graph.gen.ts +++ b/packages/grafana-schema/src/schema/graph.gen.ts @@ -11,9 +11,9 @@ export enum AxisPlacement { Right = 'right', Top = 'top', } -export enum PointVisibility { - Always = 'always', +export enum VisibilityMode { Auto = 'auto', + Always = 'always', Never = 'never', } export enum GraphDrawStyle { @@ -45,12 +45,11 @@ export interface LineStyle { dash?: number[]; fill?: 'solid' | 'dash' | 'dot' | 'square'; } - export interface PointsConfig { pointColor?: string; pointSize?: number; pointSymbol?: string; - showPoints?: PointVisibility; + showPoints?: VisibilityMode; } export interface ScaleDistributionConfig { log?: number; @@ -71,15 +70,6 @@ export enum BarAlignment { After = 1, } -/** - * @alpha - */ -export enum BarValueVisibility { - Auto = 'auto', - Never = 'never', - Always = 'always', -} - /** * @alpha */ diff --git a/packages/grafana-toolkit/package.json b/packages/grafana-toolkit/package.json index c9981e4db3a..4dcd9b6943c 100644 --- a/packages/grafana-toolkit/package.json +++ b/packages/grafana-toolkit/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/toolkit", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana Toolkit", "keywords": [ "grafana", @@ -28,10 +28,10 @@ "dependencies": { "@babel/core": "7.13.14", "@babel/preset-env": "7.13.12", - "@grafana/data": "8.2.0-pre", + "@grafana/data": "8.3.0-pre", "@grafana/eslint-config": "2.5.0", "@grafana/tsconfig": "^1.0.0-rc1", - "@grafana/ui": "8.2.0-pre", + "@grafana/ui": "8.3.0-pre", "@types/command-exists": "^1.2.0", "@types/expect-puppeteer": "3.3.1", "@types/fs-extra": "^8.1.0", @@ -103,8 +103,8 @@ "ts-jest": "26.4.4", "ts-loader": "6.2.1", "ts-node": "9.0.0", - "tslib": "2.2.0", - "typescript": "4.3.4", + "tslib": "2.3.1", + "typescript": "4.4.3", "url-loader": "^2.0.1", "webpack": "4.41.5" }, diff --git a/packages/grafana-toolkit/src/cli/tasks/package.build.ts b/packages/grafana-toolkit/src/cli/tasks/package.build.ts index 0d72e4c2b2a..5e00ffb2f47 100644 --- a/packages/grafana-toolkit/src/cli/tasks/package.build.ts +++ b/packages/grafana-toolkit/src/cli/tasks/package.build.ts @@ -1,6 +1,5 @@ import execa = require('execa'); import { promises as fs } from 'fs'; -// @ts-ignore import * as path from 'path'; import chalk from 'chalk'; import { useSpinner } from '../utils/useSpinner'; diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts index 16a4c5d8086..eb880cd5c96 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.ci.ts @@ -2,8 +2,6 @@ import { Task, TaskRunner } from './task'; import { pluginBuildRunner } from './plugin.build'; import { getPluginJson } from '../../config/utils/pluginValidation'; import { getPluginId } from '../../config/utils/getPluginId'; - -// @ts-ignore import execa = require('execa'); import path = require('path'); import fs from 'fs-extra'; diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.dev.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.dev.ts index 34eeb0b93fc..7585bdf5956 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.dev.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.dev.ts @@ -2,8 +2,6 @@ import { Task, TaskRunner } from './task'; import { bundlePlugin as bundleFn, PluginBundleOptions } from './plugin/bundle'; import { useSpinner } from '../utils/useSpinner'; import { lintPlugin } from './plugin.build'; - -// @ts-ignore import execa = require('execa'); import path = require('path'); @@ -15,7 +13,7 @@ const yarnlink = () => try { // Make sure we are not using package.json defined toolkit await execa('yarn', ['remove', '@grafana/toolkit']); - } catch (e) { + } catch (e: any) { console.log('\n', e.message, '\n'); } await execa('yarn', ['link', '@grafana/toolkit']); diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin.utils.ts b/packages/grafana-toolkit/src/cli/tasks/plugin.utils.ts index 92940148274..2ffeabfc784 100755 --- a/packages/grafana-toolkit/src/cli/tasks/plugin.utils.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin.utils.ts @@ -5,8 +5,6 @@ import { getPluginId } from '../../config/utils/getPluginId'; import { getCiFolder } from '../../plugins/env'; import { useSpinner } from '../utils/useSpinner'; import path = require('path'); - -// @ts-ignore import execa = require('execa'); interface Command extends Array {} @@ -120,7 +118,7 @@ const prepareRelease = ({ dryrun, verbose }: any) => console.log('skipping empty line'); } } - } catch (ex) { + } catch (ex: any) { const err: string = ex.message; if (opts['okOnError'] && Array.isArray(opts['okOnError'])) { let trueError = true; diff --git a/packages/grafana-toolkit/src/cli/tasks/plugin/bundle.managed.ts b/packages/grafana-toolkit/src/cli/tasks/plugin/bundle.managed.ts index 2dafe879489..052c067a759 100644 --- a/packages/grafana-toolkit/src/cli/tasks/plugin/bundle.managed.ts +++ b/packages/grafana-toolkit/src/cli/tasks/plugin/bundle.managed.ts @@ -18,7 +18,7 @@ const bundleManagedPluginsRunner: TaskRunner = async () => console.log(`[${scope}]: ${plugin} building...`); await execa('yarn', ['build'], { cwd: `${MANAGED_PLUGINS_PATH}/${scope}/${plugin}` }); console.log(`[${scope}]: ${plugin} bundled`); - } catch (e) { + } catch (e: any) { console.log(e.stdout); } } diff --git a/packages/grafana-toolkit/src/cli/utils/githubRelease.ts b/packages/grafana-toolkit/src/cli/utils/githubRelease.ts index 54df0ffba9c..a63a5609b52 100644 --- a/packages/grafana-toolkit/src/cli/utils/githubRelease.ts +++ b/packages/grafana-toolkit/src/cli/utils/githubRelease.ts @@ -3,8 +3,6 @@ import { getPluginJson } from '../../config/utils/pluginValidation'; import { getCiFolder } from '../../plugins/env'; import path = require('path'); import fs = require('fs'); -// @ts-ignore -// import execa = require('execa'); import GithubClient from './githubClient'; import { AxiosResponse } from 'axios'; @@ -79,7 +77,7 @@ class GitHubRelease { if (latestRelease.data.tag_name === `v${pluginInfo.version}`) { await this.git.client.delete(`releases/${latestRelease.data.id}`); } - } catch (reason) { + } catch (reason: any) { if (reason.response.status !== 404) { // 404 just means no release found. Not an error. Anything else though, re throw the error throw reason; @@ -102,7 +100,7 @@ class GitHubRelease { `https://uploads.github.com/repos/${this.username}/${this.repository}/releases/${newReleaseResponse.data.id}/assets` ); await Promise.all(publishPromises); - } catch (reason) { + } catch (reason: any) { console.error(reason.data?.message ?? reason.response.data ?? reason); // Rethrow the error so that we can trigger a non-zero exit code to circle-ci throw reason; diff --git a/packages/grafana-toolkit/src/cli/utils/useSpinner.ts b/packages/grafana-toolkit/src/cli/utils/useSpinner.ts index a80df432f52..6ba94e330c2 100644 --- a/packages/grafana-toolkit/src/cli/utils/useSpinner.ts +++ b/packages/grafana-toolkit/src/cli/utils/useSpinner.ts @@ -6,7 +6,7 @@ export const useSpinner = async (label: string, fn: () => Promise, killProc try { await fn(); spinner.succeed(); - } catch (err) { + } catch (err: any) { spinner.fail(err.message || err); if (err.stdout) { diff --git a/packages/grafana-toolkit/src/config/webpack.plugin.config.ts b/packages/grafana-toolkit/src/config/webpack.plugin.config.ts index 9b1539a5acd..8f6a1809f80 100644 --- a/packages/grafana-toolkit/src/config/webpack.plugin.config.ts +++ b/packages/grafana-toolkit/src/config/webpack.plugin.config.ts @@ -274,7 +274,7 @@ export const loadWebpackConfig: WebpackConfigurationGetter = async (options) => ); } return (configGetter as CustomWebpackConfigurationGetter)(baseConfig, options); - } catch (err) { + } catch (err: any) { if (err.code === 'ENOENT') { return baseConfig; } diff --git a/packages/grafana-toolkit/src/plugins/manifest.ts b/packages/grafana-toolkit/src/plugins/manifest.ts index 66c5bff94f6..b06417df778 100644 --- a/packages/grafana-toolkit/src/plugins/manifest.ts +++ b/packages/grafana-toolkit/src/plugins/manifest.ts @@ -75,7 +75,7 @@ export async function signManifest(manifest: ManifestInfo): Promise { } return info.data; - } catch (err) { + } catch (err: any) { if ((err.response && err.response.data) || err.response.data.message) { throw new Error('Error signing manifest: ' + err.response.data.message); } diff --git a/packages/grafana-toolkit/tsconfig.json b/packages/grafana-toolkit/tsconfig.json index b6c80bdbb7f..76f8cf95687 100644 --- a/packages/grafana-toolkit/tsconfig.json +++ b/packages/grafana-toolkit/tsconfig.json @@ -4,7 +4,8 @@ "module": "commonjs", "outDir": "dist/src", "rootDirs": ["."], - "typeRoots": ["node_modules/@types"] + "typeRoots": ["node_modules/@types"], + "useUnknownInCatchVariables": false }, "exclude": ["dist", "node_modules"], "extends": "@grafana/tsconfig", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index e04e8067757..59d424676d8 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -2,7 +2,7 @@ "author": "Grafana Labs", "license": "Apache-2.0", "name": "@grafana/ui", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Grafana Components Library", "keywords": [ "grafana", @@ -33,9 +33,9 @@ "@emotion/css": "11.1.3", "@emotion/react": "11.1.5", "@grafana/aws-sdk": "0.0.3", - "@grafana/data": "8.2.0-pre", - "@grafana/e2e-selectors": "8.2.0-pre", - "@grafana/schema": "8.2.0-pre", + "@grafana/data": "8.3.0-pre", + "@grafana/e2e-selectors": "8.3.0-pre", + "@grafana/schema": "8.3.0-pre", "@grafana/slate-react": "0.22.10-grafana", "@grafana/tsconfig": "^1.0.0-rc1", "@monaco-editor/react": "4.2.2", @@ -83,10 +83,10 @@ "@storybook/addon-essentials": "6.3.7", "@storybook/addon-knobs": "6.3.0", "@storybook/addon-storysource": "6.3.7", - "@storybook/react": "6.3.7", - "@storybook/theming": "6.3.7", "@storybook/builder-webpack5": "6.3.7", "@storybook/manager-webpack5": "6.3.7", + "@storybook/react": "6.3.7", + "@storybook/theming": "6.3.7", "@testing-library/jest-dom": "5.11.9", "@types/classnames": "2.2.7", "@types/common-tags": "^1.8.0", @@ -124,7 +124,7 @@ "rollup-plugin-visualizer": "4.2.0", "storybook-dark-mode": "1.0.8", "ts-loader": "8.0.11", - "typescript": "4.3.4", + "typescript": "4.4.3", "webpack-filter-warnings-plugin": "1.2.1" }, "types": "src/index.ts", diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx index 340845b1436..307473a6924 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx @@ -4,6 +4,7 @@ import { DisplayValue, VizOrientation, ThresholdsMode, + FALLBACK_COLOR, Field, FieldType, getDisplayProcessor, @@ -12,6 +13,7 @@ import { import { BarGauge, Props, + getCellColor, getValueColor, getBasicAndGradientStyles, getBarGradient, @@ -74,6 +76,69 @@ function getValue(value: number, title?: string): DisplayValue { } describe('BarGauge', () => { + describe('getCellColor', () => { + it('returns a fallback if the positionValue is null', () => { + const props = getProps(); + expect(getCellColor(null, props.value, props.display)).toEqual({ + background: FALLBACK_COLOR, + border: FALLBACK_COLOR, + }); + }); + + it('does not show as lit if the value is null (somehow)', () => { + const props = getProps(); + expect(getCellColor(1, (null as unknown) as DisplayValue, props.display)).toEqual( + expect.objectContaining({ + isLit: false, + }) + ); + }); + + it('does not show as lit if the numeric value is NaN', () => { + const props = getProps(); + expect( + getCellColor( + 1, + { + numeric: NaN, + text: '0', + }, + props.display + ) + ).toEqual( + expect.objectContaining({ + isLit: false, + }) + ); + }); + + it('does not show as lit if the positionValue is greater than the numeric value', () => { + const props = getProps(); + expect(getCellColor(75, props.value, props.display)).toEqual( + expect.objectContaining({ + isLit: false, + }) + ); + }); + + it('shows as lit otherwise', () => { + const props = getProps(); + expect(getCellColor(1, props.value, props.display)).toEqual( + expect.objectContaining({ + isLit: true, + }) + ); + }); + + it('returns a fallback if there is no display processor', () => { + const props = getProps(); + expect(getCellColor(null, props.value, undefined)).toEqual({ + background: FALLBACK_COLOR, + border: FALLBACK_COLOR, + }); + }); + }); + describe('Get value color', () => { it('should get the threshold color if value is same as a threshold', () => { const props = getProps(); diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx index c196fd13544..8a444b61352 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx @@ -122,43 +122,8 @@ export class BarGauge extends PureComponent { ); } - getCellColor(positionValue: TimeSeriesValue): CellColors { - const { value, display } = this.props; - if (positionValue === null) { - return { - background: FALLBACK_COLOR, - border: FALLBACK_COLOR, - }; - } - - const color = display ? display(positionValue).color : null; - - if (color) { - // if we are past real value the cell is not "on" - if (value === null || (positionValue !== null && positionValue > value.numeric)) { - return { - background: tinycolor(color).setAlpha(0.18).toRgbString(), - border: 'transparent', - isLit: false, - }; - } else { - return { - background: tinycolor(color).setAlpha(0.95).toRgbString(), - backgroundShade: tinycolor(color).setAlpha(0.55).toRgbString(), - border: tinycolor(color).setAlpha(0.9).toRgbString(), - isLit: true, - }; - } - } - - return { - background: FALLBACK_COLOR, - border: FALLBACK_COLOR, - }; - } - renderRetroBars(): ReactNode { - const { field, value, itemSpacing, alignmentFactors, orientation, lcdCellWidth, text } = this.props; + const { display, field, value, itemSpacing, alignmentFactors, orientation, lcdCellWidth, text } = this.props; const { valueHeight, valueWidth, @@ -200,7 +165,7 @@ export class BarGauge extends PureComponent { for (let i = 0; i < cellCount; i++) { const currentValue = minValue + (valueRange / cellCount) * i; - const cellColor = this.getCellColor(currentValue); + const cellColor = getCellColor(currentValue, value, display); const cellStyles: CSSProperties = { borderRadius: '2px', }; @@ -425,6 +390,44 @@ export function calculateBarAndValueDimensions(props: Props): BarAndValueDimensi }; } +export function getCellColor( + positionValue: TimeSeriesValue, + value: Props['value'], + display: Props['display'] +): CellColors { + if (positionValue === null) { + return { + background: FALLBACK_COLOR, + border: FALLBACK_COLOR, + }; + } + + const color = display ? display(positionValue).color : null; + + if (color) { + // if we are past real value the cell is not "on" + if (value === null || isNaN(value.numeric) || (positionValue !== null && positionValue > value.numeric)) { + return { + background: tinycolor(color).setAlpha(0.18).toRgbString(), + border: 'transparent', + isLit: false, + }; + } else { + return { + background: tinycolor(color).setAlpha(0.95).toRgbString(), + backgroundShade: tinycolor(color).setAlpha(0.55).toRgbString(), + border: tinycolor(color).setAlpha(0.9).toRgbString(), + isLit: true, + }; + } + } + + return { + background: FALLBACK_COLOR, + border: FALLBACK_COLOR, + }; +} + export function getValuePercent(value: number, minValue: number, maxValue: number): number { return Math.min((value - minValue) / (maxValue - minValue), 1); } diff --git a/packages/grafana-ui/src/components/DataLinks/SelectionReference.ts b/packages/grafana-ui/src/components/DataLinks/SelectionReference.ts index fa6964f1ee5..725ec3f2ce4 100644 --- a/packages/grafana-ui/src/components/DataLinks/SelectionReference.ts +++ b/packages/grafana-ui/src/components/DataLinks/SelectionReference.ts @@ -1,4 +1,6 @@ -export class SelectionReference { +import { VirtualElement } from '@popperjs/core/lib/types'; + +export class SelectionReference implements VirtualElement { getBoundingClientRect() { const selection = window.getSelection(); const node = selection && selection.anchorNode; @@ -15,7 +17,7 @@ export class SelectionReference { right: 0, width: 0, height: 0, - }; + } as DOMRect; } get clientWidth() { diff --git a/packages/grafana-ui/src/components/GraphNG/utils.test.ts b/packages/grafana-ui/src/components/GraphNG/utils.test.ts index 49f99787583..7552cd1974f 100644 --- a/packages/grafana-ui/src/components/GraphNG/utils.test.ts +++ b/packages/grafana-ui/src/components/GraphNG/utils.test.ts @@ -18,7 +18,7 @@ import { GraphFieldConfig, GraphGradientMode, LineInterpolation, - PointVisibility, + VisibilityMode, StackingMode, } from '@grafana/schema'; @@ -48,7 +48,7 @@ function mockDataFrame() { spanNulls: false, fillColor: '#ff0000', fillOpacity: 0.1, - showPoints: PointVisibility.Always, + showPoints: VisibilityMode.Always, stacking: { group: 'A', mode: StackingMode.Normal, @@ -72,7 +72,7 @@ function mockDataFrame() { barAlignment: BarAlignment.Before, fillColor: '#ff0000', fillOpacity: 0.1, - showPoints: PointVisibility.Always, + showPoints: VisibilityMode.Always, stacking: { group: 'A', mode: StackingMode.Normal, @@ -96,7 +96,7 @@ function mockDataFrame() { spanNulls: false, fillColor: '#ff0000', fillOpacity: 0.1, - showPoints: PointVisibility.Always, + showPoints: VisibilityMode.Always, stacking: { group: 'B', mode: StackingMode.Normal, @@ -119,7 +119,7 @@ function mockDataFrame() { barAlignment: BarAlignment.Before, fillColor: '#ff0000', fillOpacity: 0.1, - showPoints: PointVisibility.Always, + showPoints: VisibilityMode.Always, stacking: { group: 'B', mode: StackingMode.Normal, @@ -142,7 +142,7 @@ function mockDataFrame() { barAlignment: BarAlignment.Before, fillColor: '#ff0000', fillOpacity: 0.1, - showPoints: PointVisibility.Always, + showPoints: VisibilityMode.Always, stacking: { group: 'B', mode: StackingMode.None, diff --git a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx index ddb1212f7be..e27106b301f 100644 --- a/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx +++ b/packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx @@ -125,6 +125,7 @@ const getStyles = (theme: GrafanaTheme2) => { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; + margin: 0; max-width: 240px; border-radius: 2px; diff --git a/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx b/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx index 8e36177fb0d..f6c16aec35f 100755 --- a/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx +++ b/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx @@ -13,7 +13,7 @@ import { AxisPlacement, GraphDrawStyle, GraphFieldConfig, - PointVisibility, + VisibilityMode, ScaleDirection, ScaleOrientation, } from '@grafana/schema'; @@ -39,7 +39,7 @@ interface State { const defaultConfig: GraphFieldConfig = { drawStyle: GraphDrawStyle.Line, - showPoints: PointVisibility.Auto, + showPoints: VisibilityMode.Auto, axisPlacement: AxisPlacement.Hidden, }; @@ -163,7 +163,7 @@ export class Sparkline extends PureComponent { const colorMode = getFieldColorModeForField(field); const seriesColor = colorMode.getCalculator(field, theme)(0, 0); const pointsMode = - customConfig.drawStyle === GraphDrawStyle.Points ? PointVisibility.Always : customConfig.showPoints; + customConfig.drawStyle === GraphDrawStyle.Points ? VisibilityMode.Always : customConfig.showPoints; builder.addSeries({ pxAlign: false, diff --git a/packages/grafana-ui/src/components/TimeSeries/utils.ts b/packages/grafana-ui/src/components/TimeSeries/utils.ts index ac66bbc39d6..0ccbdb7638e 100644 --- a/packages/grafana-ui/src/components/TimeSeries/utils.ts +++ b/packages/grafana-ui/src/components/TimeSeries/utils.ts @@ -20,7 +20,7 @@ import { GraphDrawStyle, GraphFieldConfig, GraphTresholdsStyleMode, - PointVisibility, + VisibilityMode, ScaleDirection, ScaleOrientation, } from '@grafana/schema'; @@ -31,7 +31,7 @@ const defaultFormatter = (v: any) => (v == null ? '-' : v.toFixed(1)); const defaultConfig: GraphFieldConfig = { drawStyle: GraphDrawStyle.Line, - showPoints: PointVisibility.Auto, + showPoints: VisibilityMode.Auto, axisPlacement: AxisPlacement.Auto, }; @@ -154,7 +154,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor } const showPoints = - customConfig.drawStyle === GraphDrawStyle.Points ? PointVisibility.Always : customConfig.showPoints; + customConfig.drawStyle === GraphDrawStyle.Points ? VisibilityMode.Always : customConfig.showPoints; let pointsFilter: uPlot.Series.Points.Filter = () => null; diff --git a/packages/grafana-ui/src/components/uPlot/config.ts b/packages/grafana-ui/src/components/uPlot/config.ts index 1dd825cf396..cb094c5eb2c 100644 --- a/packages/grafana-ui/src/components/uPlot/config.ts +++ b/packages/grafana-ui/src/components/uPlot/config.ts @@ -6,7 +6,7 @@ import { GraphGradientMode, GraphTresholdsStyleMode, LineInterpolation, - PointVisibility, + VisibilityMode, StackingMode, } from '@grafana/schema'; @@ -34,10 +34,10 @@ export const graphFieldOptions = { ] as Array>, showPoints: [ - { label: 'Auto', value: PointVisibility.Auto, description: 'Show points when the density is low' }, - { label: 'Always', value: PointVisibility.Always }, - { label: 'Never', value: PointVisibility.Never }, - ] as Array>, + { label: 'Auto', value: VisibilityMode.Auto, description: 'Show points when the density is low' }, + { label: 'Always', value: VisibilityMode.Always }, + { label: 'Never', value: VisibilityMode.Never }, + ] as Array>, axisPlacement: [ { label: 'Auto', value: AxisPlacement.Auto, description: 'First field on the left, everything else on the right' }, diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts index 57fc787fce7..50b93c34527 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts @@ -5,7 +5,7 @@ import { GraphGradientMode, AxisPlacement, GraphDrawStyle, - PointVisibility, + VisibilityMode, ScaleOrientation, ScaleDirection, GraphTresholdsStyleMode, @@ -479,7 +479,7 @@ describe('UPlotConfigBuilder', () => { scaleKey: 'scale-x', fillOpacity: 50, gradientMode: GraphGradientMode.Opacity, - showPoints: PointVisibility.Auto, + showPoints: VisibilityMode.Auto, pointSize: 5, lineColor: '#0000ff', lineWidth: 1, @@ -544,7 +544,7 @@ describe('UPlotConfigBuilder', () => { scaleKey: 'scale-x', fillOpacity: 50, gradientMode: GraphGradientMode.Opacity, - showPoints: PointVisibility.Auto, + showPoints: VisibilityMode.Auto, lineColor: '#0000ff', lineWidth: 1, spanNulls: false, @@ -555,7 +555,7 @@ describe('UPlotConfigBuilder', () => { scaleKey: 'scale-x', fillOpacity: 50, gradientMode: GraphGradientMode.Opacity, - showPoints: PointVisibility.Auto, + showPoints: VisibilityMode.Auto, pointSize: 5, lineColor: '#00ff00', lineWidth: 1, @@ -568,7 +568,7 @@ describe('UPlotConfigBuilder', () => { scaleKey: 'scale-x', fillOpacity: 50, gradientMode: GraphGradientMode.Opacity, - showPoints: PointVisibility.Auto, + showPoints: VisibilityMode.Auto, pointSize: 5, lineColor: '#ff0000', lineWidth: 1, diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts index c7cd5356d8f..c02e6c4cb84 100755 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts @@ -17,7 +17,7 @@ import { LineConfig, LineInterpolation, PointsConfig, - PointVisibility, + VisibilityMode, } from '@grafana/schema'; import { PlotConfigBuilder } from '../types'; import { getHueGradientFn, getOpacityGradientFn, getScaleGradientFn } from './gradientFills'; @@ -118,13 +118,13 @@ export class UPlotSeriesBuilder extends PlotConfigBuilder { if (drawStyle === GraphDrawStyle.Points) { pointsConfig.points!.show = true; } else { - if (showPoints === PointVisibility.Auto) { + if (showPoints === VisibilityMode.Auto) { if (drawStyle === GraphDrawStyle.Bars) { pointsConfig.points!.show = false; } - } else if (showPoints === PointVisibility.Never) { + } else if (showPoints === VisibilityMode.Never) { pointsConfig.points!.show = false; - } else if (showPoints === PointVisibility.Always) { + } else if (showPoints === VisibilityMode.Always) { pointsConfig.points!.show = true; } } diff --git a/packages/grafana-ui/src/schema.ts b/packages/grafana-ui/src/schema.ts index 6d86f1575bd..a9e03c4faec 100644 --- a/packages/grafana-ui/src/schema.ts +++ b/packages/grafana-ui/src/schema.ts @@ -7,7 +7,7 @@ export { GraphDrawStyle as DrawStyle, // All exports AxisPlacement, - PointVisibility, + VisibilityMode as PointVisibility, LineInterpolation, ScaleDistribution, GraphGradientMode, @@ -16,7 +16,7 @@ export { ScaleDistributionConfig, HideSeriesConfig, BarAlignment, - BarValueVisibility, + VisibilityMode as BarValueVisibility, ScaleOrientation, ScaleDirection, LineConfig, diff --git a/packages/jaeger-ui-components/package.json b/packages/jaeger-ui-components/package.json index 5e523e62d67..14dcd78a14d 100644 --- a/packages/jaeger-ui-components/package.json +++ b/packages/jaeger-ui-components/package.json @@ -1,6 +1,6 @@ { "name": "@jaegertracing/jaeger-ui-components", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,13 +11,13 @@ "devDependencies": { "@wojtekmaj/enzyme-adapter-react-17": "0.6.2", "enzyme": "3.11.0", - "typescript": "4.3.4" + "typescript": "4.4.3" }, "dependencies": { "@emotion/css": "11.1.3", "@emotion/react": "11.1.5", - "@grafana/data": "8.2.0-pre", - "@grafana/ui": "8.2.0-pre", + "@grafana/data": "8.3.0-pre", + "@grafana/ui": "8.3.0-pre", "@types/classnames": "^2.2.7", "@types/deep-freeze": "^0.1.1", "@types/hoist-non-react-statics": "^3.3.1", diff --git a/pkg/api/acl.go b/pkg/api/acl.go index 6c839a2f11a..eae0cf21aeb 100644 --- a/pkg/api/acl.go +++ b/pkg/api/acl.go @@ -1,10 +1,15 @@ package api -import "github.com/grafana/grafana/pkg/models" +import ( + "context" + + "github.com/grafana/grafana/pkg/dashboards" + "github.com/grafana/grafana/pkg/models" +) // updateDashboardACL updates a dashboard's ACL items. // // Stubbable by tests. -var updateDashboardACL = func(hs *HTTPServer, dashID int64, items []*models.DashboardAcl) error { - return hs.SQLStore.UpdateDashboardACL(dashID, items) +var updateDashboardACL = func(ctx context.Context, s dashboards.Store, dashID int64, items []*models.DashboardAcl) error { + return s.UpdateDashboardACLCtx(ctx, dashID, items) } diff --git a/pkg/api/alerting.go b/pkg/api/alerting.go index e4181509df0..f2469eac478 100644 --- a/pkg/api/alerting.go +++ b/pkg/api/alerting.go @@ -462,7 +462,7 @@ func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) response.Respo return response.Error(500, "Get Alert failed", err) } - guardian := guardian.New(query.Result.DashboardId, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), query.Result.DashboardId, c.OrgId, c.SignedInUser) if canEdit, err := guardian.CanEdit(); err != nil || !canEdit { if err != nil { return response.Error(500, "Error while checking permissions for Alert", err) diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go index cb3154e19dc..031fd55f2ca 100644 --- a/pkg/api/annotations.go +++ b/pkg/api/annotations.go @@ -265,7 +265,7 @@ func canSaveByDashboardID(c *models.ReqContext, dashboardID int64) (bool, error) } if dashboardID != 0 { - guard := guardian.New(dashboardID, c.OrgId, c.SignedInUser) + guard := guardian.New(c.Req.Context(), dashboardID, c.OrgId, c.SignedInUser) if canEdit, err := guard.CanEdit(); err != nil || !canEdit { return false, err } diff --git a/pkg/api/api.go b/pkg/api/api.go index 6a2ceeb76e6..4407325af89 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -53,9 +53,9 @@ func (hs *HTTPServer) registerRoutes() { r.Get("/profile/switch-org/:id", reqSignedInNoAnonymous, hs.ChangeActiveOrgAndRedirectToHome) r.Get("/org/", reqOrgAdmin, hs.Index) r.Get("/org/new", reqGrafanaAdmin, hs.Index) - r.Get("/datasources/", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesRead)), hs.Index) - r.Get("/datasources/new", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesCreate)), hs.Index) - r.Get("/datasources/edit/*", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesRead)), hs.Index) + r.Get("/datasources/", authorize(reqOrgAdmin, dataSourcesConfigurationAccessEvaluator), hs.Index) + r.Get("/datasources/new", authorize(reqOrgAdmin, dataSourcesNewAccessEvaluator), hs.Index) + r.Get("/datasources/edit/*", authorize(reqOrgAdmin, dataSourcesEditAccessEvaluator), hs.Index) r.Get("/org/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), hs.Index) r.Get("/org/users/new", reqOrgAdmin, hs.Index) r.Get("/org/users/invite", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), hs.Index) @@ -438,6 +438,7 @@ func (hs *HTTPServer) registerRoutes() { // POST Live data to be processed according to channel rules. liveRoute.Post("/push/:streamId/:path", hs.LivePushGateway.HandlePath) liveRoute.Get("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesListHTTP), reqOrgAdmin) + liveRoute.Get("/pipeline-entities", routing.Wrap(hs.Live.HandlePipelineEntitiesListHTTP), reqOrgAdmin) liveRoute.Get("/remote-write-backends", routing.Wrap(hs.Live.HandleRemoteWriteBackendsListHTTP), reqOrgAdmin) } }) diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index bd4744aa781..ca4e8dc0df3 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -91,7 +91,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response { } } - guardian := guardian.New(dash.Id, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), dash.Id, c.OrgId, c.SignedInUser) if canView, err := guardian.CanView(); err != nil || !canView { return dashboardGuardianResponse(err) } @@ -175,7 +175,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response { dash.Data.Set("version", dash.Version) // load library panels JSON for this dashboard - err = hs.LibraryPanelService.LoadLibraryPanelsForDashboard(c, dash) + err = hs.LibraryPanelService.LoadLibraryPanelsForDashboard(c.Req.Context(), dash) if err != nil { return response.Error(500, "Error while loading library panels", err) } @@ -238,13 +238,13 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response { return rsp } - guardian := guardian.New(dash.Id, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), dash.Id, c.OrgId, c.SignedInUser) if canSave, err := guardian.CanSave(); err != nil || !canSave { return dashboardGuardianResponse(err) } // disconnect all library elements for this dashboard - err := hs.LibraryElementService.DisconnectElementsFromDashboard(c, dash.Id) + err := hs.LibraryElementService.DisconnectElementsFromDashboard(c.Req.Context(), dash.Id) if err != nil { hs.log.Error("Failed to disconnect library elements", "dashboard", dash.Id, "user", c.SignedInUser.UserId, "error", err) } @@ -370,7 +370,7 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa } // connect library panels for this dashboard after the dashboard is stored and has an ID - err = hs.LibraryPanelService.ConnectLibraryPanelsForDashboard(c, dashboard) + err = hs.LibraryPanelService.ConnectLibraryPanelsForDashboard(c.Req.Context(), c.SignedInUser, dashboard) if err != nil { return response.Error(500, "Error while connecting library panels", err) } @@ -508,7 +508,7 @@ func (hs *HTTPServer) addGettingStartedPanelToHomeDashboard(c *models.ReqContext func GetDashboardVersions(c *models.ReqContext) response.Response { dashID := c.ParamsInt64(":dashboardId") - guardian := guardian.New(dashID, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), dashID, c.OrgId, c.SignedInUser) if canSave, err := guardian.CanSave(); err != nil || !canSave { return dashboardGuardianResponse(err) } @@ -547,7 +547,7 @@ func GetDashboardVersions(c *models.ReqContext) response.Response { func GetDashboardVersion(c *models.ReqContext) response.Response { dashID := c.ParamsInt64(":dashboardId") - guardian := guardian.New(dashID, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), dashID, c.OrgId, c.SignedInUser) if canSave, err := guardian.CanSave(); err != nil || !canSave { return dashboardGuardianResponse(err) } @@ -584,13 +584,13 @@ func GetDashboardVersion(c *models.ReqContext) response.Response { // POST /api/dashboards/calculate-diff performs diffs on two dashboards func CalculateDashboardDiff(c *models.ReqContext, apiOptions dtos.CalculateDiffOptions) response.Response { - guardianBase := guardian.New(apiOptions.Base.DashboardId, c.OrgId, c.SignedInUser) + guardianBase := guardian.New(c.Req.Context(), apiOptions.Base.DashboardId, c.OrgId, c.SignedInUser) if canSave, err := guardianBase.CanSave(); err != nil || !canSave { return dashboardGuardianResponse(err) } if apiOptions.Base.DashboardId != apiOptions.New.DashboardId { - guardianNew := guardian.New(apiOptions.New.DashboardId, c.OrgId, c.SignedInUser) + guardianNew := guardian.New(c.Req.Context(), apiOptions.New.DashboardId, c.OrgId, c.SignedInUser) if canSave, err := guardianNew.CanSave(); err != nil || !canSave { return dashboardGuardianResponse(err) } @@ -633,7 +633,7 @@ func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext, apiCmd dtos. return rsp } - guardian := guardian.New(dash.Id, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), dash.Id, c.OrgId, c.SignedInUser) if canSave, err := guardian.CanSave(); err != nil || !canSave { return dashboardGuardianResponse(err) } diff --git a/pkg/api/dashboard_permission.go b/pkg/api/dashboard_permission.go index 4867d68e41c..c32339cf931 100644 --- a/pkg/api/dashboard_permission.go +++ b/pkg/api/dashboard_permission.go @@ -18,7 +18,7 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response. return rsp } - g := guardian.New(dashID, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), dashID, c.OrgId, c.SignedInUser) if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin { return dashboardGuardianResponse(err) @@ -62,7 +62,7 @@ func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dt return rsp } - g := guardian.New(dashID, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), dashID, c.OrgId, c.SignedInUser) if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin { return dashboardGuardianResponse(err) } @@ -99,7 +99,7 @@ func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dt return response.Error(403, "Cannot remove own admin permission for a folder", nil) } - if err := updateDashboardACL(hs, dashID, items); err != nil { + if err := updateDashboardACL(c.Req.Context(), hs.SQLStore, dashID, items); err != nil { if errors.Is(err, models.ErrDashboardAclInfoMissing) || errors.Is(err, models.ErrDashboardPermissionDashboardEmpty) { return response.Error(409, err.Error(), err) diff --git a/pkg/api/dashboard_permission_test.go b/pkg/api/dashboard_permission_test.go index 93e148a6148..9ff803230a9 100644 --- a/pkg/api/dashboard_permission_test.go +++ b/pkg/api/dashboard_permission_test.go @@ -6,15 +6,17 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/dashboards" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/setting" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestDashboardPermissionAPIEndpoint(t *testing.T) { @@ -342,7 +344,7 @@ func TestDashboardPermissionAPIEndpoint(t *testing.T) { updateDashboardACL = origUpdateDashboardACL }) var gotItems []*models.DashboardAcl - updateDashboardACL = func(hs *HTTPServer, folderID int64, items []*models.DashboardAcl) error { + updateDashboardACL = func(_ context.Context, _ dashboards.Store, folderID int64, items []*models.DashboardAcl) error { gotItems = items return nil } @@ -368,7 +370,7 @@ func callUpdateDashboardPermissions(t *testing.T, sc *scenarioContext) { t.Cleanup(func() { updateDashboardACL = origUpdateDashboardACL }) - updateDashboardACL = func(hs *HTTPServer, dashID int64, items []*models.DashboardAcl) error { + updateDashboardACL = func(_ context.Context, _ dashboards.Store, dashID int64, items []*models.DashboardAcl) error { return nil } diff --git a/pkg/api/dashboard_snapshot.go b/pkg/api/dashboard_snapshot.go index b108a0b1141..434e85a46c4 100644 --- a/pkg/api/dashboard_snapshot.go +++ b/pkg/api/dashboard_snapshot.go @@ -254,7 +254,7 @@ func DeleteDashboardSnapshot(c *models.ReqContext) response.Response { dashboardID := query.Result.Dashboard.Get("id").MustInt64() - guardian := guardian.New(dashboardID, c.OrgId, c.SignedInUser) + guardian := guardian.New(c.Req.Context(), dashboardID, c.OrgId, c.SignedInUser) canEdit, err := guardian.CanEdit() if err != nil { return response.Error(500, "Error while checking permissions for snapshot", err) diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index ce80c2c137a..2e8f4fb1cf0 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -16,6 +16,7 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" dboards "github.com/grafana/grafana/pkg/dashboards" + "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/dashboards" @@ -86,9 +87,37 @@ type testState struct { dashQueries []*models.GetDashboardQuery } +type usageStatsMock struct { + t *testing.T + metricsFuncs []usagestats.MetricsFunc +} + +func (usm *usageStatsMock) RegisterMetricsFunc(fn usagestats.MetricsFunc) { + usm.metricsFuncs = append(usm.metricsFuncs, fn) +} + +func (usm *usageStatsMock) GetUsageReport(_ context.Context) (usagestats.Report, error) { + all := make(map[string]interface{}) + for _, fn := range usm.metricsFuncs { + fnMetrics, err := fn() + require.NoError(usm.t, err) + + for name, value := range fnMetrics { + all[name] = value + } + } + return usagestats.Report{Metrics: all}, nil +} + +func (usm *usageStatsMock) ShouldBeReported(_ string) bool { + return true +} + +func (usm *usageStatsMock) RegisterSendReportCallback(_ usagestats.SendReportCallbackFunc) {} + func newTestLive(t *testing.T) *live.GrafanaLive { cfg := &setting.Cfg{AppURL: "http://localhost:3000/"} - gLive, err := live.ProvideService(nil, cfg, routing.NewRouteRegister(), nil, nil, nil, nil, sqlstore.InitTestDB(t)) + gLive, err := live.ProvideService(nil, cfg, routing.NewRouteRegister(), nil, nil, nil, nil, sqlstore.InitTestDB(t), &usageStatsMock{t: t}) require.NoError(t, err) return gLive } @@ -1233,7 +1262,7 @@ func (s mockDashboardProvisioningService) GetProvisionedDashboardDataByDashboard type mockLibraryPanelService struct { } -func (m *mockLibraryPanelService) LoadLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard) error { +func (m *mockLibraryPanelService) LoadLibraryPanelsForDashboard(c context.Context, dash *models.Dashboard) error { return nil } @@ -1241,42 +1270,42 @@ func (m *mockLibraryPanelService) CleanLibraryPanelsForDashboard(dash *models.Da return nil } -func (m *mockLibraryPanelService) ConnectLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard) error { +func (m *mockLibraryPanelService) ConnectLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard) error { return nil } -func (m *mockLibraryPanelService) ImportLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard, folderID int64) error { +func (m *mockLibraryPanelService) ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard, folderID int64) error { return nil } type mockLibraryElementService struct { } -func (l *mockLibraryElementService) CreateElement(c *models.ReqContext, cmd libraryelements.CreateLibraryElementCommand) (libraryelements.LibraryElementDTO, error) { +func (l *mockLibraryElementService) CreateElement(c context.Context, signedInUser *models.SignedInUser, cmd libraryelements.CreateLibraryElementCommand) (libraryelements.LibraryElementDTO, error) { return libraryelements.LibraryElementDTO{}, nil } // GetElement gets an element from a UID. -func (l *mockLibraryElementService) GetElement(c *models.ReqContext, UID string) (libraryelements.LibraryElementDTO, error) { +func (l *mockLibraryElementService) GetElement(c context.Context, signedInUser *models.SignedInUser, UID string) (libraryelements.LibraryElementDTO, error) { return libraryelements.LibraryElementDTO{}, nil } // GetElementsForDashboard gets all connected elements for a specific dashboard. -func (l *mockLibraryElementService) GetElementsForDashboard(c *models.ReqContext, dashboardID int64) (map[string]libraryelements.LibraryElementDTO, error) { +func (l *mockLibraryElementService) GetElementsForDashboard(c context.Context, dashboardID int64) (map[string]libraryelements.LibraryElementDTO, error) { return map[string]libraryelements.LibraryElementDTO{}, nil } // ConnectElementsToDashboard connects elements to a specific dashboard. -func (l *mockLibraryElementService) ConnectElementsToDashboard(c *models.ReqContext, elementUIDs []string, dashboardID int64) error { +func (l *mockLibraryElementService) ConnectElementsToDashboard(c context.Context, signedInUser *models.SignedInUser, elementUIDs []string, dashboardID int64) error { return nil } // DisconnectElementsFromDashboard disconnects elements from a specific dashboard. -func (l *mockLibraryElementService) DisconnectElementsFromDashboard(c *models.ReqContext, dashboardID int64) error { +func (l *mockLibraryElementService) DisconnectElementsFromDashboard(c context.Context, dashboardID int64) error { return nil } // DeleteLibraryElementsInFolder deletes all elements for a specific folder. -func (l *mockLibraryElementService) DeleteLibraryElementsInFolder(c *models.ReqContext, folderUID string) error { +func (l *mockLibraryElementService) DeleteLibraryElementsInFolder(c context.Context, signedInUser *models.SignedInUser, folderUID string) error { return nil } diff --git a/pkg/api/folder.go b/pkg/api/folder.go index d6e4e60d3c9..fa3543041cb 100644 --- a/pkg/api/folder.go +++ b/pkg/api/folder.go @@ -44,7 +44,7 @@ func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response { return apierrors.ToFolderErrorResponse(err) } - g := guardian.New(folder.Id, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser) return response.JSON(200, toFolderDto(c.Req.Context(), g, folder)) } @@ -55,7 +55,7 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response { return apierrors.ToFolderErrorResponse(err) } - g := guardian.New(folder.Id, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser) return response.JSON(200, toFolderDto(c.Req.Context(), g, folder)) } @@ -73,7 +73,7 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolder } } - g := guardian.New(folder.Id, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser) return response.JSON(200, toFolderDto(c.Req.Context(), g, folder)) } @@ -84,13 +84,13 @@ func (hs *HTTPServer) UpdateFolder(c *models.ReqContext, cmd models.UpdateFolder return apierrors.ToFolderErrorResponse(err) } - g := guardian.New(cmd.Result.Id, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), cmd.Result.Id, c.OrgId, c.SignedInUser) return response.JSON(200, toFolderDto(c.Req.Context(), g, cmd.Result)) } func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { // temporarily adding this function to HTTPServer, will be removed from HTTPServer when librarypanels featuretoggle is removed s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore) - err := hs.LibraryElementService.DeleteLibraryElementsInFolder(c, macaron.Params(c.Req)[":uid"]) + err := hs.LibraryElementService.DeleteLibraryElementsInFolder(c.Req.Context(), c.SignedInUser, macaron.Params(c.Req)[":uid"]) if err != nil { if errors.Is(err, libraryelements.ErrFolderHasConnectedLibraryElements) { return response.Error(403, "Folder could not be deleted because it contains library elements in use", err) diff --git a/pkg/api/folder_permission.go b/pkg/api/folder_permission.go index 2f5e68faef2..aa6fa4736a6 100644 --- a/pkg/api/folder_permission.go +++ b/pkg/api/folder_permission.go @@ -4,6 +4,8 @@ import ( "errors" "time" + macaron "gopkg.in/macaron.v1" + "github.com/grafana/grafana/pkg/api/apierrors" "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/response" @@ -11,7 +13,6 @@ import ( "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/util" - macaron "gopkg.in/macaron.v1" ) func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Response { @@ -22,7 +23,7 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res return apierrors.ToFolderErrorResponse(err) } - g := guardian.New(folder.Id, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser) if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin { return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied) @@ -69,7 +70,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos. return apierrors.ToFolderErrorResponse(err) } - g := guardian.New(folder.Id, c.OrgId, c.SignedInUser) + g := guardian.New(c.Req.Context(), folder.Id, c.OrgId, c.SignedInUser) canAdmin, err := g.CanAdmin() if err != nil { return apierrors.ToFolderErrorResponse(err) @@ -112,7 +113,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos. return response.Error(403, "Cannot remove own admin permission for a folder", nil) } - if err := updateDashboardACL(hs, folder.Id, items); err != nil { + if err := updateDashboardACL(c.Req.Context(), hs.SQLStore, folder.Id, items); err != nil { if errors.Is(err, models.ErrDashboardAclInfoMissing) { err = models.ErrFolderAclInfoMissing } diff --git a/pkg/api/folder_permission_test.go b/pkg/api/folder_permission_test.go index bcbcbeb4b5a..e5eee71ce06 100644 --- a/pkg/api/folder_permission_test.go +++ b/pkg/api/folder_permission_test.go @@ -1,20 +1,23 @@ package api import ( + "context" "encoding/json" "fmt" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/bus" + dashboardifaces "github.com/grafana/grafana/pkg/dashboards" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/setting" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestFolderPermissionAPIEndpoint(t *testing.T) { @@ -360,7 +363,7 @@ func TestFolderPermissionAPIEndpoint(t *testing.T) { updateDashboardACL = origUpdateDashboardACL }) var gotItems []*models.DashboardAcl - updateDashboardACL = func(hs *HTTPServer, dashID int64, items []*models.DashboardAcl) error { + updateDashboardACL = func(_ context.Context, _ dashboardifaces.Store, _ int64, items []*models.DashboardAcl) error { gotItems = items return nil } @@ -385,7 +388,7 @@ func callUpdateFolderPermissions(t *testing.T, sc *scenarioContext) { t.Cleanup(func() { updateDashboardACL = origUpdateDashboardACL }) - updateDashboardACL = func(hs *HTTPServer, dashID int64, items []*models.DashboardAcl) error { + updateDashboardACL = func(_ context.Context, _ dashboardifaces.Store, dashID int64, items []*models.DashboardAcl) error { return nil } diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 1c924157425..c4ef2218760 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -22,7 +22,6 @@ import ( "github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/infra/remotecache" "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/login/social" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/models" @@ -68,7 +67,6 @@ type HTTPServer struct { httpSrv *http.Server middlewares []macaron.Handler - UsageStatsService usagestats.UsageStats PluginContextProvider *plugincontext.Provider RouteRegister routing.RouteRegister Bus bus.Bus @@ -118,8 +116,7 @@ type ServerOptions struct { func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routing.RouteRegister, bus bus.Bus, renderService rendering.Service, licensing models.Licensing, hooksService *hooks.HooksService, cacheService *localcache.CacheService, sqlStore *sqlstore.SQLStore, - dataService *tsdb.Service, alertEngine *alerting.AlertEngine, - usageStatsService *usagestats.UsageStatsService, pluginRequestValidator models.PluginRequestValidator, + dataService *tsdb.Service, alertEngine *alerting.AlertEngine, pluginRequestValidator models.PluginRequestValidator, pluginManager plugins.Manager, backendPM backendplugin.Manager, settingsProvider setting.Provider, dataSourceCache datasources.CacheService, userTokenService models.UserTokenService, cleanUpService *cleanup.CleanUpService, shortURLService shorturls.Service, @@ -148,7 +145,6 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi SQLStore: sqlStore, DataService: dataService, AlertEngine: alertEngine, - UsageStatsService: usageStatsService, PluginRequestValidator: pluginRequestValidator, PluginManager: pluginManager, BackendPluginManager: backendPM, diff --git a/pkg/api/index.go b/pkg/api/index.go index c039bb9e941..e86521fac93 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -18,16 +18,6 @@ const ( darkName = "dark" ) -// dataSourcesConfigurationAccessEvaluator is used to protect the "Configure > Data sources" tab access -var dataSourcesConfigurationAccessEvaluator = ac.EvalAll( - ac.EvalPermission(ActionDatasourcesRead, ScopeDatasourcesAll), - ac.EvalAny( - ac.EvalPermission(ActionDatasourcesCreate), - ac.EvalPermission(ActionDatasourcesDelete), - ac.EvalPermission(ActionDatasourcesWrite), - ), -) - func (hs *HTTPServer) getProfileNode(c *models.ReqContext) *dtos.NavLink { // Only set login if it's different from the name var login string diff --git a/pkg/api/plugins.go b/pkg/api/plugins.go index 5d0cadaa1fe..a99dd4e508a 100644 --- a/pkg/api/plugins.go +++ b/pkg/api/plugins.go @@ -224,12 +224,12 @@ func (hs *HTTPServer) ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDa return hs.dashboardSaveErrorToApiResponse(err) } - err = hs.LibraryPanelService.ImportLibraryPanelsForDashboard(c, dash, apiCmd.FolderId) + err = hs.LibraryPanelService.ImportLibraryPanelsForDashboard(c.Req.Context(), c.SignedInUser, dash, apiCmd.FolderId) if err != nil { return response.Error(500, "Error while importing library panels", err) } - err = hs.LibraryPanelService.ConnectLibraryPanelsForDashboard(c, dash) + err = hs.LibraryPanelService.ConnectLibraryPanelsForDashboard(c.Req.Context(), c.SignedInUser, dash) if err != nil { return response.Error(500, "Error while connecting library panels", err) } diff --git a/pkg/api/quota.go b/pkg/api/quota.go index c78626c4ea1..9f0ff492fd1 100644 --- a/pkg/api/quota.go +++ b/pkg/api/quota.go @@ -14,7 +14,7 @@ func GetOrgQuotas(c *models.ReqContext) response.Response { } query := models.GetOrgQuotasQuery{OrgId: c.ParamsInt64(":orgId")} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to get org quotas", err) } @@ -32,7 +32,7 @@ func UpdateOrgQuota(c *models.ReqContext, cmd models.UpdateOrgQuotaCmd) response return response.Error(404, "Invalid quota target", nil) } - if err := bus.Dispatch(&cmd); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &cmd); err != nil { return response.Error(500, "Failed to update org quotas", err) } return response.Success("Organization quota updated") @@ -44,7 +44,7 @@ func GetUserQuotas(c *models.ReqContext) response.Response { } query := models.GetUserQuotasQuery{UserId: c.ParamsInt64(":id")} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil { return response.Error(500, "Failed to get org quotas", err) } @@ -62,7 +62,7 @@ func UpdateUserQuota(c *models.ReqContext, cmd models.UpdateUserQuotaCmd) respon return response.Error(404, "Invalid quota target", nil) } - if err := bus.Dispatch(&cmd); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &cmd); err != nil { return response.Error(500, "Failed to update org quotas", err) } return response.Success("Organization quota updated") diff --git a/pkg/api/roles.go b/pkg/api/roles.go index 4dc3b898ab0..77244c3ffc8 100644 --- a/pkg/api/roles.go +++ b/pkg/api/roles.go @@ -90,3 +90,29 @@ func (hs *HTTPServer) declareFixedRoles() error { return hs.AccessControl.DeclareFixedRoles(registrations...) } + +// Evaluators +// here is the list of complex evaluators we use in this package + +// dataSourcesConfigurationAccessEvaluator is used to protect the "Configure > Data sources" tab access +var dataSourcesConfigurationAccessEvaluator = accesscontrol.EvalAll( + accesscontrol.EvalPermission(ActionDatasourcesRead, ScopeDatasourcesAll), + accesscontrol.EvalAny( + accesscontrol.EvalPermission(ActionDatasourcesCreate), + accesscontrol.EvalPermission(ActionDatasourcesDelete), + accesscontrol.EvalPermission(ActionDatasourcesWrite), + ), +) + +// dataSourcesNewAccessEvaluator is used to protect the "Configure > Data sources > New" page access +var dataSourcesNewAccessEvaluator = accesscontrol.EvalAll( + accesscontrol.EvalPermission(ActionDatasourcesRead, ScopeDatasourcesAll), + accesscontrol.EvalPermission(ActionDatasourcesCreate), + accesscontrol.EvalPermission(ActionDatasourcesWrite), +) + +// dataSourcesEditAccessEvaluator is used to protect the "Configure > Data sources > Edit" page access +var dataSourcesEditAccessEvaluator = accesscontrol.EvalAll( + accesscontrol.EvalPermission(ActionDatasourcesRead, ScopeDatasourcesAll), + accesscontrol.EvalPermission(ActionDatasourcesWrite), +) diff --git a/pkg/components/gtime/gtime.go b/pkg/components/gtime/gtime.go deleted file mode 100644 index 22e6eefb847..00000000000 --- a/pkg/components/gtime/gtime.go +++ /dev/null @@ -1,87 +0,0 @@ -package gtime - -import ( - "fmt" - "regexp" - "strconv" - "time" -) - -var dateUnitPattern = regexp.MustCompile(`^(\d+)([dwMy])$`) - -// ParseInterval parses an interval with support for all units that Grafana uses. -// An interval is relative to the current wall time. -func ParseInterval(inp string) (time.Duration, error) { - dur, period, err := parse(inp) - if err != nil { - return 0, err - } - if period == "" { - return dur, nil - } - - num := int(dur) - - // Use UTC to ensure that the interval is deterministic, and daylight saving - // doesn't cause surprises - now := time.Now().UTC() - switch period { - case "d": - return now.AddDate(0, 0, num).Sub(now), nil - case "w": - return now.AddDate(0, 0, num*7).Sub(now), nil - case "M": - return now.AddDate(0, num, 0).Sub(now), nil - case "y": - return now.AddDate(num, 0, 0).Sub(now), nil - } - - return 0, fmt.Errorf("invalid interval %q", inp) -} - -// ParseDuration parses a duration with support for all units that Grafana uses. -// Durations are independent of wall time. -func ParseDuration(inp string) (time.Duration, error) { - dur, period, err := parse(inp) - if err != nil { - return 0, err - } - if period == "" { - return dur, nil - } - - // The average number of days in a year, using the Julian calendar - const daysInAYear = 365.25 - const day = 24 * time.Hour - const week = 7 * day - const year = time.Duration(float64(day) * daysInAYear) - const month = time.Duration(float64(year) / 12) - - switch period { - case "d": - return dur * day, nil - case "w": - return dur * week, nil - case "M": - return dur * month, nil - case "y": - return dur * year, nil - } - - return 0, fmt.Errorf("invalid duration %q", inp) -} - -func parse(inp string) (time.Duration, string, error) { - result := dateUnitPattern.FindSubmatch([]byte(inp)) - if len(result) != 3 { - dur, err := time.ParseDuration(inp) - return dur, "", err - } - - num, err := strconv.Atoi(string(result[1])) - if err != nil { - return 0, "", err - } - - return time.Duration(num), string(result[2]), nil -} diff --git a/pkg/components/gtime/gtime_test.go b/pkg/components/gtime/gtime_test.go deleted file mode 100644 index 0b1b23a1dbe..00000000000 --- a/pkg/components/gtime/gtime_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package gtime - -import ( - "fmt" - "regexp" - "testing" - "time" - - "github.com/stretchr/testify/require" -) - -func TestParseInterval(t *testing.T) { - daysInMonth, daysInYear := calculateDays() - - tcs := []struct { - inp string - duration time.Duration - err *regexp.Regexp - }{ - {inp: "1d", duration: 24 * time.Hour}, - {inp: "1w", duration: 168 * time.Hour}, - {inp: "2w", duration: 2 * 168 * time.Hour}, - {inp: "1M", duration: time.Duration(daysInMonth * 24 * int(time.Hour))}, - {inp: "1y", duration: time.Duration(daysInYear * 24 * int(time.Hour))}, - {inp: "5y", duration: time.Duration(calculateDays5y() * 24 * int(time.Hour))}, - {inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)}, - } - for i, tc := range tcs { - t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) { - res, err := ParseInterval(tc.inp) - if tc.err == nil { - require.NoError(t, err, "input %q", tc.inp) - require.Equal(t, tc.duration, res, "input %q", tc.inp) - } else { - require.Error(t, err, "input %q", tc.inp) - require.Regexp(t, tc.err, err.Error()) - } - }) - } -} - -func TestParseDuration(t *testing.T) { - tcs := []struct { - inp string - duration time.Duration - err *regexp.Regexp - }{ - {inp: "1s", duration: time.Second}, - {inp: "1m", duration: time.Minute}, - {inp: "1h", duration: time.Hour}, - {inp: "1d", duration: 24 * time.Hour}, - {inp: "1w", duration: 7 * 24 * time.Hour}, - {inp: "2w", duration: 2 * 7 * 24 * time.Hour}, - {inp: "1M", duration: time.Duration(730.5 * float64(time.Hour))}, - {inp: "1y", duration: 365.25 * 24 * time.Hour}, - {inp: "5y", duration: 5 * 365.25 * 24 * time.Hour}, - {inp: "invalid-duration", err: regexp.MustCompile(`^time: invalid duration "?invalid-duration"?$`)}, - } - for i, tc := range tcs { - t.Run(fmt.Sprintf("testcase %d", i), func(t *testing.T) { - res, err := ParseDuration(tc.inp) - if tc.err == nil { - require.NoError(t, err, "input %q", tc.inp) - require.Equal(t, tc.duration, res, "input %q", tc.inp) - } else { - require.Error(t, err, "input %q", tc.inp) - require.Regexp(t, tc.err, err.Error()) - } - }) - } -} - -func calculateDays() (int, int) { - now := time.Now().UTC() - currentYear, currentMonth, _ := now.Date() - - firstDayOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, time.UTC) - daysInMonth := firstDayOfMonth.AddDate(0, 1, -1).Day() - - t1 := time.Date(currentYear, 1, 1, 0, 0, 0, 0, time.UTC) - t2 := time.Date(currentYear+1, 1, 1, 0, 0, 0, 0, time.UTC) - - daysInYear := int(t2.Sub(t1).Hours() / 24) - - return daysInMonth, daysInYear -} - -func calculateDays5y() int { - now := time.Now().UTC() - currentYear, _, _ := now.Date() - - var daysInYear int - - for i := 0; i < 5; i++ { - t1 := time.Date(currentYear+i, 1, 1, 0, 0, 0, 0, time.UTC) - t2 := time.Date(currentYear+i+1, 1, 1, 0, 0, 0, 0, time.UTC) - - daysInYear = daysInYear + int(t2.Sub(t1).Hours()/24) - } - - return daysInYear -} diff --git a/pkg/dashboards/ifaces.go b/pkg/dashboards/ifaces.go index 101cd362676..4e524d58d1a 100644 --- a/pkg/dashboards/ifaces.go +++ b/pkg/dashboards/ifaces.go @@ -1,6 +1,10 @@ package dashboards -import "github.com/grafana/grafana/pkg/models" +import ( + "context" + + "github.com/grafana/grafana/pkg/models" +) // Store is a dashboard store. type Store interface { @@ -12,7 +16,7 @@ type Store interface { GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) SaveProvisionedDashboard(cmd models.SaveDashboardCommand, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error) - UpdateDashboardACL(uid int64, items []*models.DashboardAcl) error + UpdateDashboardACLCtx(ctx context.Context, uid int64, items []*models.DashboardAcl) error // SaveAlerts saves dashboard alerts. SaveAlerts(dashID int64, alerts []*models.Alert) error } diff --git a/pkg/expr/commands.go b/pkg/expr/commands.go index 2112c813c46..f31b9164f67 100644 --- a/pkg/expr/commands.go +++ b/pkg/expr/commands.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/expr/mathexp" ) diff --git a/pkg/infra/remotecache/redis_storage.go b/pkg/infra/remotecache/redis_storage.go index 59d751c3db0..d0b67995f3f 100644 --- a/pkg/infra/remotecache/redis_storage.go +++ b/pkg/infra/remotecache/redis_storage.go @@ -1,15 +1,16 @@ package remotecache import ( + "context" "crypto/tls" "fmt" "strconv" "strings" "time" + "github.com/go-redis/redis/v8" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util/errutil" - redis "gopkg.in/redis.v5" ) const redisCacheType = "redis" @@ -91,13 +92,13 @@ func (s *redisStorage) Set(key string, val interface{}, expires time.Duration) e if err != nil { return err } - status := s.c.Set(key, string(value), expires) + status := s.c.Set(context.TODO(), key, string(value), expires) return status.Err() } // Get gets value by given key in session. func (s *redisStorage) Get(key string) (interface{}, error) { - v := s.c.Get(key) + v := s.c.Get(context.TODO(), key) item := &cachedItem{} err := decodeGob([]byte(v.Val()), item) @@ -113,6 +114,6 @@ func (s *redisStorage) Get(key string) (interface{}, error) { // Delete delete a key from session. func (s *redisStorage) Delete(key string) error { - cmd := s.c.Del(key) + cmd := s.c.Del(context.TODO(), key) return cmd.Err() } diff --git a/pkg/infra/remotecache/redis_storage_test.go b/pkg/infra/remotecache/redis_storage_test.go index 0ba9dcc907e..32138431f21 100644 --- a/pkg/infra/remotecache/redis_storage_test.go +++ b/pkg/infra/remotecache/redis_storage_test.go @@ -5,8 +5,8 @@ import ( "fmt" "testing" + "github.com/go-redis/redis/v8" "github.com/stretchr/testify/assert" - redis "gopkg.in/redis.v5" ) func Test_parseRedisConnStr(t *testing.T) { diff --git a/pkg/infra/usagestats/service.go b/pkg/infra/usagestats/service.go index 2e07741e437..73fb59219a2 100644 --- a/pkg/infra/usagestats/service.go +++ b/pkg/infra/usagestats/service.go @@ -2,168 +2,26 @@ package usagestats import ( "context" - "fmt" - "time" - - "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/infra/kvstore" - "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/login/social" - "github.com/grafana/grafana/pkg/plugins" - "github.com/grafana/grafana/pkg/services/alerting" - "github.com/grafana/grafana/pkg/services/live" - "github.com/grafana/grafana/pkg/services/sqlstore" - "github.com/grafana/grafana/pkg/setting" ) -type UsageStats interface { - GetUsageReport(context.Context) (UsageReport, error) - RegisterMetricsFunc(MetricsFunc) - ShouldBeReported(string) bool +type Report struct { + Version string `json:"version"` + Metrics map[string]interface{} `json:"metrics"` + Os string `json:"os"` + Arch string `json:"arch"` + Edition string `json:"edition"` + HasValidLicense bool `json:"hasValidLicense"` + Packaging string `json:"packaging"` + UsageStatsId string `json:"usageStatsId"` } type MetricsFunc func() (map[string]interface{}, error) -type UsageStatsService struct { - Cfg *setting.Cfg - Bus bus.Bus - SQLStore *sqlstore.SQLStore - AlertingUsageStats alerting.UsageStatsQuerier - PluginManager plugins.Manager - SocialService social.Service - grafanaLive *live.GrafanaLive - kvStore *kvstore.NamespacedKVStore +type SendReportCallbackFunc func() - log log.Logger - - oauthProviders map[string]bool - externalMetrics []MetricsFunc - concurrentUserStatsCache memoConcurrentUserStats - liveStats liveUsageStats - startTime time.Time -} - -type liveUsageStats struct { - numClientsMax int - numClientsMin int - numClientsSum int - numUsersMax int - numUsersMin int - numUsersSum int - sampleCount int -} - -func ProvideService(cfg *setting.Cfg, bus bus.Bus, sqlStore *sqlstore.SQLStore, - alertingStats alerting.UsageStatsQuerier, pluginManager plugins.Manager, - socialService social.Service, grafanaLive *live.GrafanaLive, - kvStore kvstore.KVStore) *UsageStatsService { - s := &UsageStatsService{ - Cfg: cfg, - Bus: bus, - SQLStore: sqlStore, - AlertingUsageStats: alertingStats, - oauthProviders: socialService.GetOAuthProviders(), - PluginManager: pluginManager, - grafanaLive: grafanaLive, - kvStore: kvstore.WithNamespace(kvStore, 0, "infra.usagestats"), - log: log.New("infra.usagestats"), - startTime: time.Now(), - } - return s -} - -func (uss *UsageStatsService) Run(ctx context.Context) error { - uss.updateTotalStats() - - // try to load last sent time from kv store - lastSent := time.Now() - if val, ok, err := uss.kvStore.Get(ctx, "last_sent"); err != nil { - uss.log.Error("Failed to get last sent time", "error", err) - } else if ok { - if parsed, err := time.Parse(time.RFC3339, val); err != nil { - uss.log.Error("Failed to parse last sent time", "error", err) - } else { - lastSent = parsed - } - } - - // calculate initial send delay - sendInterval := time.Hour * 24 - nextSendInterval := time.Until(lastSent.Add(sendInterval)) - if nextSendInterval < time.Minute { - nextSendInterval = time.Minute - } - - sendReportTicker := time.NewTicker(nextSendInterval) - updateStatsTicker := time.NewTicker(time.Minute * 30) - - defer sendReportTicker.Stop() - defer updateStatsTicker.Stop() - - for { - select { - case <-sendReportTicker.C: - if err := uss.sendUsageStats(ctx); err != nil { - uss.log.Warn("Failed to send usage stats", "error", err) - } - - lastSent = time.Now() - if err := uss.kvStore.Set(ctx, "last_sent", lastSent.Format(time.RFC3339)); err != nil { - uss.log.Warn("Failed to update last sent time", "error", err) - } - - if nextSendInterval != sendInterval { - nextSendInterval = sendInterval - sendReportTicker.Reset(nextSendInterval) - } - - // always reset live stats every report tick - uss.resetLiveStats() - case <-updateStatsTicker.C: - uss.updateTotalStats() - uss.sampleLiveStats() - case <-ctx.Done(): - return ctx.Err() - } - } -} - -type memoConcurrentUserStats struct { - stats *concurrentUsersStats - - memoized time.Time -} - -const concurrentUserStatsCacheLifetime = time.Hour - -func (uss *UsageStatsService) GetConcurrentUsersStats(ctx context.Context) (*concurrentUsersStats, error) { - memoizationPeriod := time.Now().Add(-concurrentUserStatsCacheLifetime) - if !uss.concurrentUserStatsCache.memoized.Before(memoizationPeriod) { - return uss.concurrentUserStatsCache.stats, nil - } - - uss.concurrentUserStatsCache.stats = &concurrentUsersStats{} - err := uss.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { - // Retrieves concurrent users stats as a histogram. Buckets are accumulative and upper bound is inclusive. - rawSQL := ` -SELECT - COUNT(CASE WHEN tokens <= 3 THEN 1 END) AS bucket_le_3, - COUNT(CASE WHEN tokens <= 6 THEN 1 END) AS bucket_le_6, - COUNT(CASE WHEN tokens <= 9 THEN 1 END) AS bucket_le_9, - COUNT(CASE WHEN tokens <= 12 THEN 1 END) AS bucket_le_12, - COUNT(CASE WHEN tokens <= 15 THEN 1 END) AS bucket_le_15, - COUNT(1) AS bucket_le_inf -FROM (select count(1) as tokens from user_auth_token group by user_id) uat;` - _, err := sess.SQL(rawSQL).Get(uss.concurrentUserStatsCache.stats) - if err != nil { - return err - } - return nil - }) - if err != nil { - return nil, fmt.Errorf("failed to get concurrent users stats from database: %w", err) - } - - uss.concurrentUserStatsCache.memoized = time.Now() - return uss.concurrentUserStatsCache.stats, nil +type Service interface { + GetUsageReport(context.Context) (Report, error) + RegisterMetricsFunc(MetricsFunc) + RegisterSendReportCallback(SendReportCallbackFunc) + ShouldBeReported(string) bool } diff --git a/pkg/infra/usagestats/service/service.go b/pkg/infra/usagestats/service/service.go new file mode 100644 index 00000000000..823b3ddba8b --- /dev/null +++ b/pkg/infra/usagestats/service/service.go @@ -0,0 +1,149 @@ +package service + +import ( + "context" + "fmt" + "time" + + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/infra/kvstore" + "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/usagestats" + "github.com/grafana/grafana/pkg/login/social" + "github.com/grafana/grafana/pkg/plugins" + "github.com/grafana/grafana/pkg/services/sqlstore" + "github.com/grafana/grafana/pkg/setting" +) + +type UsageStats struct { + Cfg *setting.Cfg + Bus bus.Bus + SQLStore *sqlstore.SQLStore + PluginManager plugins.Manager + SocialService social.Service + kvStore *kvstore.NamespacedKVStore + + log log.Logger + + oauthProviders map[string]bool + externalMetrics []usagestats.MetricsFunc + concurrentUserStatsCache memoConcurrentUserStats + startTime time.Time + sendReportCallbacks []usagestats.SendReportCallbackFunc +} + +func ProvideService(cfg *setting.Cfg, bus bus.Bus, sqlStore *sqlstore.SQLStore, pluginManager plugins.Manager, + socialService social.Service, kvStore kvstore.KVStore) *UsageStats { + s := &UsageStats{ + Cfg: cfg, + Bus: bus, + SQLStore: sqlStore, + oauthProviders: socialService.GetOAuthProviders(), + PluginManager: pluginManager, + kvStore: kvstore.WithNamespace(kvStore, 0, "infra.usagestats"), + log: log.New("infra.usagestats"), + startTime: time.Now(), + } + + return s +} + +func (uss *UsageStats) Run(ctx context.Context) error { + uss.updateTotalStats() + + // try to load last sent time from kv store + lastSent := time.Now() + if val, ok, err := uss.kvStore.Get(ctx, "last_sent"); err != nil { + uss.log.Error("Failed to get last sent time", "error", err) + } else if ok { + if parsed, err := time.Parse(time.RFC3339, val); err != nil { + uss.log.Error("Failed to parse last sent time", "error", err) + } else { + lastSent = parsed + } + } + + // calculate initial send delay + sendInterval := time.Hour * 24 + nextSendInterval := time.Until(lastSent.Add(sendInterval)) + if nextSendInterval < time.Minute { + nextSendInterval = time.Minute + } + + sendReportTicker := time.NewTicker(nextSendInterval) + updateStatsTicker := time.NewTicker(time.Minute * 30) + + defer sendReportTicker.Stop() + defer updateStatsTicker.Stop() + + for { + select { + case <-sendReportTicker.C: + if err := uss.sendUsageStats(ctx); err != nil { + uss.log.Warn("Failed to send usage stats", "error", err) + } + + lastSent = time.Now() + if err := uss.kvStore.Set(ctx, "last_sent", lastSent.Format(time.RFC3339)); err != nil { + uss.log.Warn("Failed to update last sent time", "error", err) + } + + if nextSendInterval != sendInterval { + nextSendInterval = sendInterval + sendReportTicker.Reset(nextSendInterval) + } + + for _, callback := range uss.sendReportCallbacks { + callback() + } + case <-updateStatsTicker.C: + uss.updateTotalStats() + case <-ctx.Done(): + return ctx.Err() + } + } +} + +type memoConcurrentUserStats struct { + stats *concurrentUsersStats + + memoized time.Time +} + +const concurrentUserStatsCacheLifetime = time.Hour + +func (uss *UsageStats) GetConcurrentUsersStats(ctx context.Context) (*concurrentUsersStats, error) { + memoizationPeriod := time.Now().Add(-concurrentUserStatsCacheLifetime) + if !uss.concurrentUserStatsCache.memoized.Before(memoizationPeriod) { + return uss.concurrentUserStatsCache.stats, nil + } + + uss.concurrentUserStatsCache.stats = &concurrentUsersStats{} + err := uss.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + // Retrieves concurrent users stats as a histogram. Buckets are accumulative and upper bound is inclusive. + rawSQL := ` +SELECT + COUNT(CASE WHEN tokens <= 3 THEN 1 END) AS bucket_le_3, + COUNT(CASE WHEN tokens <= 6 THEN 1 END) AS bucket_le_6, + COUNT(CASE WHEN tokens <= 9 THEN 1 END) AS bucket_le_9, + COUNT(CASE WHEN tokens <= 12 THEN 1 END) AS bucket_le_12, + COUNT(CASE WHEN tokens <= 15 THEN 1 END) AS bucket_le_15, + COUNT(1) AS bucket_le_inf +FROM (select count(1) as tokens from user_auth_token group by user_id) uat;` + _, err := sess.SQL(rawSQL).Get(uss.concurrentUserStatsCache.stats) + if err != nil { + return err + } + return nil + }) + if err != nil { + return nil, fmt.Errorf("failed to get concurrent users stats from database: %w", err) + } + + uss.concurrentUserStatsCache.memoized = time.Now() + return uss.concurrentUserStatsCache.stats, nil +} + +func (uss *UsageStats) RegisterSendReportCallback(c usagestats.SendReportCallbackFunc) { + uss.sendReportCallbacks = append(uss.sendReportCallbacks, c) +} diff --git a/pkg/infra/usagestats/types.go b/pkg/infra/usagestats/service/types.go similarity index 93% rename from pkg/infra/usagestats/types.go rename to pkg/infra/usagestats/service/types.go index df1a7bf3bb8..c9e2a4d8361 100644 --- a/pkg/infra/usagestats/types.go +++ b/pkg/infra/usagestats/service/types.go @@ -1,4 +1,4 @@ -package usagestats +package service type concurrentUsersStats struct { BucketLE3 int32 `xorm:"bucket_le_3"` diff --git a/pkg/infra/usagestats/usage_stats.go b/pkg/infra/usagestats/service/usage_stats.go similarity index 79% rename from pkg/infra/usagestats/usage_stats.go rename to pkg/infra/usagestats/service/usage_stats.go index 87115fc352f..5bdbaa13184 100644 --- a/pkg/infra/usagestats/usage_stats.go +++ b/pkg/infra/usagestats/service/usage_stats.go @@ -1,4 +1,4 @@ -package usagestats +package service import ( "bytes" @@ -12,23 +12,13 @@ import ( "github.com/google/uuid" "github.com/grafana/grafana/pkg/infra/metrics" + "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/models" ) var usageStatsURL = "https://stats.grafana.org/grafana-usage-report" -type UsageReport struct { - Version string `json:"version"` - Metrics map[string]interface{} `json:"metrics"` - Os string `json:"os"` - Arch string `json:"arch"` - Edition string `json:"edition"` - HasValidLicense bool `json:"hasValidLicense"` - Packaging string `json:"packaging"` - UsageStatsId string `json:"usageStatsId"` -} - -func (uss *UsageStatsService) GetUsageReport(ctx context.Context) (UsageReport, error) { +func (uss *UsageStats) GetUsageReport(ctx context.Context) (usagestats.Report, error) { version := strings.ReplaceAll(uss.Cfg.BuildVersion, ".", "_") metrics := map[string]interface{}{} @@ -37,7 +27,7 @@ func (uss *UsageStatsService) GetUsageReport(ctx context.Context) (UsageReport, if uss.Cfg.IsEnterprise { edition = "enterprise" } - report := UsageReport{ + report := usagestats.Report{ Version: version, Metrics: metrics, Os: runtime.GOOS, @@ -93,20 +83,6 @@ func (uss *UsageStatsService) GetUsageReport(ctx context.Context) (UsageReport, metrics["stats.folders_viewers_can_edit.count"] = statsQuery.Result.FoldersViewersCanEdit metrics["stats.folders_viewers_can_admin.count"] = statsQuery.Result.FoldersViewersCanAdmin - liveUsersAvg := 0 - liveClientsAvg := 0 - if uss.liveStats.sampleCount > 0 { - liveUsersAvg = uss.liveStats.numUsersSum / uss.liveStats.sampleCount - liveClientsAvg = uss.liveStats.numClientsSum / uss.liveStats.sampleCount - } - metrics["stats.live_samples.count"] = uss.liveStats.sampleCount - metrics["stats.live_users_max.count"] = uss.liveStats.numUsersMax - metrics["stats.live_users_min.count"] = uss.liveStats.numUsersMin - metrics["stats.live_users_avg.count"] = liveUsersAvg - metrics["stats.live_clients_max.count"] = uss.liveStats.numClientsMax - metrics["stats.live_clients_min.count"] = uss.liveStats.numClientsMin - metrics["stats.live_clients_avg.count"] = liveClientsAvg - ossEditionCount := 1 enterpriseEditionCount := 0 if uss.Cfg.IsEnterprise { @@ -174,28 +150,6 @@ func (uss *UsageStatsService) GetUsageReport(ctx context.Context) (UsageReport, metrics["stats.packaging."+uss.Cfg.Packaging+".count"] = 1 metrics["stats.distributor."+uss.Cfg.ReportingDistributor+".count"] = 1 - // Alerting stats - alertingUsageStats, err := uss.AlertingUsageStats.QueryUsageStats() - if err != nil { - uss.log.Error("Failed to get alerting usage stats", "error", err) - return report, err - } - - var addAlertingUsageStats = func(dsType string, usageCount int) { - metrics[fmt.Sprintf("stats.alerting.ds.%s.count", dsType)] = usageCount - } - - alertingOtherCount := 0 - for dsType, usageCount := range alertingUsageStats.DatasourceUsage { - if uss.ShouldBeReported(dsType) { - addAlertingUsageStats(dsType, usageCount) - } else { - alertingOtherCount += usageCount - } - } - - addAlertingUsageStats("other", alertingOtherCount) - // fetch datasource access stats dsAccessStats := models.GetDataSourceAccessStatsQuery{} if err := uss.Bus.Dispatch(&dsAccessStats); err != nil { @@ -276,7 +230,7 @@ func (uss *UsageStatsService) GetUsageReport(ctx context.Context) (UsageReport, return report, nil } -func (uss *UsageStatsService) registerExternalMetrics(metrics map[string]interface{}) { +func (uss *UsageStats) registerExternalMetrics(metrics map[string]interface{}) { for _, fn := range uss.externalMetrics { fnMetrics, err := fn() if err != nil { @@ -290,11 +244,11 @@ func (uss *UsageStatsService) registerExternalMetrics(metrics map[string]interfa } } -func (uss *UsageStatsService) RegisterMetricsFunc(fn MetricsFunc) { +func (uss *UsageStats) RegisterMetricsFunc(fn usagestats.MetricsFunc) { uss.externalMetrics = append(uss.externalMetrics, fn) } -func (uss *UsageStatsService) sendUsageStats(ctx context.Context) error { +func (uss *UsageStats) sendUsageStats(ctx context.Context) error { if !uss.Cfg.ReportingEnabled { return nil } @@ -319,7 +273,7 @@ func (uss *UsageStatsService) sendUsageStats(ctx context.Context) error { // sendUsageStats sends usage statistics. // // Stubbable by tests. -var sendUsageStats = func(uss *UsageStatsService, data *bytes.Buffer) { +var sendUsageStats = func(uss *UsageStats, data *bytes.Buffer) { go func() { client := http.Client{Timeout: 5 * time.Second} resp, err := client.Post(usageStatsURL, "application/json", data) @@ -333,35 +287,7 @@ var sendUsageStats = func(uss *UsageStatsService, data *bytes.Buffer) { }() } -func (uss *UsageStatsService) sampleLiveStats() { - current := uss.grafanaLive.UsageStats() - - uss.liveStats.sampleCount++ - uss.liveStats.numClientsSum += current.NumClients - uss.liveStats.numUsersSum += current.NumUsers - - if current.NumClients > uss.liveStats.numClientsMax { - uss.liveStats.numClientsMax = current.NumClients - } - - if current.NumClients < uss.liveStats.numClientsMin { - uss.liveStats.numClientsMin = current.NumClients - } - - if current.NumUsers > uss.liveStats.numUsersMax { - uss.liveStats.numUsersMax = current.NumUsers - } - - if current.NumUsers < uss.liveStats.numUsersMin { - uss.liveStats.numUsersMin = current.NumUsers - } -} - -func (uss *UsageStatsService) resetLiveStats() { - uss.liveStats = liveUsageStats{} -} - -func (uss *UsageStatsService) updateTotalStats() { +func (uss *UsageStats) updateTotalStats() { if !uss.Cfg.MetricsEndpointEnabled || uss.Cfg.MetricsEndpointDisableTotalStats { return } @@ -401,7 +327,7 @@ func (uss *UsageStatsService) updateTotalStats() { } } -func (uss *UsageStatsService) ShouldBeReported(dsType string) bool { +func (uss *UsageStats) ShouldBeReported(dsType string) bool { ds := uss.PluginManager.GetDataSource(dsType) if ds == nil { return false @@ -410,7 +336,7 @@ func (uss *UsageStatsService) ShouldBeReported(dsType string) bool { return ds.Signature.IsValid() || ds.Signature.IsInternal() } -func (uss *UsageStatsService) GetUsageStatsId(ctx context.Context) string { +func (uss *UsageStats) GetUsageStatsId(ctx context.Context) string { anonId, ok, err := uss.kvStore.Get(ctx, "anonymous_id") if err != nil { uss.log.Error("Failed to get usage stats id", "error", err) diff --git a/pkg/infra/usagestats/usage_stats_service_test.go b/pkg/infra/usagestats/service/usage_stats_service_test.go similarity index 98% rename from pkg/infra/usagestats/usage_stats_service_test.go rename to pkg/infra/usagestats/service/usage_stats_service_test.go index ba226d9c064..80b5f8ccf60 100644 --- a/pkg/infra/usagestats/usage_stats_service_test.go +++ b/pkg/infra/usagestats/service/usage_stats_service_test.go @@ -1,4 +1,4 @@ -package usagestats +package service import ( "context" @@ -19,7 +19,7 @@ import ( func TestUsageStatsService_GetConcurrentUsersStats(t *testing.T) { sqlStore := sqlstore.InitTestDB(t) - uss := &UsageStatsService{ + uss := &UsageStats{ Bus: bus.New(), SQLStore: sqlStore, kvStore: kvstore.WithNamespace(kvstore.ProvideService(sqlStore), 0, "infra.usagestats"), diff --git a/pkg/infra/usagestats/usage_stats_test.go b/pkg/infra/usagestats/service/usage_stats_test.go similarity index 91% rename from pkg/infra/usagestats/usage_stats_test.go rename to pkg/infra/usagestats/service/usage_stats_test.go index 7b6ca4a72f1..7fc54de8ff0 100644 --- a/pkg/infra/usagestats/usage_stats_test.go +++ b/pkg/infra/usagestats/service/usage_stats_test.go @@ -1,4 +1,4 @@ -package usagestats +package service import ( "bytes" @@ -11,16 +11,14 @@ import ( "testing" "time" - "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/manager" - "github.com/grafana/grafana/pkg/services/alerting" - "github.com/grafana/grafana/pkg/services/live" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/setting" "github.com/stretchr/testify/assert" @@ -29,10 +27,10 @@ import ( // This is to ensure that the interface contract is held by the implementation func Test_InterfaceContractValidity(t *testing.T) { - newUsageStats := func() UsageStats { - return &UsageStatsService{} + newUsageStats := func() usagestats.Service { + return &UsageStats{} } - v, ok := newUsageStats().(*UsageStatsService) + v, ok := newUsageStats().(*UsageStats) assert.NotNil(t, v) assert.True(t, ok) @@ -201,7 +199,6 @@ func TestMetrics(t *testing.T) { }) createConcurrentTokens(t, uss.SQLStore) - uss.AlertingUsageStats = &alertingUsageMock{} uss.oauthProviders = map[string]bool{ "github": true, @@ -221,7 +218,7 @@ func TestMetrics(t *testing.T) { sendUsageStats = origSendUsageStats }) statsSent := false - sendUsageStats = func(uss *UsageStatsService, b *bytes.Buffer) { + sendUsageStats = func(uss *UsageStats, b *bytes.Buffer) { statsSent = true } @@ -371,11 +368,6 @@ func TestMetrics(t *testing.T) { assert.Equal(t, 6+7, metrics.Get("stats.ds_access.other.direct.count").MustInt()) assert.Equal(t, 4+8, metrics.Get("stats.ds_access.other.proxy.count").MustInt()) - assert.Equal(t, 1, metrics.Get("stats.alerting.ds.prometheus.count").MustInt()) - assert.Equal(t, 2, metrics.Get("stats.alerting.ds.graphite.count").MustInt()) - assert.Equal(t, 5, metrics.Get("stats.alerting.ds.mysql.count").MustInt()) - assert.Equal(t, 90, metrics.Get("stats.alerting.ds.other.count").MustInt()) - assert.Equal(t, 1, metrics.Get("stats.alert_notifiers.slack.count").MustInt()) assert.Equal(t, 2, metrics.Get("stats.alert_notifiers.webhook.count").MustInt()) @@ -560,19 +552,6 @@ func TestMetrics(t *testing.T) { }) } -type alertingUsageMock struct{} - -func (aum *alertingUsageMock) QueryUsageStats() (*alerting.UsageStats, error) { - return &alerting.UsageStats{ - DatasourceUsage: map[string]int{ - "prometheus": 1, - "graphite": 2, - "mysql": 5, - "unknown-datasource": 90, - }, - }, nil -} - type fakePluginManager struct { manager.PluginManager @@ -592,7 +571,7 @@ func (pm *fakePluginManager) PanelCount() int { return len(pm.panels) } -func setupSomeDataSourcePlugins(t *testing.T, uss *UsageStatsService) { +func setupSomeDataSourcePlugins(t *testing.T, uss *UsageStats) { t.Helper() uss.PluginManager = &fakePluginManager{ @@ -635,28 +614,19 @@ type httpResp struct { err error } -func createService(t *testing.T, cfg setting.Cfg) *UsageStatsService { +func createService(t *testing.T, cfg setting.Cfg) *UsageStats { t.Helper() sqlStore := sqlstore.InitTestDB(t) - return &UsageStatsService{ - Bus: bus.New(), - Cfg: &cfg, - SQLStore: sqlStore, - AlertingUsageStats: &alertingUsageMock{}, - externalMetrics: make([]MetricsFunc, 0), - PluginManager: &fakePluginManager{}, - grafanaLive: newTestLive(t), - kvStore: kvstore.WithNamespace(kvstore.ProvideService(sqlStore), 0, "infra.usagestats"), - log: log.New("infra.usagestats"), - startTime: time.Now().Add(-1 * time.Minute), + return &UsageStats{ + Bus: bus.New(), + Cfg: &cfg, + SQLStore: sqlStore, + externalMetrics: make([]usagestats.MetricsFunc, 0), + PluginManager: &fakePluginManager{}, + kvStore: kvstore.WithNamespace(kvstore.ProvideService(sqlStore), 0, "infra.usagestats"), + log: log.New("infra.usagestats"), + startTime: time.Now().Add(-1 * time.Minute), } } - -func newTestLive(t *testing.T) *live.GrafanaLive { - cfg := &setting.Cfg{AppURL: "http://localhost:3000/"} - gLive, err := live.ProvideService(nil, cfg, routing.NewRouteRegister(), nil, nil, nil, nil, sqlstore.InitTestDB(t)) - require.NoError(t, err) - return gLive -} diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index c477ff3be91..59628d0d380 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -15,9 +15,9 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/macaron.v1" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/components/gtime" "github.com/grafana/grafana/pkg/infra/fs" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/remotecache" diff --git a/pkg/middleware/quota_test.go b/pkg/middleware/quota_test.go index 2319c470191..c719e99b5da 100644 --- a/pkg/middleware/quota_test.go +++ b/pkg/middleware/quota_test.go @@ -16,7 +16,7 @@ import ( func TestMiddlewareQuota(t *testing.T) { t.Run("With user not logged in", func(t *testing.T) { middlewareScenario(t, "and global quota not reached", func(t *testing.T, sc *scenarioContext) { - bus.AddHandler("globalQuota", func(query *models.GetGlobalQuotaByTargetQuery) error { + bus.AddHandlerCtx("globalQuota", func(_ context.Context, query *models.GetGlobalQuotaByTargetQuery) error { query.Result = &models.GlobalQuotaDTO{ Target: query.Target, Limit: query.Default, @@ -33,7 +33,7 @@ func TestMiddlewareQuota(t *testing.T) { }, configure) middlewareScenario(t, "and global quota reached", func(t *testing.T, sc *scenarioContext) { - bus.AddHandler("globalQuota", func(query *models.GetGlobalQuotaByTargetQuery) error { + bus.AddHandlerCtx("globalQuota", func(_ context.Context, query *models.GetGlobalQuotaByTargetQuery) error { query.Result = &models.GlobalQuotaDTO{ Target: query.Target, Limit: query.Default, @@ -53,7 +53,7 @@ func TestMiddlewareQuota(t *testing.T) { }) middlewareScenario(t, "and global session quota not reached", func(t *testing.T, sc *scenarioContext) { - bus.AddHandler("globalQuota", func(query *models.GetGlobalQuotaByTargetQuery) error { + bus.AddHandlerCtx("globalQuota", func(_ context.Context, query *models.GetGlobalQuotaByTargetQuery) error { query.Result = &models.GlobalQuotaDTO{ Target: query.Target, Limit: query.Default, @@ -101,7 +101,7 @@ func TestMiddlewareQuota(t *testing.T) { }, nil } - bus.AddHandler("globalQuota", func(query *models.GetGlobalQuotaByTargetQuery) error { + bus.AddHandlerCtx("globalQuota", func(_ context.Context, query *models.GetGlobalQuotaByTargetQuery) error { query.Result = &models.GlobalQuotaDTO{ Target: query.Target, Limit: query.Default, diff --git a/pkg/server/backgroundsvcs/background_services.go b/pkg/server/backgroundsvcs/background_services.go index 7d2e3440b6d..8a5c3cb764d 100644 --- a/pkg/server/backgroundsvcs/background_services.go +++ b/pkg/server/backgroundsvcs/background_services.go @@ -5,7 +5,7 @@ import ( "github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/infra/remotecache" "github.com/grafana/grafana/pkg/infra/tracing" - "github.com/grafana/grafana/pkg/infra/usagestats" + uss "github.com/grafana/grafana/pkg/infra/usagestats/service" "github.com/grafana/grafana/pkg/models" backendmanager "github.com/grafana/grafana/pkg/plugins/backendplugin/manager" "github.com/grafana/grafana/pkg/plugins/manager" @@ -42,7 +42,7 @@ func ProvideBackgroundServiceRegistry( rendering *rendering.RenderingService, tokenService models.UserTokenBackgroundService, provisioning *provisioning.ProvisioningServiceImpl, alerting *alerting.AlertEngine, pm *manager.PluginManager, backendPM *backendmanager.Manager, metrics *metrics.InternalMetricsService, - usageStats *usagestats.UsageStatsService, tracing *tracing.TracingService, remoteCache *remotecache.RemoteCache, + usageStats *uss.UsageStats, tracing *tracing.TracingService, remoteCache *remotecache.RemoteCache, // Need to make sure these are initialized, is there a better place to put them? _ *azuremonitor.Service, _ *cloudwatch.CloudWatchService, _ *elasticsearch.Service, _ *graphite.Service, _ *influxdb.Service, _ *loki.Service, _ *opentsdb.Service, _ *prometheus.Service, _ *tempo.Service, diff --git a/pkg/server/wire.go b/pkg/server/wire.go index ceb7a104966..6ee1bfd6ca5 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -19,6 +19,7 @@ import ( "github.com/grafana/grafana/pkg/infra/serverlock" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/infra/usagestats" + uss "github.com/grafana/grafana/pkg/infra/usagestats/service" "github.com/grafana/grafana/pkg/login/social" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" @@ -87,8 +88,8 @@ var wireBasicSet = wire.NewSet( hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, - usagestats.ProvideService, - wire.Bind(new(usagestats.UsageStats), new(*usagestats.UsageStatsService)), + uss.ProvideService, + wire.Bind(new(usagestats.Service), new(*uss.UsageStats)), manager.ProvideService, wire.Bind(new(plugins.Manager), new(*manager.PluginManager)), backendmanager.ProvideService, diff --git a/pkg/services/accesscontrol/models.go b/pkg/services/accesscontrol/models.go index a4db7af2977..ab6bc8cbba7 100644 --- a/pkg/services/accesscontrol/models.go +++ b/pkg/services/accesscontrol/models.go @@ -1,6 +1,7 @@ package accesscontrol import ( + "encoding/json" "time" ) @@ -11,9 +12,12 @@ type RoleRegistration struct { Grants []string } +// Role is the model for Role in RBAC. type Role struct { + ID int64 `json:"-" xorm:"pk autoincr 'id'"` + OrgID int64 `json:"-" xorm:"org_id"` Version int64 `json:"version"` - UID string `json:"uid"` + UID string `xorm:"uid" json:"uid"` Name string `json:"name"` Description string `json:"description"` @@ -23,25 +27,80 @@ type Role struct { type RoleDTO struct { Version int64 `json:"version"` - UID string `json:"uid"` + UID string `xorm:"uid" json:"uid"` Name string `json:"name"` Description string `json:"description"` Permissions []Permission `json:"permissions,omitempty"` + + ID int64 `json:"-" xorm:"pk autoincr 'id'"` + OrgID int64 `json:"-" xorm:"org_id"` + + Updated time.Time `json:"updated"` + Created time.Time `json:"created"` } +func (r RoleDTO) Role() Role { + return Role{ + ID: r.ID, + OrgID: r.OrgID, + UID: r.UID, + Name: r.Name, + Description: r.Description, + Updated: r.Updated, + Created: r.Created, + } +} + +func (r RoleDTO) Global() bool { + return r.OrgID == GlobalOrgID +} + +func (r Role) Global() bool { + return r.OrgID == GlobalOrgID +} + +func (r RoleDTO) MarshalJSON() ([]byte, error) { + type Alias RoleDTO + return json.Marshal(&struct { + Alias + Global bool `json:"global" xorm:"-"` + }{ + Alias: (Alias)(r), + Global: r.Global(), + }) +} + +func (r Role) MarshalJSON() ([]byte, error) { + type Alias Role + return json.Marshal(&struct { + Alias + Global bool `json:"global" xorm:"-"` + }{ + Alias: (Alias)(r), + Global: r.Global(), + }) +} + +// Permission is the model for access control permissions. type Permission struct { + ID int64 `json:"-" xorm:"pk autoincr 'id'"` + RoleID int64 `json:"-" xorm:"role_id"` Action string `json:"action"` Scope string `json:"scope"` + + Updated time.Time `json:"updated"` + Created time.Time `json:"created"` } -func (p RoleDTO) Role() Role { - return Role{ - Name: p.Name, - Description: p.Description, +func (p Permission) OSSPermission() Permission { + return Permission{ + Action: p.Action, + Scope: p.Scope, } } const ( + GlobalOrgID = 0 // Permission actions // Users actions diff --git a/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol.go b/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol.go index f37815f7739..492b3a7f9b0 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol.go @@ -12,7 +12,7 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -func ProvideService(cfg *setting.Cfg, usageStats usagestats.UsageStats) *OSSAccessControlService { +func ProvideService(cfg *setting.Cfg, usageStats usagestats.Service) *OSSAccessControlService { s := &OSSAccessControlService{ Cfg: cfg, UsageStats: usageStats, @@ -25,7 +25,7 @@ func ProvideService(cfg *setting.Cfg, usageStats usagestats.UsageStats) *OSSAcce // OSSAccessControlService is the service implementing role based access control. type OSSAccessControlService struct { Cfg *setting.Cfg - UsageStats usagestats.UsageStats + UsageStats usagestats.Service Log log.Logger registrations accesscontrol.RegistrationList } diff --git a/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol_test.go b/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol_test.go index 345e61e0e41..8eea5ce0619 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol_test.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/ossaccesscontrol_test.go @@ -54,7 +54,7 @@ func (usm *usageStatsMock) RegisterMetricsFunc(fn usagestats.MetricsFunc) { usm.metricsFuncs = append(usm.metricsFuncs, fn) } -func (usm *usageStatsMock) GetUsageReport(_ context.Context) (usagestats.UsageReport, error) { +func (usm *usageStatsMock) GetUsageReport(_ context.Context) (usagestats.Report, error) { all := make(map[string]interface{}) for _, fn := range usm.metricsFuncs { fnMetrics, err := fn() @@ -64,13 +64,15 @@ func (usm *usageStatsMock) GetUsageReport(_ context.Context) (usagestats.UsageRe all[name] = value } } - return usagestats.UsageReport{Metrics: all}, nil + return usagestats.Report{Metrics: all}, nil } func (usm *usageStatsMock) ShouldBeReported(_ string) bool { return true } +func (usm *usageStatsMock) RegisterSendReportCallback(_ usagestats.SendReportCallbackFunc) {} + type evaluatingPermissionsTestCase struct { desc string user userTestCase diff --git a/pkg/services/alerting/engine.go b/pkg/services/alerting/engine.go index 2a4ac15543d..1a7478b8bcd 100644 --- a/pkg/services/alerting/engine.go +++ b/pkg/services/alerting/engine.go @@ -9,6 +9,7 @@ import ( "github.com/benbjohnson/clock" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/rendering" @@ -29,13 +30,14 @@ type AlertEngine struct { DataService plugins.DataRequestHandler Cfg *setting.Cfg - execQueue chan *Job - ticker *Ticker - scheduler scheduler - evalHandler evalHandler - ruleReader ruleReader - log log.Logger - resultHandler resultHandler + execQueue chan *Job + ticker *Ticker + scheduler scheduler + evalHandler evalHandler + ruleReader ruleReader + log log.Logger + resultHandler resultHandler + usageStatsService usagestats.Service } // IsDisabled returns true if the alerting service is disable for this instance. @@ -45,13 +47,14 @@ func (e *AlertEngine) IsDisabled() bool { // ProvideAlertEngine returns a new AlertEngine. func ProvideAlertEngine(renderer rendering.Service, bus bus.Bus, requestValidator models.PluginRequestValidator, - dataService plugins.DataRequestHandler, cfg *setting.Cfg) *AlertEngine { + dataService plugins.DataRequestHandler, usageStatsService usagestats.Service, cfg *setting.Cfg) *AlertEngine { e := &AlertEngine{ - Cfg: cfg, - RenderService: renderer, - Bus: bus, - RequestValidator: requestValidator, - DataService: dataService, + Cfg: cfg, + RenderService: renderer, + Bus: bus, + RequestValidator: requestValidator, + DataService: dataService, + usageStatsService: usageStatsService, } e.ticker = NewTicker(time.Now(), time.Second*0, clock.New(), 1) e.execQueue = make(chan *Job, 1000) @@ -61,6 +64,8 @@ func ProvideAlertEngine(renderer rendering.Service, bus bus.Bus, requestValidato e.log = log.New("alerting.engine") e.resultHandler = newResultHandler(e.RenderService) + e.registerUsageMetrics() + return e } @@ -237,3 +242,27 @@ func (e *AlertEngine) processJob(attemptID int, attemptChan chan int, cancelChan close(attemptChan) }() } + +func (e *AlertEngine) registerUsageMetrics() { + e.usageStatsService.RegisterMetricsFunc(func() (map[string]interface{}, error) { + alertingUsageStats, err := e.QueryUsageStats() + if err != nil { + return nil, err + } + + alertingOtherCount := 0 + metrics := map[string]interface{}{} + + for dsType, usageCount := range alertingUsageStats.DatasourceUsage { + if e.usageStatsService.ShouldBeReported(dsType) { + metrics[fmt.Sprintf("stats.alerting.ds.%s.count", dsType)] = usageCount + } else { + alertingOtherCount += usageCount + } + } + + metrics["stats.alerting.ds.other.count"] = alertingOtherCount + + return metrics, nil + }) +} diff --git a/pkg/services/alerting/engine_integration_test.go b/pkg/services/alerting/engine_integration_test.go index 4db265d548e..83872961321 100644 --- a/pkg/services/alerting/engine_integration_test.go +++ b/pkg/services/alerting/engine_integration_test.go @@ -18,7 +18,8 @@ import ( func TestEngineTimeouts(t *testing.T) { Convey("Alerting engine timeout tests", t, func() { - engine := ProvideAlertEngine(nil, nil, nil, nil, setting.NewCfg()) + usMock := &usageStatsMock{t: t} + engine := ProvideAlertEngine(nil, nil, nil, nil, usMock, setting.NewCfg()) setting.AlertingNotificationTimeout = 30 * time.Second setting.AlertingMaxAttempts = 3 engine.resultHandler = &FakeResultHandler{} diff --git a/pkg/services/alerting/engine_test.go b/pkg/services/alerting/engine_test.go index 3326f690b37..592282bfba7 100644 --- a/pkg/services/alerting/engine_test.go +++ b/pkg/services/alerting/engine_test.go @@ -5,11 +5,15 @@ import ( "errors" "math" "testing" - "time" + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/components/simplejson" + "github.com/grafana/grafana/pkg/infra/usagestats" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/setting" . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/require" ) type FakeEvalHandler struct { @@ -37,15 +41,67 @@ func (handler *FakeResultHandler) handle(evalContext *EvalContext) error { return nil } +type usageStatsMock struct { + t *testing.T + metricsFuncs []usagestats.MetricsFunc +} + +func (usm *usageStatsMock) RegisterMetricsFunc(fn usagestats.MetricsFunc) { + usm.metricsFuncs = append(usm.metricsFuncs, fn) +} + +func (usm *usageStatsMock) GetUsageReport(_ context.Context) (usagestats.Report, error) { + all := make(map[string]interface{}) + for _, fn := range usm.metricsFuncs { + fnMetrics, err := fn() + require.NoError(usm.t, err) + + for name, value := range fnMetrics { + all[name] = value + } + } + return usagestats.Report{Metrics: all}, nil +} + +func (usm *usageStatsMock) ShouldBeReported(_ string) bool { + return true +} + +func (usm *usageStatsMock) RegisterSendReportCallback(_ usagestats.SendReportCallbackFunc) {} + func TestEngineProcessJob(t *testing.T) { Convey("Alerting engine job processing", t, func() { - engine := ProvideAlertEngine(nil, nil, nil, nil, setting.NewCfg()) + bus := bus.New() + usMock := &usageStatsMock{t: t} + engine := ProvideAlertEngine(nil, bus, nil, nil, usMock, setting.NewCfg()) setting.AlertingEvaluationTimeout = 30 * time.Second setting.AlertingNotificationTimeout = 30 * time.Second setting.AlertingMaxAttempts = 3 engine.resultHandler = &FakeResultHandler{} job := &Job{running: true, Rule: &Rule{}} + Convey("Should register usage metrics func", func() { + bus.AddHandler(func(q *models.GetAllAlertsQuery) error { + settings, err := simplejson.NewJson([]byte(`{"conditions": [{"query": { "datasourceId": 1}}]}`)) + if err != nil { + return err + } + q.Result = []*models.Alert{{Settings: settings}} + return nil + }) + + bus.AddHandler(func(q *models.GetDataSourceQuery) error { + q.Result = &models.DataSource{Id: 1, Type: models.DS_PROMETHEUS} + return nil + }) + + report, err := usMock.GetUsageReport(context.Background()) + So(err, ShouldBeNil) + + So(report.Metrics["stats.alerting.ds.prometheus.count"], ShouldEqual, 1) + So(report.Metrics["stats.alerting.ds.other.count"], ShouldEqual, 0) + }) + Convey("Should trigger retry if needed", func() { Convey("error + not last attempt -> retry", func() { engine.evalHandler = NewFakeEvalHandler(0) diff --git a/pkg/services/contexthandler/contexthandler_test.go b/pkg/services/contexthandler/contexthandler_test.go index b9b0ecbf216..61ee2683a60 100644 --- a/pkg/services/contexthandler/contexthandler_test.go +++ b/pkg/services/contexthandler/contexthandler_test.go @@ -7,7 +7,7 @@ import ( "net/http/httptest" "testing" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/auth" diff --git a/pkg/services/dashboards/acl_service.go b/pkg/services/dashboards/acl_service.go index f445e515e7d..0a9b7b4f024 100644 --- a/pkg/services/dashboards/acl_service.go +++ b/pkg/services/dashboards/acl_service.go @@ -43,7 +43,7 @@ func (dr *dashboardServiceImpl) MakeUserAdmin(ctx context.Context, orgID int64, ) } - if err := dr.dashboardStore.UpdateDashboardACL(dashboardID, items); err != nil { + if err := dr.dashboardStore.UpdateDashboardACLCtx(ctx, dashboardID, items); err != nil { return err } diff --git a/pkg/services/dashboards/dashboard_service.go b/pkg/services/dashboards/dashboard_service.go index 4df63285df1..e36575b1303 100644 --- a/pkg/services/dashboards/dashboard_service.go +++ b/pkg/services/dashboards/dashboard_service.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/dashboards" "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/setting" @@ -124,7 +124,7 @@ func (dr *dashboardServiceImpl) buildSaveDashboardCommand(dto *SaveDashboardDTO, } if isParentFolderChanged { - folderGuardian := guardian.New(dash.FolderId, dto.OrgId, dto.User) + folderGuardian := guardian.New(context.TODO(), dash.FolderId, dto.OrgId, dto.User) if canSave, err := folderGuardian.CanSave(); err != nil || !canSave { if err != nil { return nil, err @@ -144,7 +144,7 @@ func (dr *dashboardServiceImpl) buildSaveDashboardCommand(dto *SaveDashboardDTO, } } - guard := guardian.New(dash.GetDashboardIdForSavePermissionCheck(), dto.OrgId, dto.User) + guard := guardian.New(context.TODO(), dash.GetDashboardIdForSavePermissionCheck(), dto.OrgId, dto.User) if canSave, err := guard.CanSave(); err != nil || !canSave { if err != nil { return nil, err diff --git a/pkg/services/dashboards/folder_service.go b/pkg/services/dashboards/folder_service.go index 97cad653bc9..b1dfcfc0ad9 100644 --- a/pkg/services/dashboards/folder_service.go +++ b/pkg/services/dashboards/folder_service.go @@ -72,7 +72,7 @@ func (dr *dashboardServiceImpl) GetFolderByID(ctx context.Context, id int64) (*m return nil, toFolderError(err) } - g := guardian.New(dashFolder.Id, dr.orgId, dr.user) + g := guardian.New(ctx, dashFolder.Id, dr.orgId, dr.user) if canView, err := g.CanView(); err != nil || !canView { if err != nil { return nil, toFolderError(err) @@ -91,7 +91,7 @@ func (dr *dashboardServiceImpl) GetFolderByUID(ctx context.Context, uid string) return nil, toFolderError(err) } - g := guardian.New(dashFolder.Id, dr.orgId, dr.user) + g := guardian.New(ctx, dashFolder.Id, dr.orgId, dr.user) if canView, err := g.CanView(); err != nil || !canView { if err != nil { return nil, toFolderError(err) @@ -108,7 +108,7 @@ func (dr *dashboardServiceImpl) GetFolderByTitle(ctx context.Context, title stri return nil, toFolderError(err) } - g := guardian.New(dashFolder.Id, dr.orgId, dr.user) + g := guardian.New(ctx, dashFolder.Id, dr.orgId, dr.user) if canView, err := g.CanView(); err != nil || !canView { if err != nil { return nil, toFolderError(err) @@ -200,7 +200,7 @@ func (dr *dashboardServiceImpl) DeleteFolder(ctx context.Context, uid string, fo return nil, toFolderError(err) } - guardian := guardian.New(dashFolder.Id, dr.orgId, dr.user) + guardian := guardian.New(ctx, dashFolder.Id, dr.orgId, dr.user) if canSave, err := guardian.CanSave(); err != nil || !canSave { if err != nil { return nil, toFolderError(err) diff --git a/pkg/services/guardian/guardian.go b/pkg/services/guardian/guardian.go index 91f6868bb57..5a561bc4aaa 100644 --- a/pkg/services/guardian/guardian.go +++ b/pkg/services/guardian/guardian.go @@ -1,6 +1,7 @@ package guardian import ( + "context" "errors" "github.com/grafana/grafana/pkg/bus" @@ -40,15 +41,17 @@ type dashboardGuardianImpl struct { acl []*models.DashboardAclInfoDTO teams []*models.TeamDTO log log.Logger + ctx context.Context } // New factory for creating a new dashboard guardian instance -var New = func(dashId int64, orgId int64, user *models.SignedInUser) DashboardGuardian { +var New = func(ctx context.Context, dashId int64, orgId int64, user *models.SignedInUser) DashboardGuardian { return &dashboardGuardianImpl{ user: user, dashId: dashId, orgId: orgId, log: log.New("dashboard.permissions"), + ctx: ctx, } } @@ -201,7 +204,7 @@ func (g *dashboardGuardianImpl) GetAcl() ([]*models.DashboardAclInfoDTO, error) } query := models.GetDashboardAclInfoListQuery{DashboardID: g.dashId, OrgID: g.orgId} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(g.ctx, &query); err != nil { return nil, err } @@ -251,6 +254,7 @@ func (g *dashboardGuardianImpl) getTeams() ([]*models.TeamDTO, error) { } query := models.GetTeamsByUserQuery{OrgId: g.orgId, UserId: g.user.UserId} + // TODO: Use bus.DispatchCtx(g.Ctx, &query) when GetTeamsByUserQuery supports context. err := bus.Dispatch(&query) g.teams = query.Result @@ -343,7 +347,7 @@ func (g *FakeDashboardGuardian) GetHiddenACL(cfg *setting.Cfg) ([]*models.Dashbo // nolint:unused func MockDashboardGuardian(mock *FakeDashboardGuardian) { - New = func(dashId int64, orgId int64, user *models.SignedInUser) DashboardGuardian { + New = func(_ context.Context, dashId int64, orgId int64, user *models.SignedInUser) DashboardGuardian { mock.OrgId = orgId mock.DashId = dashId mock.User = user diff --git a/pkg/services/guardian/guardian_test.go b/pkg/services/guardian/guardian_test.go index 3b9fdcb4ed0..a46a198dad3 100644 --- a/pkg/services/guardian/guardian_test.go +++ b/pkg/services/guardian/guardian_test.go @@ -1,6 +1,7 @@ package guardian import ( + "context" "errors" "fmt" "runtime" @@ -701,7 +702,7 @@ func TestGuardianGetHiddenACL(t *testing.T) { UserId: 1, Login: "user1", } - g := New(dashboardID, orgID, user) + g := New(context.Background(), dashboardID, orgID, user) hiddenACL, err := g.GetHiddenACL(cfg) So(err, ShouldBeNil) @@ -717,7 +718,7 @@ func TestGuardianGetHiddenACL(t *testing.T) { Login: "user1", IsGrafanaAdmin: true, } - g := New(dashboardID, orgID, user) + g := New(context.Background(), dashboardID, orgID, user) hiddenACL, err := g.GetHiddenACL(cfg) So(err, ShouldBeNil) @@ -751,7 +752,7 @@ func TestGuardianGetAclWithoutDuplicates(t *testing.T) { UserId: 1, Login: "user1", } - g := New(dashboardID, orgID, user) + g := New(context.Background(), dashboardID, orgID, user) acl, err := g.GetACLWithoutDuplicates() require.NoError(t, err) diff --git a/pkg/services/guardian/guardian_util_test.go b/pkg/services/guardian/guardian_util_test.go index 1ac35ea1d7d..91eed18d775 100644 --- a/pkg/services/guardian/guardian_util_test.go +++ b/pkg/services/guardian/guardian_util_test.go @@ -2,6 +2,7 @@ package guardian import ( "bytes" + "context" "fmt" "strings" "testing" @@ -35,7 +36,7 @@ func orgRoleScenario(desc string, t *testing.T, role models.RoleType, fn scenari OrgId: orgID, OrgRole: role, } - guard := New(dashboardID, orgID, user) + guard := New(context.Background(), dashboardID, orgID, user) sc := &scenarioContext{ t: t, @@ -56,7 +57,7 @@ func apiKeyScenario(desc string, t *testing.T, role models.RoleType, fn scenario OrgRole: role, ApiKeyId: 10, } - guard := New(dashboardID, orgID, user) + guard := New(context.Background(), dashboardID, orgID, user) sc := &scenarioContext{ t: t, orgRoleScenario: desc, @@ -107,7 +108,7 @@ func permissionScenario(desc string, dashboardID int64, sc *scenarioContext, }) sc.permissionScenario = desc - sc.g = New(dashboardID, sc.givenUser.OrgId, sc.givenUser) + sc.g = New(context.Background(), dashboardID, sc.givenUser.OrgId, sc.givenUser) sc.givenDashboardID = dashboardID sc.givenPermissions = permissions sc.givenTeams = teams diff --git a/pkg/services/libraryelements/api.go b/pkg/services/libraryelements/api.go index 39ad46696cf..cfda6770fcb 100644 --- a/pkg/services/libraryelements/api.go +++ b/pkg/services/libraryelements/api.go @@ -26,7 +26,7 @@ func (l *LibraryElementService) registerAPIEndpoints() { // createHandler handles POST /api/library-elements. func (l *LibraryElementService) createHandler(c *models.ReqContext, cmd CreateLibraryElementCommand) response.Response { - element, err := l.createLibraryElement(c, cmd) + element, err := l.createLibraryElement(c.Req.Context(), c.SignedInUser, cmd) if err != nil { return toLibraryElementError(err, "Failed to create library element") } @@ -36,7 +36,7 @@ func (l *LibraryElementService) createHandler(c *models.ReqContext, cmd CreateLi // deleteHandler handles DELETE /api/library-elements/:uid. func (l *LibraryElementService) deleteHandler(c *models.ReqContext) response.Response { - err := l.deleteLibraryElement(c, macaron.Params(c.Req)[":uid"]) + err := l.deleteLibraryElement(c.Req.Context(), c.SignedInUser, macaron.Params(c.Req)[":uid"]) if err != nil { return toLibraryElementError(err, "Failed to delete library element") } @@ -46,7 +46,7 @@ func (l *LibraryElementService) deleteHandler(c *models.ReqContext) response.Res // getHandler handles GET /api/library-elements/:uid. func (l *LibraryElementService) getHandler(c *models.ReqContext) response.Response { - element, err := l.getLibraryElementByUid(c, macaron.Params(c.Req)[":uid"]) + element, err := l.getLibraryElementByUid(c.Req.Context(), c.SignedInUser, macaron.Params(c.Req)[":uid"]) if err != nil { return toLibraryElementError(err, "Failed to get library element") } @@ -66,7 +66,7 @@ func (l *LibraryElementService) getAllHandler(c *models.ReqContext) response.Res excludeUID: c.Query("excludeUid"), folderFilter: c.Query("folderFilter"), } - elementsResult, err := l.getAllLibraryElements(c, query) + elementsResult, err := l.getAllLibraryElements(c.Req.Context(), c.SignedInUser, query) if err != nil { return toLibraryElementError(err, "Failed to get library elements") } @@ -76,7 +76,7 @@ func (l *LibraryElementService) getAllHandler(c *models.ReqContext) response.Res // patchHandler handles PATCH /api/library-elements/:uid func (l *LibraryElementService) patchHandler(c *models.ReqContext, cmd patchLibraryElementCommand) response.Response { - element, err := l.patchLibraryElement(c, cmd, macaron.Params(c.Req)[":uid"]) + element, err := l.patchLibraryElement(c.Req.Context(), c.SignedInUser, cmd, macaron.Params(c.Req)[":uid"]) if err != nil { return toLibraryElementError(err, "Failed to update library element") } @@ -86,7 +86,7 @@ func (l *LibraryElementService) patchHandler(c *models.ReqContext, cmd patchLibr // getConnectionsHandler handles GET /api/library-panels/:uid/connections/. func (l *LibraryElementService) getConnectionsHandler(c *models.ReqContext) response.Response { - connections, err := l.getConnections(c, macaron.Params(c.Req)[":uid"]) + connections, err := l.getConnections(c.Req.Context(), c.SignedInUser, macaron.Params(c.Req)[":uid"]) if err != nil { return toLibraryElementError(err, "Failed to get connections") } @@ -96,7 +96,7 @@ func (l *LibraryElementService) getConnectionsHandler(c *models.ReqContext) resp // getByNameHandler handles GET /api/library-elements/name/:name/. func (l *LibraryElementService) getByNameHandler(c *models.ReqContext) response.Response { - elements, err := l.getLibraryElementsByName(c) + elements, err := l.getLibraryElementsByName(c.Req.Context(), c.SignedInUser, macaron.Params(c.Req)[":name"]) if err != nil { return toLibraryElementError(err, "Failed to get library element") } diff --git a/pkg/services/libraryelements/database.go b/pkg/services/libraryelements/database.go index aec3f1ff954..6def4bfee19 100644 --- a/pkg/services/libraryelements/database.go +++ b/pkg/services/libraryelements/database.go @@ -14,7 +14,6 @@ import ( "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/sqlstore/migrator" "github.com/grafana/grafana/pkg/util" - "gopkg.in/macaron.v1" ) const ( @@ -91,7 +90,7 @@ func getLibraryElement(dialect migrator.Dialect, session *sqlstore.DBSession, ui } // createLibraryElement adds a library element. -func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd CreateLibraryElementCommand) (LibraryElementDTO, error) { +func (l *LibraryElementService) createLibraryElement(c context.Context, signedInUser *models.SignedInUser, cmd CreateLibraryElementCommand) (LibraryElementDTO, error) { if err := l.requireSupportedElementKind(cmd.Kind); err != nil { return LibraryElementDTO{}, err } @@ -106,7 +105,7 @@ func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd C } } element := LibraryElement{ - OrgID: c.SignedInUser.OrgId, + OrgID: signedInUser.OrgId, FolderID: cmd.FolderID, UID: createUID, Name: cmd.Name, @@ -117,16 +116,16 @@ func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd C Created: time.Now(), Updated: time.Now(), - CreatedBy: c.SignedInUser.UserId, - UpdatedBy: c.SignedInUser.UserId, + CreatedBy: signedInUser.UserId, + UpdatedBy: signedInUser.UserId, } if err := syncFieldsWithModel(&element); err != nil { return LibraryElementDTO{}, err } - err := l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { - if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, cmd.FolderID); err != nil { + err := l.SQLStore.WithTransactionalDbSession(c, func(session *sqlstore.DBSession) error { + if err := l.requirePermissionsOnFolder(c, signedInUser, cmd.FolderID); err != nil { return err } if _, err := session.Insert(&element); err != nil { @@ -155,13 +154,13 @@ func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd C Updated: element.Updated, CreatedBy: LibraryElementDTOMetaUser{ ID: element.CreatedBy, - Name: c.SignedInUser.Login, - AvatarURL: dtos.GetGravatarUrl(c.SignedInUser.Email), + Name: signedInUser.Login, + AvatarURL: dtos.GetGravatarUrl(signedInUser.Email), }, UpdatedBy: LibraryElementDTOMetaUser{ ID: element.UpdatedBy, - Name: c.SignedInUser.Login, - AvatarURL: dtos.GetGravatarUrl(c.SignedInUser.Email), + Name: signedInUser.Login, + AvatarURL: dtos.GetGravatarUrl(signedInUser.Email), }, }, } @@ -170,13 +169,13 @@ func (l *LibraryElementService) createLibraryElement(c *models.ReqContext, cmd C } // deleteLibraryElement deletes a library element. -func (l *LibraryElementService) deleteLibraryElement(c *models.ReqContext, uid string) error { - return l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { - element, err := getLibraryElement(l.SQLStore.Dialect, session, uid, c.SignedInUser.OrgId) +func (l *LibraryElementService) deleteLibraryElement(c context.Context, signedInUser *models.SignedInUser, uid string) error { + return l.SQLStore.WithTransactionalDbSession(c, func(session *sqlstore.DBSession) error { + element, err := getLibraryElement(l.SQLStore.Dialect, session, uid, signedInUser.OrgId) if err != nil { return err } - if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, element.FolderID); err != nil { + if err := l.requirePermissionsOnFolder(c, signedInUser, element.FolderID); err != nil { return err } var connectionIDs []struct { @@ -204,9 +203,9 @@ func (l *LibraryElementService) deleteLibraryElement(c *models.ReqContext, uid s } // getLibraryElements gets a Library Element where param == value -func getLibraryElements(c *models.ReqContext, store *sqlstore.SQLStore, params []Pair) ([]LibraryElementDTO, error) { +func getLibraryElements(c context.Context, store *sqlstore.SQLStore, signedInUser *models.SignedInUser, params []Pair) ([]LibraryElementDTO, error) { libraryElements := make([]LibraryElementWithMeta, 0) - err := store.WithDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { + err := store.WithDbSession(c, func(session *sqlstore.DBSession) error { builder := sqlstore.SQLBuilder{} builder.Write(selectLibraryElementDTOWithMeta) builder.Write(", 'General' as folder_name ") @@ -220,8 +219,8 @@ func getLibraryElements(c *models.ReqContext, store *sqlstore.SQLStore, params [ builder.Write(getFromLibraryElementDTOWithMeta(store.Dialect)) builder.Write(" INNER JOIN dashboard AS dashboard on le.folder_id = dashboard.id AND le.folder_id <> 0") writeParamSelectorSQL(&builder, params...) - if c.SignedInUser.OrgRole != models.ROLE_ADMIN { - builder.WriteDashboardPermissionFilter(c.SignedInUser, models.PERMISSION_VIEW) + if signedInUser.OrgRole != models.ROLE_ADMIN { + builder.WriteDashboardPermissionFilter(signedInUser, models.PERMISSION_VIEW) } builder.Write(` OR dashboard.id=0`) if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElements); err != nil { @@ -274,8 +273,8 @@ func getLibraryElements(c *models.ReqContext, store *sqlstore.SQLStore, params [ } // getLibraryElementByUid gets a Library Element by uid. -func (l *LibraryElementService) getLibraryElementByUid(c *models.ReqContext, UID string) (LibraryElementDTO, error) { - libraryElements, err := getLibraryElements(c, l.SQLStore, []Pair{{key: "org_id", value: c.SignedInUser.OrgId}, {key: "uid", value: UID}}) +func (l *LibraryElementService) getLibraryElementByUid(c context.Context, signedInUser *models.SignedInUser, UID string) (LibraryElementDTO, error) { + libraryElements, err := getLibraryElements(c, l.SQLStore, signedInUser, []Pair{{key: "org_id", value: signedInUser.OrgId}, {key: "uid", value: UID}}) if err != nil { return LibraryElementDTO{}, err } @@ -287,12 +286,12 @@ func (l *LibraryElementService) getLibraryElementByUid(c *models.ReqContext, UID } // getLibraryElementByName gets a Library Element by name. -func (l *LibraryElementService) getLibraryElementsByName(c *models.ReqContext) ([]LibraryElementDTO, error) { - return getLibraryElements(c, l.SQLStore, []Pair{{"org_id", c.SignedInUser.OrgId}, {"name", macaron.Params(c.Req)[":name"]}}) +func (l *LibraryElementService) getLibraryElementsByName(c context.Context, signedInUser *models.SignedInUser, name string) ([]LibraryElementDTO, error) { + return getLibraryElements(c, l.SQLStore, signedInUser, []Pair{{"org_id", signedInUser.OrgId}, {"name", name}}) } // getAllLibraryElements gets all Library Elements. -func (l *LibraryElementService) getAllLibraryElements(c *models.ReqContext, query searchLibraryElementsQuery) (LibraryElementSearchResult, error) { +func (l *LibraryElementService) getAllLibraryElements(c context.Context, signedInUser *models.SignedInUser, query searchLibraryElementsQuery) (LibraryElementSearchResult, error) { elements := make([]LibraryElementWithMeta, 0) result := LibraryElementSearchResult{} if query.perPage <= 0 { @@ -309,14 +308,14 @@ func (l *LibraryElementService) getAllLibraryElements(c *models.ReqContext, quer if folderFilter.parseError != nil { return LibraryElementSearchResult{}, folderFilter.parseError } - err := l.SQLStore.WithDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { + err := l.SQLStore.WithDbSession(c, func(session *sqlstore.DBSession) error { builder := sqlstore.SQLBuilder{} if folderFilter.includeGeneralFolder { builder.Write(selectLibraryElementDTOWithMeta) builder.Write(", 'General' as folder_name ") builder.Write(", '' as folder_uid ") builder.Write(getFromLibraryElementDTOWithMeta(l.SQLStore.Dialect)) - builder.Write(` WHERE le.org_id=? AND le.folder_id=0`, c.SignedInUser.OrgId) + builder.Write(` WHERE le.org_id=? AND le.folder_id=0`, signedInUser.OrgId) writeKindSQL(query, &builder) writeSearchStringSQL(query, l.SQLStore, &builder) writeExcludeSQL(query, &builder) @@ -328,7 +327,7 @@ func (l *LibraryElementService) getAllLibraryElements(c *models.ReqContext, quer builder.Write(", dashboard.uid as folder_uid ") builder.Write(getFromLibraryElementDTOWithMeta(l.SQLStore.Dialect)) builder.Write(" INNER JOIN dashboard AS dashboard on le.folder_id = dashboard.id AND le.folder_id<>0") - builder.Write(` WHERE le.org_id=?`, c.SignedInUser.OrgId) + builder.Write(` WHERE le.org_id=?`, signedInUser.OrgId) writeKindSQL(query, &builder) writeSearchStringSQL(query, l.SQLStore, &builder) writeExcludeSQL(query, &builder) @@ -336,8 +335,8 @@ func (l *LibraryElementService) getAllLibraryElements(c *models.ReqContext, quer if err := folderFilter.writeFolderFilterSQL(false, &builder); err != nil { return err } - if c.SignedInUser.OrgRole != models.ROLE_ADMIN { - builder.WriteDashboardPermissionFilter(c.SignedInUser, models.PERMISSION_VIEW) + if signedInUser.OrgRole != models.ROLE_ADMIN { + builder.WriteDashboardPermissionFilter(signedInUser, models.PERMISSION_VIEW) } if query.sortDirection == search.SortAlphaDesc.Name { builder.Write(" ORDER BY 1 DESC") @@ -385,7 +384,7 @@ func (l *LibraryElementService) getAllLibraryElements(c *models.ReqContext, quer var libraryElements []LibraryElement countBuilder := sqlstore.SQLBuilder{} countBuilder.Write("SELECT * FROM library_element AS le") - countBuilder.Write(` WHERE le.org_id=?`, c.SignedInUser.OrgId) + countBuilder.Write(` WHERE le.org_id=?`, signedInUser.OrgId) writeKindSQL(query, &countBuilder) writeSearchStringSQL(query, l.SQLStore, &countBuilder) writeExcludeSQL(query, &countBuilder) @@ -434,13 +433,13 @@ func (l *LibraryElementService) handleFolderIDPatches(ctx context.Context, eleme } // patchLibraryElement updates a Library Element. -func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd patchLibraryElementCommand, uid string) (LibraryElementDTO, error) { +func (l *LibraryElementService) patchLibraryElement(c context.Context, signedInUser *models.SignedInUser, cmd patchLibraryElementCommand, uid string) (LibraryElementDTO, error) { var dto LibraryElementDTO if err := l.requireSupportedElementKind(cmd.Kind); err != nil { return LibraryElementDTO{}, err } - err := l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { - elementInDB, err := getLibraryElement(l.SQLStore.Dialect, session, uid, c.SignedInUser.OrgId) + err := l.SQLStore.WithTransactionalDbSession(c, func(session *sqlstore.DBSession) error { + elementInDB, err := getLibraryElement(l.SQLStore.Dialect, session, uid, signedInUser.OrgId) if err != nil { return err } @@ -457,7 +456,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa return errLibraryElementUIDTooLong } - _, err := getLibraryElement(l.SQLStore.Dialect, session, updateUID, c.SignedInUser.OrgId) + _, err := getLibraryElement(l.SQLStore.Dialect, session, updateUID, signedInUser.OrgId) if !errors.Is(err, ErrLibraryElementNotFound) { return errLibraryElementAlreadyExists } @@ -465,7 +464,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa var libraryElement = LibraryElement{ ID: elementInDB.ID, - OrgID: c.SignedInUser.OrgId, + OrgID: signedInUser.OrgId, FolderID: cmd.FolderID, UID: updateUID, Name: cmd.Name, @@ -477,7 +476,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa Created: elementInDB.Created, CreatedBy: elementInDB.CreatedBy, Updated: time.Now(), - UpdatedBy: c.SignedInUser.UserId, + UpdatedBy: signedInUser.UserId, } if cmd.Name == "" { @@ -486,7 +485,7 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa if cmd.Model == nil { libraryElement.Model = elementInDB.Model } - if err := l.handleFolderIDPatches(c.Req.Context(), &libraryElement, elementInDB.FolderID, cmd.FolderID, c.SignedInUser); err != nil { + if err := l.handleFolderIDPatches(c, &libraryElement, elementInDB.FolderID, cmd.FolderID, signedInUser); err != nil { return err } if err := syncFieldsWithModel(&libraryElement); err != nil { @@ -523,8 +522,8 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa }, UpdatedBy: LibraryElementDTOMetaUser{ ID: libraryElement.UpdatedBy, - Name: c.SignedInUser.Login, - AvatarURL: dtos.GetGravatarUrl(c.SignedInUser.Email), + Name: signedInUser.Login, + AvatarURL: dtos.GetGravatarUrl(signedInUser.Email), }, }, } @@ -536,10 +535,10 @@ func (l *LibraryElementService) patchLibraryElement(c *models.ReqContext, cmd pa } // getConnections gets all connections for a Library Element. -func (l *LibraryElementService) getConnections(c *models.ReqContext, uid string) ([]LibraryElementConnectionDTO, error) { +func (l *LibraryElementService) getConnections(c context.Context, signedInUser *models.SignedInUser, uid string) ([]LibraryElementConnectionDTO, error) { connections := make([]LibraryElementConnectionDTO, 0) - err := l.SQLStore.WithDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { - element, err := getLibraryElement(l.SQLStore.Dialect, session, uid, c.SignedInUser.OrgId) + err := l.SQLStore.WithDbSession(c, func(session *sqlstore.DBSession) error { + element, err := getLibraryElement(l.SQLStore.Dialect, session, uid, signedInUser.OrgId) if err != nil { return err } @@ -550,8 +549,8 @@ func (l *LibraryElementService) getConnections(c *models.ReqContext, uid string) builder.Write(" LEFT JOIN " + l.SQLStore.Dialect.Quote("user") + " AS u1 ON lec.created_by = u1.id") builder.Write(" INNER JOIN dashboard AS dashboard on lec.connection_id = dashboard.id") builder.Write(` WHERE lec.element_id=?`, element.ID) - if c.SignedInUser.OrgRole != models.ROLE_ADMIN { - builder.WriteDashboardPermissionFilter(c.SignedInUser, models.PERMISSION_VIEW) + if signedInUser.OrgRole != models.ROLE_ADMIN { + builder.WriteDashboardPermissionFilter(signedInUser, models.PERMISSION_VIEW) } if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElementConnections); err != nil { return err @@ -579,9 +578,9 @@ func (l *LibraryElementService) getConnections(c *models.ReqContext, uid string) } //getElementsForDashboardID gets all elements for a specific dashboard -func (l *LibraryElementService) getElementsForDashboardID(c *models.ReqContext, dashboardID int64) (map[string]LibraryElementDTO, error) { +func (l *LibraryElementService) getElementsForDashboardID(c context.Context, dashboardID int64) (map[string]LibraryElementDTO, error) { libraryElementMap := make(map[string]LibraryElementDTO) - err := l.SQLStore.WithDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { + err := l.SQLStore.WithDbSession(c, func(session *sqlstore.DBSession) error { var libraryElements []LibraryElementWithMeta sql := selectLibraryElementDTOWithMeta + ", coalesce(dashboard.title, 'General') AS folder_name" + @@ -634,18 +633,18 @@ func (l *LibraryElementService) getElementsForDashboardID(c *models.ReqContext, } // connectElementsToDashboardID adds connections for all elements Library Elements in a Dashboard. -func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContext, elementUIDs []string, dashboardID int64) error { - err := l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { +func (l *LibraryElementService) connectElementsToDashboardID(c context.Context, signedInUser *models.SignedInUser, elementUIDs []string, dashboardID int64) error { + err := l.SQLStore.WithTransactionalDbSession(c, func(session *sqlstore.DBSession) error { _, err := session.Exec("DELETE FROM "+models.LibraryElementConnectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID) if err != nil { return err } for _, elementUID := range elementUIDs { - element, err := getLibraryElement(l.SQLStore.Dialect, session, elementUID, c.SignedInUser.OrgId) + element, err := getLibraryElement(l.SQLStore.Dialect, session, elementUID, signedInUser.OrgId) if err != nil { return err } - if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, element.FolderID); err != nil { + if err := l.requirePermissionsOnFolder(c, signedInUser, element.FolderID); err != nil { return err } @@ -654,7 +653,7 @@ func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContex Kind: 1, ConnectionID: dashboardID, Created: time.Now(), - CreatedBy: c.SignedInUser.UserId, + CreatedBy: signedInUser.UserId, } if _, err := session.Insert(&connection); err != nil { if l.SQLStore.Dialect.IsUniqueConstraintViolation(err) { @@ -670,8 +669,8 @@ func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContex } // disconnectElementsFromDashboardID deletes connections for all Library Elements in a Dashboard. -func (l *LibraryElementService) disconnectElementsFromDashboardID(c *models.ReqContext, dashboardID int64) error { - return l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error { +func (l *LibraryElementService) disconnectElementsFromDashboardID(c context.Context, dashboardID int64) error { + return l.SQLStore.WithTransactionalDbSession(c, func(session *sqlstore.DBSession) error { _, err := session.Exec("DELETE FROM "+models.LibraryElementConnectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID) if err != nil { return err @@ -681,12 +680,12 @@ func (l *LibraryElementService) disconnectElementsFromDashboardID(c *models.ReqC } // deleteLibraryElementsInFolderUID deletes all Library Elements in a folder. -func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqContext, folderUID string) error { - return l.SQLStore.WithTransactionalDbSession(c.Req.Context(), func(session *sqlstore.DBSession) error { +func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c context.Context, signedInUser *models.SignedInUser, folderUID string) error { + return l.SQLStore.WithTransactionalDbSession(c, func(session *sqlstore.DBSession) error { var folderUIDs []struct { ID int64 `xorm:"id"` } - err := session.SQL("SELECT id from dashboard WHERE uid=? AND org_id=? AND is_folder=?", folderUID, c.SignedInUser.OrgId, l.SQLStore.Dialect.BooleanStr(true)).Find(&folderUIDs) + err := session.SQL("SELECT id from dashboard WHERE uid=? AND org_id=? AND is_folder=?", folderUID, signedInUser.OrgId, l.SQLStore.Dialect.BooleanStr(true)).Find(&folderUIDs) if err != nil { return err } @@ -695,7 +694,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo } folderID := folderUIDs[0].ID - if err := l.requirePermissionsOnFolder(c.Req.Context(), c.SignedInUser, folderID); err != nil { + if err := l.requirePermissionsOnFolder(c, signedInUser, folderID); err != nil { return err } var connectionIDs []struct { @@ -704,7 +703,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo sql := "SELECT lec.connection_id FROM library_element AS le" sql += " INNER JOIN " + models.LibraryElementConnectionTableName + " AS lec on le.id = lec.element_id" sql += " WHERE le.folder_id=? AND le.org_id=?" - err = session.SQL(sql, folderID, c.SignedInUser.OrgId).Find(&connectionIDs) + err = session.SQL(sql, folderID, signedInUser.OrgId).Find(&connectionIDs) if err != nil { return err } @@ -715,7 +714,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo var elementIDs []struct { ID int64 `xorm:"id"` } - err = session.SQL("SELECT id from library_element WHERE folder_id=? AND org_id=?", folderID, c.SignedInUser.OrgId).Find(&elementIDs) + err = session.SQL("SELECT id from library_element WHERE folder_id=? AND org_id=?", folderID, signedInUser.OrgId).Find(&elementIDs) if err != nil { return err } @@ -725,7 +724,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo return err } } - if _, err := session.Exec("DELETE FROM library_element WHERE folder_id=? AND org_id=?", folderID, c.SignedInUser.OrgId); err != nil { + if _, err := session.Exec("DELETE FROM library_element WHERE folder_id=? AND org_id=?", folderID, signedInUser.OrgId); err != nil { return err } diff --git a/pkg/services/libraryelements/guard.go b/pkg/services/libraryelements/guard.go index 9745cefd887..8d483488140 100644 --- a/pkg/services/libraryelements/guard.go +++ b/pkg/services/libraryelements/guard.go @@ -39,7 +39,7 @@ func (l *LibraryElementService) requirePermissionsOnFolder(ctx context.Context, return err } - g := guardian.New(folder.Id, user.OrgId, user) + g := guardian.New(ctx, folder.Id, user.OrgId, user) canEdit, err := g.CanEdit() if err != nil { diff --git a/pkg/services/libraryelements/libraryelements.go b/pkg/services/libraryelements/libraryelements.go index 1dedb8e640f..302b31a1b59 100644 --- a/pkg/services/libraryelements/libraryelements.go +++ b/pkg/services/libraryelements/libraryelements.go @@ -1,6 +1,8 @@ package libraryelements import ( + "context" + "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" @@ -21,12 +23,12 @@ func ProvideService(cfg *setting.Cfg, sqlStore *sqlstore.SQLStore, routeRegister // Service is a service for operating on library elements. type Service interface { - CreateElement(c *models.ReqContext, cmd CreateLibraryElementCommand) (LibraryElementDTO, error) - GetElement(c *models.ReqContext, UID string) (LibraryElementDTO, error) - GetElementsForDashboard(c *models.ReqContext, dashboardID int64) (map[string]LibraryElementDTO, error) - ConnectElementsToDashboard(c *models.ReqContext, elementUIDs []string, dashboardID int64) error - DisconnectElementsFromDashboard(c *models.ReqContext, dashboardID int64) error - DeleteLibraryElementsInFolder(c *models.ReqContext, folderUID string) error + CreateElement(c context.Context, signedInUser *models.SignedInUser, cmd CreateLibraryElementCommand) (LibraryElementDTO, error) + GetElement(c context.Context, signedInUser *models.SignedInUser, UID string) (LibraryElementDTO, error) + GetElementsForDashboard(c context.Context, dashboardID int64) (map[string]LibraryElementDTO, error) + ConnectElementsToDashboard(c context.Context, signedInUser *models.SignedInUser, elementUIDs []string, dashboardID int64) error + DisconnectElementsFromDashboard(c context.Context, dashboardID int64) error + DeleteLibraryElementsInFolder(c context.Context, signedInUser *models.SignedInUser, folderUID string) error } // LibraryElementService is the service for the Library Element feature. @@ -38,31 +40,31 @@ type LibraryElementService struct { } // CreateElement creates a Library Element. -func (l *LibraryElementService) CreateElement(c *models.ReqContext, cmd CreateLibraryElementCommand) (LibraryElementDTO, error) { - return l.createLibraryElement(c, cmd) +func (l *LibraryElementService) CreateElement(c context.Context, signedInUser *models.SignedInUser, cmd CreateLibraryElementCommand) (LibraryElementDTO, error) { + return l.createLibraryElement(c, signedInUser, cmd) } // GetElement gets an element from a UID. -func (l *LibraryElementService) GetElement(c *models.ReqContext, UID string) (LibraryElementDTO, error) { - return l.getLibraryElementByUid(c, UID) +func (l *LibraryElementService) GetElement(c context.Context, signedInUser *models.SignedInUser, UID string) (LibraryElementDTO, error) { + return l.getLibraryElementByUid(c, signedInUser, UID) } // GetElementsForDashboard gets all connected elements for a specific dashboard. -func (l *LibraryElementService) GetElementsForDashboard(c *models.ReqContext, dashboardID int64) (map[string]LibraryElementDTO, error) { +func (l *LibraryElementService) GetElementsForDashboard(c context.Context, dashboardID int64) (map[string]LibraryElementDTO, error) { return l.getElementsForDashboardID(c, dashboardID) } // ConnectElementsToDashboard connects elements to a specific dashboard. -func (l *LibraryElementService) ConnectElementsToDashboard(c *models.ReqContext, elementUIDs []string, dashboardID int64) error { - return l.connectElementsToDashboardID(c, elementUIDs, dashboardID) +func (l *LibraryElementService) ConnectElementsToDashboard(c context.Context, signedInUser *models.SignedInUser, elementUIDs []string, dashboardID int64) error { + return l.connectElementsToDashboardID(c, signedInUser, elementUIDs, dashboardID) } // DisconnectElementsFromDashboard disconnects elements from a specific dashboard. -func (l *LibraryElementService) DisconnectElementsFromDashboard(c *models.ReqContext, dashboardID int64) error { +func (l *LibraryElementService) DisconnectElementsFromDashboard(c context.Context, dashboardID int64) error { return l.disconnectElementsFromDashboardID(c, dashboardID) } // DeleteLibraryElementsInFolder deletes all elements for a specific folder. -func (l *LibraryElementService) DeleteLibraryElementsInFolder(c *models.ReqContext, folderUID string) error { - return l.deleteLibraryElementsInFolderUID(c, folderUID) +func (l *LibraryElementService) DeleteLibraryElementsInFolder(c context.Context, signedInUser *models.SignedInUser, folderUID string) error { + return l.deleteLibraryElementsInFolderUID(c, signedInUser, folderUID) } diff --git a/pkg/services/libraryelements/libraryelements_delete_test.go b/pkg/services/libraryelements/libraryelements_delete_test.go index 3f5d01fdf48..191bd7559c8 100644 --- a/pkg/services/libraryelements/libraryelements_delete_test.go +++ b/pkg/services/libraryelements/libraryelements_delete_test.go @@ -67,7 +67,7 @@ func TestDeleteLibraryElement(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.service.ConnectElementsToDashboard(sc.reqContext, []string{sc.initialResult.Result.UID}, dashInDB.Id) + err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) sc.ctx.Req = macaron.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID}) diff --git a/pkg/services/libraryelements/libraryelements_get_test.go b/pkg/services/libraryelements/libraryelements_get_test.go index 6fd7585e14c..bfe375adb73 100644 --- a/pkg/services/libraryelements/libraryelements_get_test.go +++ b/pkg/services/libraryelements/libraryelements_get_test.go @@ -120,7 +120,7 @@ func TestGetLibraryElement(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.service.ConnectElementsToDashboard(sc.reqContext, []string{sc.initialResult.Result.UID}, dashInDB.Id) + err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) expected := func(res libraryElementResult) libraryElementResult { diff --git a/pkg/services/libraryelements/libraryelements_test.go b/pkg/services/libraryelements/libraryelements_test.go index ac296bc9eab..28334377e53 100644 --- a/pkg/services/libraryelements/libraryelements_test.go +++ b/pkg/services/libraryelements/libraryelements_test.go @@ -59,10 +59,10 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.service.ConnectElementsToDashboard(sc.reqContext, []string{sc.initialResult.Result.UID}, dashInDB.Id) + err := sc.service.ConnectElementsToDashboard(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, []string{sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) - err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext, sc.folder.Uid) + err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.Uid) require.EqualError(t, err, ErrFolderHasConnectedLibraryElements.Error()) }) @@ -80,7 +80,7 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) { require.NotNil(t, result.Result) require.Equal(t, 2, len(result.Result.Elements)) - err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext, sc.folder.Uid) + err = sc.service.DeleteLibraryElementsInFolder(sc.reqContext.Req.Context(), sc.reqContext.SignedInUser, sc.folder.Uid) require.NoError(t, err) resp = sc.service.getAllHandler(sc.reqContext) require.Equal(t, 200, resp.Status()) diff --git a/pkg/services/librarypanels/librarypanels.go b/pkg/services/librarypanels/librarypanels.go index ba53ac8f7f4..c23268a03a8 100644 --- a/pkg/services/librarypanels/librarypanels.go +++ b/pkg/services/librarypanels/librarypanels.go @@ -1,6 +1,7 @@ package librarypanels import ( + "context" "encoding/json" "errors" "fmt" @@ -27,10 +28,10 @@ func ProvideService(cfg *setting.Cfg, sqlStore *sqlstore.SQLStore, routeRegister // Service is a service for operating on library panels. type Service interface { - LoadLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard) error + LoadLibraryPanelsForDashboard(c context.Context, dash *models.Dashboard) error CleanLibraryPanelsForDashboard(dash *models.Dashboard) error - ConnectLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard) error - ImportLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard, folderID int64) error + ConnectLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard) error + ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard, folderID int64) error } // LibraryPanelService is the service for the Panel Library feature. @@ -44,7 +45,7 @@ type LibraryPanelService struct { // LoadLibraryPanelsForDashboard loops through all panels in dashboard JSON and replaces any library panel JSON // with JSON stored for library panel in db. -func (lps *LibraryPanelService) LoadLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard) error { +func (lps *LibraryPanelService) LoadLibraryPanelsForDashboard(c context.Context, dash *models.Dashboard) error { elements, err := lps.LibraryElementService.GetElementsForDashboard(c, dash.Id) if err != nil { return err @@ -195,7 +196,7 @@ func cleanLibraryPanelsRecursively(parent *simplejson.Json) error { } // ConnectLibraryPanelsForDashboard loops through all panels in dashboard JSON and connects any library panels to the dashboard. -func (lps *LibraryPanelService) ConnectLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard) error { +func (lps *LibraryPanelService) ConnectLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard) error { panels := dash.Data.Get("panels").MustArray() libraryPanels := make(map[string]string) err := connectLibraryPanelsRecursively(c, panels, libraryPanels) @@ -208,14 +209,14 @@ func (lps *LibraryPanelService) ConnectLibraryPanelsForDashboard(c *models.ReqCo elementUIDs = append(elementUIDs, libraryPanel) } - return lps.LibraryElementService.ConnectElementsToDashboard(c, elementUIDs, dash.Id) + return lps.LibraryElementService.ConnectElementsToDashboard(c, signedInUser, elementUIDs, dash.Id) } func isLibraryPanelOrRow(panel *simplejson.Json, panelType string) bool { return panel.Interface() != nil || panelType == "row" } -func connectLibraryPanelsRecursively(c *models.ReqContext, panels []interface{}, libraryPanels map[string]string) error { +func connectLibraryPanelsRecursively(c context.Context, panels []interface{}, libraryPanels map[string]string) error { for _, panel := range panels { panelAsJSON := simplejson.NewFromAny(panel) libraryPanel := panelAsJSON.Get("libraryPanel") @@ -249,11 +250,11 @@ func connectLibraryPanelsRecursively(c *models.ReqContext, panels []interface{}, } // ImportLibraryPanelsForDashboard loops through all panels in dashboard JSON and creates any missing library panels in the database. -func (lps *LibraryPanelService) ImportLibraryPanelsForDashboard(c *models.ReqContext, dash *models.Dashboard, folderID int64) error { - return importLibraryPanelsRecursively(c, lps.LibraryElementService, dash.Data, folderID) +func (lps *LibraryPanelService) ImportLibraryPanelsForDashboard(c context.Context, signedInUser *models.SignedInUser, dash *models.Dashboard, folderID int64) error { + return importLibraryPanelsRecursively(c, lps.LibraryElementService, signedInUser, dash.Data, folderID) } -func importLibraryPanelsRecursively(c *models.ReqContext, service libraryelements.Service, parent *simplejson.Json, folderID int64) error { +func importLibraryPanelsRecursively(c context.Context, service libraryelements.Service, signedInUser *models.SignedInUser, parent *simplejson.Json, folderID int64) error { panels := parent.Get("panels").MustArray() for _, panel := range panels { panelAsJSON := simplejson.NewFromAny(panel) @@ -265,7 +266,7 @@ func importLibraryPanelsRecursively(c *models.ReqContext, service libraryelement // we have a row if panelType == "row" { - err := importLibraryPanelsRecursively(c, service, panelAsJSON, folderID) + err := importLibraryPanelsRecursively(c, service, signedInUser, panelAsJSON, folderID) if err != nil { return err } @@ -282,7 +283,7 @@ func importLibraryPanelsRecursively(c *models.ReqContext, service libraryelement return errLibraryPanelHeaderNameMissing } - _, err := service.GetElement(c, UID) + _, err := service.GetElement(c, signedInUser, UID) if err == nil { continue } @@ -304,7 +305,7 @@ func importLibraryPanelsRecursively(c *models.ReqContext, service libraryelement Kind: int64(models.PanelElement), UID: UID, } - _, err = service.CreateElement(c, cmd) + _, err = service.CreateElement(c, signedInUser, cmd) if err != nil { return err } diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index ac82c2404bb..8ff38c5860a 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -4,13 +4,11 @@ import ( "context" "encoding/json" "fmt" - "net/http" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" - "gopkg.in/macaron.v1" "github.com/grafana/grafana/pkg/components/simplejson" dboards "github.com/grafana/grafana/pkg/dashboards" @@ -58,10 +56,10 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.elementService.ConnectElementsToDashboard(sc.reqContext, []string{sc.initialResult.Result.UID}, dashInDB.Id) + err := sc.elementService.ConnectElementsToDashboard(sc.ctx, sc.user, []string{sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) - err = sc.service.LoadLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err = sc.service.LoadLibraryPanelsForDashboard(sc.ctx, dashInDB) require.NoError(t, err) expectedJSON := map[string]interface{}{ "title": "Testing LoadLibraryPanelsForDashboard", @@ -138,7 +136,7 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { `), Kind: int64(models.PanelElement), } - outsidePanel, err := sc.elementService.CreateElement(sc.reqContext, cmd) + outsidePanel, err := sc.elementService.CreateElement(sc.ctx, sc.user, cmd) require.NoError(t, err) dashJSON := map[string]interface{}{ "panels": []interface{}{ @@ -212,10 +210,10 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err = sc.elementService.ConnectElementsToDashboard(sc.reqContext, []string{outsidePanel.UID, sc.initialResult.Result.UID}, dashInDB.Id) + err = sc.elementService.ConnectElementsToDashboard(sc.ctx, sc.user, []string{outsidePanel.UID, sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) - err = sc.service.LoadLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err = sc.service.LoadLibraryPanelsForDashboard(sc.ctx, dashInDB) require.NoError(t, err) expectedJSON := map[string]interface{}{ "title": "Testing LoadLibraryPanelsForDashboard", @@ -367,10 +365,10 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.elementService.ConnectElementsToDashboard(sc.reqContext, []string{sc.initialResult.Result.UID}, dashInDB.Id) + err := sc.elementService.ConnectElementsToDashboard(sc.ctx, sc.user, []string{sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) - err = sc.service.LoadLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err = sc.service.LoadLibraryPanelsForDashboard(sc.ctx, dashInDB) require.EqualError(t, err, errLibraryPanelHeaderUIDMissing.Error()) }) @@ -408,7 +406,7 @@ func TestLoadLibraryPanelsForDashboard(t *testing.T) { } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.service.LoadLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err := sc.service.LoadLibraryPanelsForDashboard(sc.ctx, dashInDB) require.NoError(t, err) expectedJSON := map[string]interface{}{ "title": "Testing LoadLibraryPanelsForDashboard", @@ -538,7 +536,7 @@ func TestCleanLibraryPanelsForDashboard(t *testing.T) { `), Kind: int64(models.PanelElement), } - outsidePanel, err := sc.elementService.CreateElement(sc.reqContext, cmd) + outsidePanel, err := sc.elementService.CreateElement(sc.ctx, sc.user, cmd) require.NoError(t, err) dashJSON := map[string]interface{}{ "panels": []interface{}{ @@ -804,10 +802,10 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.service.ConnectLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.NoError(t, err) - elements, err := sc.elementService.GetElementsForDashboard(sc.reqContext, dashInDB.Id) + elements, err := sc.elementService.GetElementsForDashboard(sc.ctx, dashInDB.Id) require.NoError(t, err) require.Len(t, elements, 1) require.Equal(t, sc.initialResult.Result.UID, elements[sc.initialResult.Result.UID].UID) @@ -829,7 +827,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { `), Kind: int64(models.PanelElement), } - outsidePanel, err := sc.elementService.CreateElement(sc.reqContext, cmd) + outsidePanel, err := sc.elementService.CreateElement(sc.ctx, sc.user, cmd) require.NoError(t, err) dashJSON := map[string]interface{}{ "panels": []interface{}{ @@ -904,10 +902,10 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err = sc.service.ConnectLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err = sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.NoError(t, err) - elements, err := sc.elementService.GetElementsForDashboard(sc.reqContext, dashInDB.Id) + elements, err := sc.elementService.GetElementsForDashboard(sc.ctx, dashInDB.Id) require.NoError(t, err) require.Len(t, elements, 2) require.Equal(t, sc.initialResult.Result.UID, elements[sc.initialResult.Result.UID].UID) @@ -950,13 +948,13 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err := sc.service.ConnectLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err := sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.EqualError(t, err, errLibraryPanelHeaderUIDMissing.Error()) }) scenarioWithLibraryPanel(t, "When an admin tries to store a dashboard with unused/removed library panels, it should disconnect unused/removed library panels", func(t *testing.T, sc scenarioContext) { - unused, err := sc.elementService.CreateElement(sc.reqContext, libraryelements.CreateLibraryElementCommand{ + unused, err := sc.elementService.CreateElement(sc.ctx, sc.user, libraryelements.CreateLibraryElementCommand{ FolderID: sc.folder.Id, Name: "Unused Libray Panel", Model: []byte(` @@ -1006,7 +1004,7 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - err = sc.elementService.ConnectElementsToDashboard(sc.reqContext, []string{sc.initialResult.Result.UID}, dashInDB.Id) + err = sc.elementService.ConnectElementsToDashboard(sc.ctx, sc.user, []string{sc.initialResult.Result.UID}, dashInDB.Id) require.NoError(t, err) panelJSON := []interface{}{ @@ -1037,10 +1035,10 @@ func TestConnectLibraryPanelsForDashboard(t *testing.T) { }, } dashInDB.Data.Set("panels", panelJSON) - err = sc.service.ConnectLibraryPanelsForDashboard(sc.reqContext, dashInDB) + err = sc.service.ConnectLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB) require.NoError(t, err) - elements, err := sc.elementService.GetElementsForDashboard(sc.reqContext, dashInDB.Id) + elements, err := sc.elementService.GetElementsForDashboard(sc.ctx, dashInDB.Id) require.NoError(t, err) require.Len(t, elements, 1) require.Equal(t, sc.initialResult.Result.UID, elements[sc.initialResult.Result.UID].UID) @@ -1089,13 +1087,13 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - _, err := sc.elementService.GetElement(sc.reqContext, missingUID) + _, err := sc.elementService.GetElement(sc.ctx, sc.user, missingUID) require.EqualError(t, err, libraryelements.ErrLibraryElementNotFound.Error()) - err = sc.service.ImportLibraryPanelsForDashboard(sc.reqContext, dashInDB, 0) + err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB, 0) require.NoError(t, err) - element, err := sc.elementService.GetElement(sc.reqContext, missingUID) + element, err := sc.elementService.GetElement(sc.ctx, sc.user, missingUID) require.NoError(t, err) var expected = getExpected(t, element, missingUID, missingName, missingModel) var result = toLibraryElement(t, element) @@ -1138,13 +1136,13 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - _, err := sc.elementService.GetElement(sc.reqContext, existingUID) + _, err := sc.elementService.GetElement(sc.ctx, sc.user, existingUID) require.NoError(t, err) - err = sc.service.ImportLibraryPanelsForDashboard(sc.reqContext, dashInDB, sc.folder.Id) + err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB, sc.folder.Id) require.NoError(t, err) - element, err := sc.elementService.GetElement(sc.reqContext, existingUID) + element, err := sc.elementService.GetElement(sc.ctx, sc.user, existingUID) require.NoError(t, err) var expected = getExpected(t, element, existingUID, existingName, sc.initialResult.Result.Model) expected.FolderID = sc.initialResult.Result.FolderID @@ -1238,15 +1236,15 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) { Data: simplejson.NewFromAny(dashJSON), } dashInDB := createDashboard(t, sc.sqlStore, sc.user, &dash, sc.folder.Id) - _, err := sc.elementService.GetElement(sc.reqContext, outsideUID) + _, err := sc.elementService.GetElement(sc.ctx, sc.user, outsideUID) require.EqualError(t, err, libraryelements.ErrLibraryElementNotFound.Error()) - _, err = sc.elementService.GetElement(sc.reqContext, insideUID) + _, err = sc.elementService.GetElement(sc.ctx, sc.user, insideUID) require.EqualError(t, err, libraryelements.ErrLibraryElementNotFound.Error()) - err = sc.service.ImportLibraryPanelsForDashboard(sc.reqContext, dashInDB, 0) + err = sc.service.ImportLibraryPanelsForDashboard(sc.ctx, sc.user, dashInDB, 0) require.NoError(t, err) - element, err := sc.elementService.GetElement(sc.reqContext, outsideUID) + element, err := sc.elementService.GetElement(sc.ctx, sc.user, outsideUID) require.NoError(t, err) expected := getExpected(t, element, outsideUID, outsideName, outsideModel) result := toLibraryElement(t, element) @@ -1254,7 +1252,7 @@ func TestImportLibraryPanelsForDashboard(t *testing.T) { t.Fatalf("Result mismatch (-want +got):\n%s", diff) } - element, err = sc.elementService.GetElement(sc.reqContext, insideUID) + element, err = sc.elementService.GetElement(sc.ctx, sc.user, insideUID) require.NoError(t, err) expected = getExpected(t, element, insideUID, insideName, insideModel) result = toLibraryElement(t, element) @@ -1318,11 +1316,10 @@ type libraryPanelResult struct { } type scenarioContext struct { - ctx *macaron.Context + ctx context.Context service Service elementService libraryelements.Service - reqContext *models.ReqContext - user models.SignedInUser + user *models.SignedInUser folder *models.Folder initialResult libraryPanelResult sqlStore *sqlstore.SQLStore @@ -1407,13 +1404,13 @@ func getExpected(t *testing.T, res libraryelements.LibraryElementDTO, UID string } } -func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user models.SignedInUser, dash *models.Dashboard, folderID int64) *models.Dashboard { +func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user *models.SignedInUser, dash *models.Dashboard, folderID int64) *models.Dashboard { dash.FolderId = folderID dashItem := &dashboards.SaveDashboardDTO{ Dashboard: dash, Message: "", OrgId: user.OrgId, - User: &user, + User: user, Overwrite: false, } origUpdateAlerting := dashboards.UpdateAlerting @@ -1431,11 +1428,11 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user models.Sign return dashboard } -func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string, user models.SignedInUser, +func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string, user *models.SignedInUser, items []folderACLItem) *models.Folder { t.Helper() - s := dashboards.NewFolderService(user.OrgId, &user, sqlStore) + s := dashboards.NewFolderService(user.OrgId, user, sqlStore) t.Logf("Creating folder with title and UID %q", title) folder, err := s.CreateFolder(context.Background(), title, title) require.NoError(t, err) @@ -1487,7 +1484,7 @@ func scenarioWithLibraryPanel(t *testing.T, desc string, fn func(t *testing.T, s `), Kind: int64(models.PanelElement), } - resp, err := sc.elementService.CreateElement(sc.reqContext, command) + resp, err := sc.elementService.CreateElement(sc.ctx, sc.user, command) require.NoError(t, err) var model map[string]interface{} err = json.Unmarshal(resp.Model, &model) @@ -1518,7 +1515,6 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo t.Helper() t.Run(desc, func(t *testing.T) { - ctx := macaron.Context{Req: &http.Request{}} cfg := setting.NewCfg() orgID := int64(1) role := models.ROLE_ADMIN @@ -1533,7 +1529,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo LibraryElementService: &elementService, } - user := models.SignedInUser{ + user := &models.SignedInUser{ UserId: 1, Name: "Signed In User", Login: "signed_in_user", @@ -1556,14 +1552,10 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo sc := scenarioContext{ user: user, - ctx: &ctx, + ctx: context.Background(), service: &service, elementService: &elementService, sqlStore: sqlStore, - reqContext: &models.ReqContext{ - Context: &ctx, - SignedInUser: &user, - }, } sc.folder = createFolderWithACL(t, sc.sqlStore, "ScenarioFolder", sc.user, []folderACLItem{}) diff --git a/pkg/services/live/features/dashboard.go b/pkg/services/live/features/dashboard.go index 600f3918a67..64f186eb9ad 100644 --- a/pkg/services/live/features/dashboard.go +++ b/pkg/services/live/features/dashboard.go @@ -68,7 +68,7 @@ func (h *DashboardHandler) OnSubscribe(ctx context.Context, user *models.SignedI } dash := query.Result - guard := guardian.New(dash.Id, user.OrgId, user) + guard := guardian.New(ctx, dash.Id, user.OrgId, user) if canView, err := guard.CanView(); err != nil || !canView { return models.SubscribeReply{}, backend.SubscribeStreamStatusPermissionDenied, nil } @@ -114,7 +114,7 @@ func (h *DashboardHandler) OnPublish(ctx context.Context, user *models.SignedInU return models.PublishReply{}, backend.PublishStreamStatusNotFound, nil } - guard := guardian.New(query.Result.Id, user.OrgId, user) + guard := guardian.New(ctx, query.Result.Id, user.OrgId, user) canEdit, err := guard.CanEdit() if err != nil { return models.PublishReply{}, backend.PublishStreamStatusNotFound, fmt.Errorf("internal error") diff --git a/pkg/services/live/live.go b/pkg/services/live/live.go index e683ded4074..f1e46000777 100644 --- a/pkg/services/live/live.go +++ b/pkg/services/live/live.go @@ -11,11 +11,17 @@ import ( "sync" "time" + "github.com/centrifugal/centrifuge" + "github.com/go-redis/redis/v8" + "github.com/gobwas/glob" + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana-plugin-sdk-go/live" "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/infra/localcache" "github.com/grafana/grafana/pkg/infra/log" + "github.com/grafana/grafana/pkg/infra/usagestats" "github.com/grafana/grafana/pkg/middleware" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins/manager" @@ -35,13 +41,8 @@ import ( "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/cloudwatch" "github.com/grafana/grafana/pkg/util" - - "github.com/centrifugal/centrifuge" - "github.com/gobwas/glob" - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana-plugin-sdk-go/live" + "golang.org/x/sync/errgroup" "gopkg.in/macaron.v1" - "gopkg.in/redis.v5" ) var ( @@ -59,7 +60,8 @@ type CoreGrafanaScope struct { func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, routeRegister routing.RouteRegister, logsService *cloudwatch.LogsService, pluginManager *manager.PluginManager, cacheService *localcache.CacheService, - dataSourceCache datasources.CacheService, sqlStore *sqlstore.SQLStore) (*GrafanaLive, error) { + dataSourceCache datasources.CacheService, sqlStore *sqlstore.SQLStore, + usageStatsService usagestats.Service) (*GrafanaLive, error) { g := &GrafanaLive{ Cfg: cfg, PluginContextProvider: plugCtxProvider, @@ -73,6 +75,7 @@ func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, r GrafanaScope: CoreGrafanaScope{ Features: make(map[string]models.ChannelHandlerFactory), }, + usageStatsService: usageStatsService, } logger.Debug("GrafanaLive initialization", "ha", g.IsHA()) @@ -146,7 +149,7 @@ func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, r redisClient := redis.NewClient(&redis.Options{ Addr: g.Cfg.LiveHAEngineAddress, }) - cmd := redisClient.Ping() + cmd := redisClient.Ping(context.TODO()) if _, err := cmd.Result(); err != nil { return nil, fmt.Errorf("error pinging Redis: %v", err) } @@ -325,6 +328,8 @@ func ProvideService(plugCtxProvider *plugincontext.Provider, cfg *setting.Cfg, r group.Get("/push/:streamId", g.pushWebsocketHandler) }, middleware.ReqOrgAdmin) + g.registerUsageMetrics() + return g, nil } @@ -364,11 +369,9 @@ type GrafanaLive struct { contextGetter *liveplugin.ContextGetter runStreamManager *runstream.Manager storage *database.Storage -} -type UsageStats struct { - NumClients int - NumUsers int + usageStatsService usagestats.Service + usageStats usageStats } func (g *GrafanaLive) getStreamPlugin(pluginID string) (backend.StreamHandler, error) { @@ -384,11 +387,30 @@ func (g *GrafanaLive) getStreamPlugin(pluginID string) (backend.StreamHandler, e } func (g *GrafanaLive) Run(ctx context.Context) error { + eGroup, eCtx := errgroup.WithContext(ctx) + + eGroup.Go(func() error { + updateStatsTicker := time.NewTicker(time.Minute * 30) + defer updateStatsTicker.Stop() + + for { + select { + case <-updateStatsTicker.C: + g.sampleLiveStats() + case <-ctx.Done(): + return ctx.Err() + } + } + }) + if g.runStreamManager != nil { // Only run stream manager if GrafanaLive properly initialized. - return g.runStreamManager.Run(ctx) + eGroup.Go(func() error { + return g.runStreamManager.Run(eCtx) + }) } - return nil + + return eGroup.Wait() } func (g *GrafanaLive) ChannelRuleStorage() pipeline.RuleStorage { @@ -781,13 +803,6 @@ func (g *GrafanaLive) ClientCount(orgID int64, channel string) (int, error) { return len(p.Presence), nil } -func (g *GrafanaLive) UsageStats() UsageStats { - clients := g.node.Hub().NumClients() - users := g.node.Hub().NumUsers() - - return UsageStats{NumClients: clients, NumUsers: users} -} - func (g *GrafanaLive) HandleHTTPPublish(ctx *models.ReqContext, cmd dtos.LivePublishCmd) response.Response { addr, err := live.ParseChannel(cmd.Channel) if err != nil { @@ -868,6 +883,98 @@ func (g *GrafanaLive) HandleChannelRulesListHTTP(c *models.ReqContext) response. }) } +type configInfo struct { + Type string `json:"type"` + Description string `json:"description"` + Example interface{} `json:"example,omitempty"` +} + +// HandlePipelineEntitiesListHTTP ... +func (g *GrafanaLive) HandlePipelineEntitiesListHTTP(_ *models.ReqContext) response.Response { + return response.JSON(http.StatusOK, util.DynMap{ + "subscribers": []configInfo{ + { + Type: pipeline.SubscriberTypeBuiltin, + Description: "apply builtin feature subscribe logic", + }, + { + Type: pipeline.SubscriberTypeManagedStream, + Description: "apply managed stream subscribe logic", + }, + { + Type: pipeline.SubscriberTypeMultiple, + Description: "apply multiple subscribers", + }, + { + Type: pipeline.SubscriberTypeAuthorizeRole, + Description: "authorize user role", + }, + }, + "outputs": []configInfo{ + { + Type: pipeline.OutputTypeManagedStream, + Description: "Only send schema when structure changes. Note this also requires a matching subscriber", + Example: pipeline.ManagedStreamOutputConfig{}, + }, + { + Type: pipeline.OutputTypeMultiple, + Description: "Send the output to multiple destinations", + Example: pipeline.MultipleOutputterConfig{}, + }, + { + Type: pipeline.OutputTypeConditional, + Description: "send to an output depending on frame values", + Example: pipeline.ConditionalOutputConfig{}, + }, + { + Type: pipeline.OutputTypeRedirect, + }, + { + Type: pipeline.OutputTypeThreshold, + }, + { + Type: pipeline.OutputTypeChangeLog, + }, + { + Type: pipeline.OutputTypeRemoteWrite, + }, + }, + "converters": []configInfo{ + { + Type: pipeline.ConverterTypeJsonAuto, + }, + { + Type: pipeline.ConverterTypeJsonExact, + }, + { + Type: pipeline.ConverterTypeInfluxAuto, + Description: "accept influx line protocol", + Example: pipeline.AutoInfluxConverterConfig{}, + }, + { + Type: pipeline.ConverterTypeJsonFrame, + }, + }, + "processors": []configInfo{ + { + Type: pipeline.ProcessorTypeKeepFields, + Description: "list the fields that should stay", + Example: pipeline.KeepFieldsProcessorConfig{}, + }, + { + Type: pipeline.ProcessorTypeDropFields, + Description: "list the fields that should be removed", + Example: pipeline.DropFieldsProcessorConfig{}, + }, + { + Type: pipeline.ProcessorTypeMultiple, + Description: "apply multiple processors", + Example: pipeline.MultipleProcessorConfig{}, + }, + }, + }) +} + // HandleRemoteWriteBackendsListHTTP ... func (g *GrafanaLive) HandleRemoteWriteBackendsListHTTP(c *models.ReqContext) response.Response { result, err := g.channelRuleStorage.ListRemoteWriteBackends(c.Req.Context(), c.OrgId) @@ -902,3 +1009,68 @@ func handleLog(msg centrifuge.LogEntry) { loggerCF.Debug(msg.Message, arr...) } } + +func (g *GrafanaLive) sampleLiveStats() { + numClients := g.node.Hub().NumClients() + numUsers := g.node.Hub().NumUsers() + + g.usageStats.sampleCount++ + g.usageStats.numClientsSum += numClients + g.usageStats.numUsersSum += numUsers + + if numClients > g.usageStats.numClientsMax { + g.usageStats.numClientsMax = numClients + } + + if numClients < g.usageStats.numClientsMin { + g.usageStats.numClientsMin = numClients + } + + if numUsers > g.usageStats.numUsersMax { + g.usageStats.numUsersMax = numUsers + } + + if numUsers < g.usageStats.numUsersMin { + g.usageStats.numUsersMin = numUsers + } +} + +func (g *GrafanaLive) resetLiveStats() { + g.usageStats = usageStats{} +} + +func (g *GrafanaLive) registerUsageMetrics() { + g.usageStatsService.RegisterSendReportCallback(g.resetLiveStats) + + g.usageStatsService.RegisterMetricsFunc(func() (map[string]interface{}, error) { + liveUsersAvg := 0 + liveClientsAvg := 0 + + if g.usageStats.sampleCount > 0 { + liveUsersAvg = g.usageStats.numUsersSum / g.usageStats.sampleCount + liveClientsAvg = g.usageStats.numClientsSum / g.usageStats.sampleCount + } + + metrics := map[string]interface{}{ + "stats.live_samples.count": g.usageStats.sampleCount, + "stats.live_users_max.count": g.usageStats.numUsersMax, + "stats.live_users_min.count": g.usageStats.numUsersMin, + "stats.live_users_avg.count": liveUsersAvg, + "stats.live_clients_max.count": g.usageStats.numClientsMax, + "stats.live_clients_min.count": g.usageStats.numClientsMin, + "stats.live_clients_avg.count": liveClientsAvg, + } + + return metrics, nil + }) +} + +type usageStats struct { + numClientsMax int + numClientsMin int + numClientsSum int + numUsersMax int + numUsersMin int + numUsersSum int + sampleCount int +} diff --git a/pkg/services/live/managedstream/cache_redis.go b/pkg/services/live/managedstream/cache_redis.go index e080a59f275..2523c8b2747 100644 --- a/pkg/services/live/managedstream/cache_redis.go +++ b/pkg/services/live/managedstream/cache_redis.go @@ -1,6 +1,7 @@ package managedstream import ( + "context" "encoding/json" "errors" "sync" @@ -8,8 +9,8 @@ import ( "github.com/grafana/grafana/pkg/services/live/orgchannel" + "github.com/go-redis/redis/v8" "github.com/grafana/grafana-plugin-sdk-go/data" - "gopkg.in/redis.v5" ) // RedisFrameCache ... @@ -43,7 +44,7 @@ func (c *RedisFrameCache) GetActiveChannels(orgID int64) (map[string]json.RawMes func (c *RedisFrameCache) GetFrame(orgID int64, channel string) (json.RawMessage, bool, error) { key := getCacheKey(orgchannel.PrependOrgID(orgID, channel)) - cmd := c.redisClient.HGetAll(key) + cmd := c.redisClient.HGetAll(context.TODO(), key) result, err := cmd.Result() if err != nil { return nil, false, err @@ -73,14 +74,16 @@ func (c *RedisFrameCache) Update(orgID int64, channel string, jsonFrame data.Fra pipe := c.redisClient.TxPipeline() defer func() { _ = pipe.Close() }() - pipe.HGetAll(key) - pipe.HMSet(key, map[string]string{ + ctx := context.TODO() + + pipe.HGetAll(ctx, key) + pipe.HMSet(ctx, key, map[string]string{ "schema": stringSchema, "frame": string(jsonFrame.Bytes(data.IncludeAll)), }) - pipe.Expire(key, frameCacheTTL) + pipe.Expire(ctx, key, frameCacheTTL) - replies, err := pipe.Exec() + replies, err := pipe.Exec(ctx) if err != nil { return false, err } diff --git a/pkg/services/live/managedstream/cache_redis_test.go b/pkg/services/live/managedstream/cache_redis_test.go index a9183e69936..df650ded044 100644 --- a/pkg/services/live/managedstream/cache_redis_test.go +++ b/pkg/services/live/managedstream/cache_redis_test.go @@ -6,8 +6,8 @@ package managedstream import ( "testing" + "github.com/go-redis/redis/v8" "github.com/stretchr/testify/require" - "gopkg.in/redis.v5" ) func TestRedisCacheStorage(t *testing.T) { diff --git a/pkg/services/live/pipeline/condition_checker.go b/pkg/services/live/pipeline/condition_checker.go index 46d4607612d..a50fd67ec0d 100644 --- a/pkg/services/live/pipeline/condition_checker.go +++ b/pkg/services/live/pipeline/condition_checker.go @@ -8,5 +8,6 @@ import ( // ConditionChecker checks conditions in context of data.Frame being processed. type ConditionChecker interface { + Type() string CheckCondition(ctx context.Context, frame *data.Frame) (bool, error) } diff --git a/pkg/services/live/pipeline/condition_checker_multiple.go b/pkg/services/live/pipeline/condition_checker_multiple.go index dee496331df..83e7c9ba069 100644 --- a/pkg/services/live/pipeline/condition_checker_multiple.go +++ b/pkg/services/live/pipeline/condition_checker_multiple.go @@ -16,24 +16,30 @@ const ( // MultipleConditionChecker can check multiple conditions according to ConditionType. type MultipleConditionChecker struct { - Type ConditionType - Conditions []ConditionChecker + ConditionType ConditionType + Conditions []ConditionChecker } -func (m MultipleConditionChecker) CheckCondition(ctx context.Context, frame *data.Frame) (bool, error) { - for _, c := range m.Conditions { - ok, err := c.CheckCondition(ctx, frame) +const ConditionCheckerTypeMultiple = "multiple" + +func (c *MultipleConditionChecker) Type() string { + return ConditionCheckerTypeMultiple +} + +func (c *MultipleConditionChecker) CheckCondition(ctx context.Context, frame *data.Frame) (bool, error) { + for _, cond := range c.Conditions { + ok, err := cond.CheckCondition(ctx, frame) if err != nil { return false, err } - if ok && m.Type == ConditionAny { + if ok && c.ConditionType == ConditionAny { return true, nil } - if !ok && m.Type == ConditionAll { + if !ok && c.ConditionType == ConditionAll { return false, nil } } - if m.Type == ConditionAny { + if c.ConditionType == ConditionAny { return false, nil } return true, nil @@ -41,5 +47,5 @@ func (m MultipleConditionChecker) CheckCondition(ctx context.Context, frame *dat // NewMultipleConditionChecker creates new MultipleConditionChecker. func NewMultipleConditionChecker(conditionType ConditionType, conditions ...ConditionChecker) *MultipleConditionChecker { - return &MultipleConditionChecker{Type: conditionType, Conditions: conditions} + return &MultipleConditionChecker{ConditionType: conditionType, Conditions: conditions} } diff --git a/pkg/services/live/pipeline/condition_number_compare.go b/pkg/services/live/pipeline/condition_number_compare.go index 429415c5b30..afcefe03c2a 100644 --- a/pkg/services/live/pipeline/condition_number_compare.go +++ b/pkg/services/live/pipeline/condition_number_compare.go @@ -27,10 +27,16 @@ const ( NumberCompareOpNe NumberCompareOp = "ne" ) -func (f NumberCompareCondition) CheckCondition(_ context.Context, frame *data.Frame) (bool, error) { +const ConditionCheckerTypeNumberCompare = "numberCompare" + +func (c *NumberCompareCondition) Type() string { + return ConditionCheckerTypeNumberCompare +} + +func (c *NumberCompareCondition) CheckCondition(_ context.Context, frame *data.Frame) (bool, error) { for _, field := range frame.Fields { // TODO: support other numeric types. - if field.Name == f.FieldName && (field.Type() == data.FieldTypeNullableFloat64) { + if field.Name == c.FieldName && (field.Type() == data.FieldTypeNullableFloat64) { value, ok := field.At(0).(*float64) if !ok { return false, fmt.Errorf("unexpected value type: %T", field.At(0)) @@ -38,21 +44,21 @@ func (f NumberCompareCondition) CheckCondition(_ context.Context, frame *data.Fr if value == nil { return false, nil } - switch f.Op { + switch c.Op { case NumberCompareOpGt: - return *value > f.Value, nil + return *value > c.Value, nil case NumberCompareOpGte: - return *value >= f.Value, nil + return *value >= c.Value, nil case NumberCompareOpLte: - return *value <= f.Value, nil + return *value <= c.Value, nil case NumberCompareOpLt: - return *value < f.Value, nil + return *value < c.Value, nil case NumberCompareOpEq: - return *value == f.Value, nil + return *value == c.Value, nil case NumberCompareOpNe: - return *value != f.Value, nil + return *value != c.Value, nil default: - return false, fmt.Errorf("unknown comparison operator: %s", f.Op) + return false, fmt.Errorf("unknown comparison operator: %s", c.Op) } } } diff --git a/pkg/services/live/pipeline/config.go b/pkg/services/live/pipeline/config.go index 61ec3373f9d..949f24ca26d 100644 --- a/pkg/services/live/pipeline/config.go +++ b/pkg/services/live/pipeline/config.go @@ -61,8 +61,9 @@ type MultipleSubscriberConfig struct { } type SubscriberConfig struct { - Type string `json:"type"` - MultipleSubscriberConfig *MultipleSubscriberConfig `json:"multiple,omitempty"` + Type string `json:"type"` + MultipleSubscriberConfig *MultipleSubscriberConfig `json:"multiple,omitempty"` + AuthorizeRoleSubscriberConfig *AuthorizeRoleSubscriberConfig `json:"authorizeRole,omitempty"` } type ChannelRuleSettings struct { @@ -128,11 +129,16 @@ func (f *StorageRuleBuilder) extractSubscriber(config *SubscriberConfig) (Subscr } missingConfiguration := fmt.Errorf("missing configuration for %s", config.Type) switch config.Type { - case "builtin": + case SubscriberTypeBuiltin: return NewBuiltinSubscriber(f.ChannelHandlerGetter), nil - case "managedStream": + case SubscriberTypeManagedStream: return NewManagedStreamSubscriber(f.ManagedStream), nil - case "multiple": + case SubscriberTypeAuthorizeRole: + if config.AuthorizeRoleSubscriberConfig == nil { + return nil, missingConfiguration + } + return NewAuthorizeRoleSubscriber(*config.AuthorizeRoleSubscriberConfig), nil + case SubscriberTypeMultiple: if config.MultipleSubscriberConfig == nil { return nil, missingConfiguration } @@ -157,22 +163,22 @@ func (f *StorageRuleBuilder) extractConverter(config *ConverterConfig) (Converte } missingConfiguration := fmt.Errorf("missing configuration for %s", config.Type) switch config.Type { - case "jsonAuto": + case ConverterTypeJsonAuto: if config.AutoJsonConverterConfig == nil { return nil, missingConfiguration } return NewAutoJsonConverter(*config.AutoJsonConverterConfig), nil - case "jsonExact": + case ConverterTypeJsonExact: if config.ExactJsonConverterConfig == nil { return nil, missingConfiguration } return NewExactJsonConverter(*config.ExactJsonConverterConfig), nil - case "jsonFrame": + case ConverterTypeJsonFrame: if config.JsonFrameConverterConfig == nil { return nil, missingConfiguration } return NewJsonFrameConverter(*config.JsonFrameConverterConfig), nil - case "influxAuto": + case ConverterTypeInfluxAuto: if config.AutoInfluxConverterConfig == nil { return nil, missingConfiguration } @@ -188,17 +194,17 @@ func (f *StorageRuleBuilder) extractProcessor(config *ProcessorConfig) (Processo } missingConfiguration := fmt.Errorf("missing configuration for %s", config.Type) switch config.Type { - case "dropFields": + case ProcessorTypeDropFields: if config.DropFieldsProcessorConfig == nil { return nil, missingConfiguration } return NewDropFieldsProcessor(*config.DropFieldsProcessorConfig), nil - case "keepFields": + case ProcessorTypeKeepFields: if config.KeepFieldsProcessorConfig == nil { return nil, missingConfiguration } return NewKeepFieldsProcessor(*config.KeepFieldsProcessorConfig), nil - case "multiple": + case ProcessorTypeMultiple: if config.MultipleProcessorConfig == nil { return nil, missingConfiguration } @@ -223,13 +229,13 @@ func (f *StorageRuleBuilder) extractConditionChecker(config *ConditionCheckerCon } missingConfiguration := fmt.Errorf("missing configuration for %s", config.Type) switch config.Type { - case "numberCompare": + case ConditionCheckerTypeNumberCompare: if config.NumberCompareConditionConfig == nil { return nil, missingConfiguration } c := *config.NumberCompareConditionConfig return NewNumberCompareCondition(c.FieldName, c.Op, c.Value), nil - case "multiple": + case ConditionCheckerTypeMultiple: var conditions []ConditionChecker if config.MultipleConditionCheckerConfig == nil { return nil, missingConfiguration @@ -254,12 +260,12 @@ func (f *StorageRuleBuilder) extractOutputter(config *OutputterConfig, remoteWri } missingConfiguration := fmt.Errorf("missing configuration for %s", config.Type) switch config.Type { - case "redirect": + case OutputTypeRedirect: if config.RedirectOutputConfig == nil { return nil, missingConfiguration } return NewRedirectOutput(*config.RedirectOutputConfig), nil - case "multiple": + case OutputTypeMultiple: if config.MultipleOutputterConfig == nil { return nil, missingConfiguration } @@ -273,11 +279,11 @@ func (f *StorageRuleBuilder) extractOutputter(config *OutputterConfig, remoteWri outputters = append(outputters, outputter) } return NewMultipleOutput(outputters...), nil - case "managedStream": + case OutputTypeManagedStream: return NewManagedStreamOutput(f.ManagedStream), nil - case "localSubscribers": + case OutputTypeLocalSubscribers: return NewLocalSubscribersOutput(f.Node), nil - case "conditional": + case OutputTypeConditional: if config.ConditionalOutputConfig == nil { return nil, missingConfiguration } @@ -290,12 +296,12 @@ func (f *StorageRuleBuilder) extractOutputter(config *OutputterConfig, remoteWri return nil, err } return NewConditionalOutput(condition, outputter), nil - case "threshold": + case OutputTypeThreshold: if config.ThresholdOutputConfig == nil { return nil, missingConfiguration } return NewThresholdOutput(f.FrameStorage, *config.ThresholdOutputConfig), nil - case "remoteWrite": + case OutputTypeRemoteWrite: if config.RemoteWriteOutputConfig == nil { return nil, missingConfiguration } @@ -304,7 +310,7 @@ func (f *StorageRuleBuilder) extractOutputter(config *OutputterConfig, remoteWri return nil, fmt.Errorf("unknown remote write backend uid: %s", config.RemoteWriteOutputConfig.UID) } return NewRemoteWriteOutput(*remoteWriteConfig), nil - case "changeLog": + case OutputTypeChangeLog: if config.ChangeLogOutputConfig == nil { return nil, missingConfiguration } diff --git a/pkg/services/live/pipeline/converter_influx_auto.go b/pkg/services/live/pipeline/converter_influx_auto.go index 810751fee6d..18ac1c8e9e2 100644 --- a/pkg/services/live/pipeline/converter_influx_auto.go +++ b/pkg/services/live/pipeline/converter_influx_auto.go @@ -22,8 +22,14 @@ func NewAutoInfluxConverter(config AutoInfluxConverterConfig) *AutoInfluxConvert return &AutoInfluxConverter{config: config, converter: convert.NewConverter()} } -func (i AutoInfluxConverter) Convert(_ context.Context, vars Vars, body []byte) ([]*ChannelFrame, error) { - frameWrappers, err := i.converter.Convert(body, i.config.FrameFormat) +const ConverterTypeInfluxAuto = "influxAuto" + +func (c *AutoInfluxConverter) Type() string { + return ConverterTypeInfluxAuto +} + +func (c *AutoInfluxConverter) Convert(_ context.Context, vars Vars, body []byte) ([]*ChannelFrame, error) { + frameWrappers, err := c.converter.Convert(body, c.config.FrameFormat) if err != nil { return nil, err } diff --git a/pkg/services/live/pipeline/converter_json_auto.go b/pkg/services/live/pipeline/converter_json_auto.go index 0e16fd9820a..110631505ef 100644 --- a/pkg/services/live/pipeline/converter_json_auto.go +++ b/pkg/services/live/pipeline/converter_json_auto.go @@ -18,6 +18,12 @@ func NewAutoJsonConverter(c AutoJsonConverterConfig) *AutoJsonConverter { return &AutoJsonConverter{config: c} } +const ConverterTypeJsonAuto = "jsonAuto" + +func (c *AutoJsonConverter) Type() string { + return ConverterTypeJsonAuto +} + // Automatic conversion works this way: // * Time added automatically // * Nulls dropped diff --git a/pkg/services/live/pipeline/converter_json_exact.go b/pkg/services/live/pipeline/converter_json_exact.go index 020ca490fa2..38e0e7981d7 100644 --- a/pkg/services/live/pipeline/converter_json_exact.go +++ b/pkg/services/live/pipeline/converter_json_exact.go @@ -27,6 +27,12 @@ func NewExactJsonConverter(c ExactJsonConverterConfig) *ExactJsonConverter { return &ExactJsonConverter{config: c} } +const ConverterTypeJsonExact = "jsonExact" + +func (c *ExactJsonConverter) Type() string { + return ConverterTypeJsonExact +} + func (c *ExactJsonConverter) Convert(_ context.Context, vars Vars, body []byte) ([]*ChannelFrame, error) { //obj, err := oj.Parse(body) //if err != nil { diff --git a/pkg/services/live/pipeline/converter_json_frame.go b/pkg/services/live/pipeline/converter_json_frame.go index d8a7426b720..ea8264caada 100644 --- a/pkg/services/live/pipeline/converter_json_frame.go +++ b/pkg/services/live/pipeline/converter_json_frame.go @@ -20,6 +20,12 @@ func NewJsonFrameConverter(c JsonFrameConverterConfig) *JsonFrameConverter { } } +const ConverterTypeJsonFrame = "jsonFrame" + +func (c *JsonFrameConverter) Type() string { + return ConverterTypeJsonFrame +} + func (c *JsonFrameConverter) Convert(_ context.Context, _ Vars, body []byte) ([]*ChannelFrame, error) { var frame data.Frame err := json.Unmarshal(body, &frame) diff --git a/pkg/services/live/pipeline/devdata.go b/pkg/services/live/pipeline/devdata.go index 59bf7ce70c4..1c7bd369d53 100644 --- a/pkg/services/live/pipeline/devdata.go +++ b/pkg/services/live/pipeline/devdata.go @@ -107,8 +107,10 @@ func (f *DevRuleBuilder) BuildRules(_ context.Context, _ int64) ([]*LiveChannelR Converter: NewJsonFrameConverter(JsonFrameConverterConfig{}), Outputter: NewMultipleOutput( NewManagedStreamOutput(f.ManagedStream), - NewRedirectOutput(RedirectOutputConfig{ - Channel: "stream/testdata/random-20Hz-stream", + NewRemoteWriteOutput(RemoteWriteConfig{ + Endpoint: os.Getenv("GF_LIVE_REMOTE_WRITE_ENDPOINT"), + User: os.Getenv("GF_LIVE_REMOTE_WRITE_USER"), + Password: os.Getenv("GF_LIVE_REMOTE_WRITE_PASSWORD"), }), ), }, diff --git a/pkg/services/live/pipeline/output_changelog.go b/pkg/services/live/pipeline/output_changelog.go index 91072a7f586..f2769806677 100644 --- a/pkg/services/live/pipeline/output_changelog.go +++ b/pkg/services/live/pipeline/output_changelog.go @@ -24,13 +24,19 @@ func NewChangeLogOutput(frameStorage FrameGetSetter, config ChangeLogOutputConfi return &ChangeLogOutput{frameStorage: frameStorage, config: config} } -func (l ChangeLogOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { - previousFrame, previousFrameOK, err := l.frameStorage.Get(vars.OrgID, l.config.Channel) +const OutputTypeChangeLog = "changeLog" + +func (out *ChangeLogOutput) Type() string { + return OutputTypeChangeLog +} + +func (out *ChangeLogOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { + previousFrame, previousFrameOK, err := out.frameStorage.Get(vars.OrgID, out.config.Channel) if err != nil { return nil, err } - fieldName := l.config.FieldName + fieldName := out.config.FieldName previousFrameFieldIndex := -1 if previousFrameOK { @@ -78,15 +84,15 @@ func (l ChangeLogOutput) Output(_ context.Context, vars OutputVars, frame *data. if fTime.Len() > 0 { changeFrame := data.NewFrame("change", fTime, f1, f2) - err := l.frameStorage.Set(vars.OrgID, l.config.Channel, frame) + err := out.frameStorage.Set(vars.OrgID, out.config.Channel, frame) if err != nil { return nil, err } return []*ChannelFrame{{ - Channel: l.config.Channel, + Channel: out.config.Channel, Frame: changeFrame, }}, nil } - return nil, l.frameStorage.Set(vars.OrgID, l.config.Channel, frame) + return nil, out.frameStorage.Set(vars.OrgID, out.config.Channel, frame) } diff --git a/pkg/services/live/pipeline/output_conditional.go b/pkg/services/live/pipeline/output_conditional.go index e47960c74e1..fef42cadebc 100644 --- a/pkg/services/live/pipeline/output_conditional.go +++ b/pkg/services/live/pipeline/output_conditional.go @@ -15,13 +15,19 @@ func NewConditionalOutput(condition ConditionChecker, outputter Outputter) *Cond return &ConditionalOutput{Condition: condition, Outputter: outputter} } -func (l ConditionalOutput) Output(ctx context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { - ok, err := l.Condition.CheckCondition(ctx, frame) +const OutputTypeConditional = "conditional" + +func (out *ConditionalOutput) Type() string { + return OutputTypeConditional +} + +func (out ConditionalOutput) Output(ctx context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { + ok, err := out.Condition.CheckCondition(ctx, frame) if err != nil { return nil, err } if !ok { return nil, nil } - return l.Outputter.Output(ctx, vars, frame) + return out.Outputter.Output(ctx, vars, frame) } diff --git a/pkg/services/live/pipeline/output_local_subscribers.go b/pkg/services/live/pipeline/output_local_subscribers.go index 5a8a2931536..ed1adf4788f 100644 --- a/pkg/services/live/pipeline/output_local_subscribers.go +++ b/pkg/services/live/pipeline/output_local_subscribers.go @@ -20,7 +20,13 @@ func NewLocalSubscribersOutput(node *centrifuge.Node) *LocalSubscribersOutput { return &LocalSubscribersOutput{node: node} } -func (l *LocalSubscribersOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { +const OutputTypeLocalSubscribers = "localSubscribers" + +func (out *LocalSubscribersOutput) Type() string { + return OutputTypeLocalSubscribers +} + +func (out *LocalSubscribersOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { channelID := vars.Channel channel := orgchannel.PrependOrgID(vars.OrgID, channelID) frameJSON, err := json.Marshal(frame) @@ -30,7 +36,7 @@ func (l *LocalSubscribersOutput) Output(_ context.Context, vars OutputVars, fram pub := ¢rifuge.Publication{ Data: frameJSON, } - err = l.node.Hub().BroadcastPublication(channel, pub, centrifuge.StreamPosition{}) + err = out.node.Hub().BroadcastPublication(channel, pub, centrifuge.StreamPosition{}) if err != nil { return nil, fmt.Errorf("error publishing %s: %w", string(frameJSON), err) } diff --git a/pkg/services/live/pipeline/output_managed_stream.go b/pkg/services/live/pipeline/output_managed_stream.go index bd225d704a4..5ec929ec487 100644 --- a/pkg/services/live/pipeline/output_managed_stream.go +++ b/pkg/services/live/pipeline/output_managed_stream.go @@ -16,8 +16,14 @@ func NewManagedStreamOutput(managedStream *managedstream.Runner) *ManagedStreamO return &ManagedStreamOutput{managedStream: managedStream} } -func (l *ManagedStreamOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { - stream, err := l.managedStream.GetOrCreateStream(vars.OrgID, vars.Scope, vars.Namespace) +const OutputTypeManagedStream = "managedStream" + +func (out *ManagedStreamOutput) Type() string { + return OutputTypeManagedStream +} + +func (out *ManagedStreamOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { + stream, err := out.managedStream.GetOrCreateStream(vars.OrgID, vars.Scope, vars.Namespace) if err != nil { logger.Error("Error getting stream", "error", err) return nil, err diff --git a/pkg/services/live/pipeline/output_multiple.go b/pkg/services/live/pipeline/output_multiple.go index d763bf259ec..bd21934b438 100644 --- a/pkg/services/live/pipeline/output_multiple.go +++ b/pkg/services/live/pipeline/output_multiple.go @@ -12,9 +12,15 @@ type MultipleOutput struct { Outputters []Outputter } -func (m MultipleOutput) Output(ctx context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { +const OutputTypeMultiple = "multiple" + +func (out *MultipleOutput) Type() string { + return OutputTypeMultiple +} + +func (out MultipleOutput) Output(ctx context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { var frames []*ChannelFrame - for _, out := range m.Outputters { + for _, out := range out.Outputters { f, err := out.Output(ctx, vars, frame) if err != nil { logger.Error("Error outputting frame", "error", err) diff --git a/pkg/services/live/pipeline/output_redirect.go b/pkg/services/live/pipeline/output_redirect.go index d562af77cf3..803a14f27f2 100644 --- a/pkg/services/live/pipeline/output_redirect.go +++ b/pkg/services/live/pipeline/output_redirect.go @@ -22,12 +22,18 @@ func NewRedirectOutput(config RedirectOutputConfig) *RedirectOutput { return &RedirectOutput{config: config} } -func (l *RedirectOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { - if vars.Channel == l.config.Channel { - return nil, fmt.Errorf("redirect to the same channel: %s", l.config.Channel) +const OutputTypeRedirect = "redirect" + +func (out *RedirectOutput) Type() string { + return OutputTypeRedirect +} + +func (out *RedirectOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { + if vars.Channel == out.config.Channel { + return nil, fmt.Errorf("redirect to the same channel: %s", out.config.Channel) } return []*ChannelFrame{{ - Channel: l.config.Channel, + Channel: out.config.Channel, Frame: frame, }}, nil } diff --git a/pkg/services/live/pipeline/output_remote_write.go b/pkg/services/live/pipeline/output_remote_write.go index 8d6eb10457f..3ee0643b2c5 100644 --- a/pkg/services/live/pipeline/output_remote_write.go +++ b/pkg/services/live/pipeline/output_remote_write.go @@ -4,11 +4,14 @@ import ( "bytes" "context" "errors" + "fmt" "net/http" + "sync" "time" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana/pkg/services/live/remotewrite" + "github.com/prometheus/prometheus/prompb" ) type RemoteWriteConfig struct { @@ -21,52 +24,90 @@ type RemoteWriteConfig struct { } type RemoteWriteOutput struct { + mu sync.Mutex config RemoteWriteConfig httpClient *http.Client + buffer []prompb.TimeSeries } func NewRemoteWriteOutput(config RemoteWriteConfig) *RemoteWriteOutput { - return &RemoteWriteOutput{ + out := &RemoteWriteOutput{ config: config, httpClient: &http.Client{Timeout: 2 * time.Second}, } + if config.Endpoint != "" { + go out.flushPeriodically() + } + return out } -func (r RemoteWriteOutput) Output(_ context.Context, _ OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { - if r.config.Endpoint == "" { - logger.Debug("Skip sending to remote write: no url") - return nil, nil - } +const OutputTypeRemoteWrite = "remoteWrite" - // Use remote write for a stream. - remoteWriteData, err := remotewrite.SerializeLabelsColumn(frame) - if err != nil { - logger.Error("Error serializing to remote write format", "error", err) - return nil, err - } +func (out *RemoteWriteOutput) Type() string { + return OutputTypeRemoteWrite +} - logger.Debug("Sending to remote write endpoint", "url", r.config.Endpoint, "bodyLength", len(remoteWriteData)) - req, err := http.NewRequest(http.MethodPost, r.config.Endpoint, bytes.NewReader(remoteWriteData)) +func (out *RemoteWriteOutput) flushPeriodically() { + for range time.NewTicker(15 * time.Second).C { + out.mu.Lock() + if len(out.buffer) == 0 { + out.mu.Unlock() + continue + } + tmpBuffer := make([]prompb.TimeSeries, len(out.buffer)) + copy(tmpBuffer, out.buffer) + out.buffer = nil + out.mu.Unlock() + + err := out.flush(tmpBuffer) + if err != nil { + logger.Error("Error flush to remote write", "error", err) + out.mu.Lock() + // TODO: drop in case of large buffer size? Make several attempts only? + out.buffer = append(tmpBuffer, out.buffer...) + out.mu.Unlock() + } + } +} + +func (out *RemoteWriteOutput) flush(timeSeries []prompb.TimeSeries) error { + logger.Debug("Remote write flush", "num time series", len(timeSeries)) + remoteWriteData, err := remotewrite.TimeSeriesToBytes(timeSeries) if err != nil { - logger.Error("Error constructing remote write request", "error", err) - return nil, err + return fmt.Errorf("error converting time series to bytes: %v", err) + } + logger.Debug("Sending to remote write endpoint", "url", out.config.Endpoint, "bodyLength", len(remoteWriteData)) + req, err := http.NewRequest(http.MethodPost, out.config.Endpoint, bytes.NewReader(remoteWriteData)) + if err != nil { + return fmt.Errorf("error constructing remote write request: %w", err) } req.Header.Set("Content-Type", "application/x-protobuf") req.Header.Set("Content-Encoding", "snappy") req.Header.Set("X-Prometheus-Remote-Write-Version", "0.1.0") - req.SetBasicAuth(r.config.User, r.config.Password) + req.SetBasicAuth(out.config.User, out.config.Password) started := time.Now() - resp, err := r.httpClient.Do(req) + resp, err := out.httpClient.Do(req) if err != nil { - logger.Error("Error sending remote write request", "error", err) - return nil, err + return fmt.Errorf("error sending remote write request: %w", err) } _ = resp.Body.Close() if resp.StatusCode != http.StatusOK { logger.Error("Unexpected response code from remote write endpoint", "code", resp.StatusCode) - return nil, errors.New("unexpected response code from remote write endpoint") + return errors.New("unexpected response code from remote write endpoint") } - logger.Debug("Successfully sent to remote write endpoint", "url", r.config.Endpoint, "elapsed", time.Since(started)) + logger.Debug("Successfully sent to remote write endpoint", "url", out.config.Endpoint, "elapsed", time.Since(started)) + return nil +} + +func (out *RemoteWriteOutput) Output(_ context.Context, _ OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { + if out.config.Endpoint == "" { + logger.Debug("Skip sending to remote write: no url") + return nil, nil + } + ts := remotewrite.TimeSeriesFromFramesLabelsColumn(frame) + out.mu.Lock() + out.buffer = append(out.buffer, ts...) + out.mu.Unlock() return nil, nil } diff --git a/pkg/services/live/pipeline/output_threshold.go b/pkg/services/live/pipeline/output_threshold.go index bda29b2b5fa..48a26b2e678 100644 --- a/pkg/services/live/pipeline/output_threshold.go +++ b/pkg/services/live/pipeline/output_threshold.go @@ -31,15 +31,21 @@ func NewThresholdOutput(frameStorage FrameGetSetter, config ThresholdOutputConfi return &ThresholdOutput{frameStorage: frameStorage, config: config} } -func (l *ThresholdOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { +const OutputTypeThreshold = "threshold" + +func (out *ThresholdOutput) Type() string { + return OutputTypeThreshold +} + +func (out *ThresholdOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { if frame == nil { return nil, nil } - previousFrame, previousFrameOk, err := l.frameStorage.Get(vars.OrgID, l.config.Channel) + previousFrame, previousFrameOk, err := out.frameStorage.Get(vars.OrgID, out.config.Channel) if err != nil { return nil, err } - fieldName := l.config.FieldName + fieldName := out.config.FieldName currentFrameFieldIndex := -1 for i, f := range frame.Fields { @@ -136,15 +142,15 @@ func (l *ThresholdOutput) Output(_ context.Context, vars OutputVars, frame *data if fTime.Len() > 0 { stateFrame := data.NewFrame("state", fTime, f1, f2, f3) - err := l.frameStorage.Set(vars.OrgID, l.config.Channel, frame) + err := out.frameStorage.Set(vars.OrgID, out.config.Channel, frame) if err != nil { return nil, err } return []*ChannelFrame{{ - Channel: l.config.Channel, + Channel: out.config.Channel, Frame: stateFrame, }}, nil } - return nil, l.frameStorage.Set(vars.OrgID, l.config.Channel, frame) + return nil, out.frameStorage.Set(vars.OrgID, out.config.Channel, frame) } diff --git a/pkg/services/live/pipeline/pipeline.go b/pkg/services/live/pipeline/pipeline.go index f6a23eb02f0..28d75ce98f7 100644 --- a/pkg/services/live/pipeline/pipeline.go +++ b/pkg/services/live/pipeline/pipeline.go @@ -47,22 +47,26 @@ type OutputVars struct { // of resulting slice will be then individually processed and outputted // according configured channel rules. type Converter interface { + Type() string Convert(ctx context.Context, vars Vars, body []byte) ([]*ChannelFrame, error) } // Processor can modify data.Frame in a custom way before it will be outputted. type Processor interface { + Type() string Process(ctx context.Context, vars ProcessorVars, frame *data.Frame) (*data.Frame, error) } // Outputter outputs data.Frame to a custom destination. Or simply // do nothing if some conditions not met. type Outputter interface { + Type() string Output(ctx context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) } // Subscriber can handle channel subscribe events. type Subscriber interface { + Type() string Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) } diff --git a/pkg/services/live/pipeline/pipeline_test.go b/pkg/services/live/pipeline/pipeline_test.go index cf1b0c2e4ed..95b49571b7d 100644 --- a/pkg/services/live/pipeline/pipeline_test.go +++ b/pkg/services/live/pipeline/pipeline_test.go @@ -16,7 +16,7 @@ type testRuleGetter struct { rules map[string]*LiveChannelRule } -func (t *testRuleGetter) Get(orgID int64, channel string) (*LiveChannelRule, bool, error) { +func (t *testRuleGetter) Get(_ int64, channel string) (*LiveChannelRule, bool, error) { t.mu.Lock() defer t.mu.Unlock() rule, ok := t.rules[channel] @@ -48,12 +48,20 @@ type testConverter struct { frame *data.Frame } +func (t *testConverter) Type() string { + return "test" +} + func (t *testConverter) Convert(_ context.Context, _ Vars, _ []byte) ([]*ChannelFrame, error) { return []*ChannelFrame{{Channel: t.channel, Frame: t.frame}}, nil } type testProcessor struct{} +func (t *testProcessor) Type() string { + return "test" +} + func (t *testProcessor) Process(_ context.Context, _ ProcessorVars, frame *data.Frame) (*data.Frame, error) { return frame, nil } @@ -63,6 +71,10 @@ type testOutputter struct { frame *data.Frame } +func (t *testOutputter) Type() string { + return "test" +} + func (t *testOutputter) Output(_ context.Context, _ OutputVars, frame *data.Frame) ([]*ChannelFrame, error) { if t.err != nil { return nil, t.err diff --git a/pkg/services/live/pipeline/processor_drop_field.go b/pkg/services/live/pipeline/processor_drop_field.go index 536579ad269..e0917269cea 100644 --- a/pkg/services/live/pipeline/processor_drop_field.go +++ b/pkg/services/live/pipeline/processor_drop_field.go @@ -23,8 +23,14 @@ func NewDropFieldsProcessor(config DropFieldsProcessorConfig) *DropFieldsProcess return &DropFieldsProcessor{config: config} } -func (d DropFieldsProcessor) Process(_ context.Context, _ ProcessorVars, frame *data.Frame) (*data.Frame, error) { - for _, f := range d.config.FieldNames { +const ProcessorTypeDropFields = "dropFields" + +func (p *DropFieldsProcessor) Type() string { + return ProcessorTypeDropFields +} + +func (p *DropFieldsProcessor) Process(_ context.Context, _ ProcessorVars, frame *data.Frame) (*data.Frame, error) { + for _, f := range p.config.FieldNames { inner: for i, field := range frame.Fields { if f == field.Name { diff --git a/pkg/services/live/pipeline/processor_keep_field.go b/pkg/services/live/pipeline/processor_keep_field.go index e71c411c729..a4943142808 100644 --- a/pkg/services/live/pipeline/processor_keep_field.go +++ b/pkg/services/live/pipeline/processor_keep_field.go @@ -28,10 +28,16 @@ func stringInSlice(str string, slice []string) bool { return false } -func (d KeepFieldsProcessor) Process(_ context.Context, _ ProcessorVars, frame *data.Frame) (*data.Frame, error) { +const ProcessorTypeKeepFields = "keepFields" + +func (p *KeepFieldsProcessor) Type() string { + return ProcessorTypeKeepFields +} + +func (p *KeepFieldsProcessor) Process(_ context.Context, _ ProcessorVars, frame *data.Frame) (*data.Frame, error) { var fieldsToKeep []*data.Field for _, field := range frame.Fields { - if stringInSlice(field.Name, d.config.FieldNames) { + if stringInSlice(field.Name, p.config.FieldNames) { fieldsToKeep = append(fieldsToKeep, field) } } diff --git a/pkg/services/live/pipeline/processor_multiple.go b/pkg/services/live/pipeline/processor_multiple.go index 40d40798971..91f228db632 100644 --- a/pkg/services/live/pipeline/processor_multiple.go +++ b/pkg/services/live/pipeline/processor_multiple.go @@ -12,8 +12,14 @@ type MultipleProcessor struct { Processors []Processor } -func (m MultipleProcessor) Process(ctx context.Context, vars ProcessorVars, frame *data.Frame) (*data.Frame, error) { - for _, p := range m.Processors { +const ProcessorTypeMultiple = "multiple" + +func (p *MultipleProcessor) Type() string { + return ProcessorTypeMultiple +} + +func (p *MultipleProcessor) Process(ctx context.Context, vars ProcessorVars, frame *data.Frame) (*data.Frame, error) { + for _, p := range p.Processors { var err error frame, err = p.Process(ctx, vars, frame) if err != nil { diff --git a/pkg/services/live/pipeline/subscribe_authorize_role.go b/pkg/services/live/pipeline/subscribe_authorize_role.go new file mode 100644 index 00000000000..069825b15d6 --- /dev/null +++ b/pkg/services/live/pipeline/subscribe_authorize_role.go @@ -0,0 +1,39 @@ +package pipeline + +import ( + "context" + + "github.com/grafana/grafana/pkg/services/live/livecontext" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana/pkg/models" +) + +type AuthorizeRoleSubscriberConfig struct { + Role models.RoleType `json:"role,omitempty"` +} + +type AuthorizeRoleSubscriber struct { + config AuthorizeRoleSubscriberConfig +} + +func NewAuthorizeRoleSubscriber(config AuthorizeRoleSubscriberConfig) *AuthorizeRoleSubscriber { + return &AuthorizeRoleSubscriber{config: config} +} + +const SubscriberTypeAuthorizeRole = "authorizeRole" + +func (s *AuthorizeRoleSubscriber) Type() string { + return SubscriberTypeAuthorizeRole +} + +func (s *AuthorizeRoleSubscriber) Subscribe(ctx context.Context, _ Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { + u, ok := livecontext.GetContextSignedUser(ctx) + if !ok { + return models.SubscribeReply{}, backend.SubscribeStreamStatusPermissionDenied, nil + } + if u.HasRole(s.config.Role) { + return models.SubscribeReply{}, backend.SubscribeStreamStatusOK, nil + } + return models.SubscribeReply{}, backend.SubscribeStreamStatusPermissionDenied, nil +} diff --git a/pkg/services/live/pipeline/subscribe_authorize_role_test.go b/pkg/services/live/pipeline/subscribe_authorize_role_test.go new file mode 100644 index 00000000000..1d87d396e20 --- /dev/null +++ b/pkg/services/live/pipeline/subscribe_authorize_role_test.go @@ -0,0 +1,34 @@ +package pipeline + +import ( + "context" + "testing" + + "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/live/livecontext" + + "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/stretchr/testify/require" +) + +func TestAuthorizeRoleSubscriber_Subscribe_PermissionDenied(t *testing.T) { + ctx := context.Background() + ctx = livecontext.SetContextSignedUser(ctx, &models.SignedInUser{OrgRole: models.ROLE_EDITOR}) + s := NewAuthorizeRoleSubscriber(AuthorizeRoleSubscriberConfig{ + Role: models.ROLE_ADMIN, + }) + _, status, err := s.Subscribe(ctx, Vars{}) + require.NoError(t, err) + require.Equal(t, backend.SubscribeStreamStatusPermissionDenied, status) +} + +func TestAuthorizeRoleSubscriber_Subscribe_OK(t *testing.T) { + ctx := context.Background() + ctx = livecontext.SetContextSignedUser(ctx, &models.SignedInUser{OrgRole: models.ROLE_ADMIN}) + s := NewAuthorizeRoleSubscriber(AuthorizeRoleSubscriberConfig{ + Role: models.ROLE_ADMIN, + }) + _, status, err := s.Subscribe(ctx, Vars{}) + require.NoError(t, err) + require.Equal(t, backend.SubscribeStreamStatusOK, status) +} diff --git a/pkg/services/live/pipeline/subscribe_builtin.go b/pkg/services/live/pipeline/subscribe_builtin.go index 7788ab1c28a..b4e7de92f56 100644 --- a/pkg/services/live/pipeline/subscribe_builtin.go +++ b/pkg/services/live/pipeline/subscribe_builtin.go @@ -18,16 +18,22 @@ type ChannelHandlerGetter interface { GetChannelHandler(user *models.SignedInUser, channel string) (models.ChannelHandler, live.Channel, error) } +const SubscriberTypeBuiltin = "builtin" + func NewBuiltinSubscriber(channelHandlerGetter ChannelHandlerGetter) *BuiltinSubscriber { return &BuiltinSubscriber{channelHandlerGetter: channelHandlerGetter} } -func (m *BuiltinSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { +func (s *BuiltinSubscriber) Type() string { + return SubscriberTypeBuiltin +} + +func (s *BuiltinSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { u, ok := livecontext.GetContextSignedUser(ctx) if !ok { return models.SubscribeReply{}, backend.SubscribeStreamStatusPermissionDenied, nil } - handler, _, err := m.channelHandlerGetter.GetChannelHandler(u, vars.Channel) + handler, _, err := s.channelHandlerGetter.GetChannelHandler(u, vars.Channel) if err != nil { return models.SubscribeReply{}, 0, err } diff --git a/pkg/services/live/pipeline/subscribe_managed_stream.go b/pkg/services/live/pipeline/subscribe_managed_stream.go index 9ddd21d16ce..cd34bef0cc6 100644 --- a/pkg/services/live/pipeline/subscribe_managed_stream.go +++ b/pkg/services/live/pipeline/subscribe_managed_stream.go @@ -14,12 +14,18 @@ type ManagedStreamSubscriber struct { managedStream *managedstream.Runner } +const SubscriberTypeManagedStream = "managedStream" + func NewManagedStreamSubscriber(managedStream *managedstream.Runner) *ManagedStreamSubscriber { return &ManagedStreamSubscriber{managedStream: managedStream} } -func (m *ManagedStreamSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { - stream, err := m.managedStream.GetOrCreateStream(vars.OrgID, vars.Scope, vars.Namespace) +func (s *ManagedStreamSubscriber) Type() string { + return SubscriberTypeManagedStream +} + +func (s *ManagedStreamSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { + stream, err := s.managedStream.GetOrCreateStream(vars.OrgID, vars.Scope, vars.Namespace) if err != nil { logger.Error("Error getting managed stream", "error", err) return models.SubscribeReply{}, 0, err diff --git a/pkg/services/live/pipeline/subscribe_multiple.go b/pkg/services/live/pipeline/subscribe_multiple.go index b508cddb627..24c271b9456 100644 --- a/pkg/services/live/pipeline/subscribe_multiple.go +++ b/pkg/services/live/pipeline/subscribe_multiple.go @@ -15,10 +15,16 @@ func NewMultipleSubscriber(subscribers ...Subscriber) *MultipleSubscriber { return &MultipleSubscriber{Subscribers: subscribers} } -func (m *MultipleSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { +const SubscriberTypeMultiple = "multiple" + +func (s *MultipleSubscriber) Type() string { + return SubscriberTypeMultiple +} + +func (s *MultipleSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { finalReply := models.SubscribeReply{} - for _, s := range m.Subscribers { + for _, s := range s.Subscribers { reply, status, err := s.Subscribe(ctx, vars) if err != nil { return models.SubscribeReply{}, 0, err diff --git a/pkg/services/live/pipeline/subscribe_permission_denied.go b/pkg/services/live/pipeline/subscribe_permission_denied.go deleted file mode 100644 index bfd3fe8a68d..00000000000 --- a/pkg/services/live/pipeline/subscribe_permission_denied.go +++ /dev/null @@ -1,18 +0,0 @@ -package pipeline - -import ( - "context" - - "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/models" -) - -type PermissionDeniedSubscriber struct{} - -func NewPermissionDeniedSubscriber() *PermissionDeniedSubscriber { - return &PermissionDeniedSubscriber{} -} - -func (m *PermissionDeniedSubscriber) Subscribe(ctx context.Context, vars Vars) (models.SubscribeReply, backend.SubscribeStreamStatus, error) { - return models.SubscribeReply{}, backend.SubscribeStreamStatusPermissionDenied, nil -} diff --git a/pkg/services/ngalert/notifier/alertmanager.go b/pkg/services/ngalert/notifier/alertmanager.go index c135dd439dc..37794f5c73c 100644 --- a/pkg/services/ngalert/notifier/alertmanager.go +++ b/pkg/services/ngalert/notifier/alertmanager.go @@ -55,29 +55,6 @@ const ( defaultResolveTimeout = 5 * time.Minute // memoryAlertsGCInterval is the interval at which we'll remove resolved alerts from memory. memoryAlertsGCInterval = 30 * time.Minute - // To start, the alertmanager needs at least one route defined. - // TODO: we should move this to Grafana settings and define this as the default. - alertmanagerDefaultConfiguration = ` -{ - "alertmanager_config": { - "route": { - "receiver": "grafana-default-email" - }, - "receivers": [{ - "name": "grafana-default-email", - "grafana_managed_receiver_configs": [{ - "uid": "", - "name": "email receiver", - "type": "email", - "isDefault": true, - "settings": { - "addresses": "" - } - }] - }] - } -} -` ) type ClusterPeer interface { @@ -252,19 +229,19 @@ func (am *Alertmanager) SaveAndApplyDefaultConfig() error { defer am.reloadConfigMtx.Unlock() cmd := &ngmodels.SaveAlertmanagerConfigurationCmd{ - AlertmanagerConfiguration: alertmanagerDefaultConfiguration, + AlertmanagerConfiguration: am.Settings.UnifiedAlerting.DefaultConfiguration, Default: true, ConfigurationVersion: fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion), OrgID: am.orgID, } - cfg, err := Load([]byte(alertmanagerDefaultConfiguration)) + cfg, err := Load([]byte(am.Settings.UnifiedAlerting.DefaultConfiguration)) if err != nil { return err } err = am.Store.SaveAlertmanagerConfigurationWithCallback(cmd, func() error { - if err := am.applyConfig(cfg, []byte(alertmanagerDefaultConfiguration)); err != nil { + if err := am.applyConfig(cfg, []byte(am.Settings.UnifiedAlerting.DefaultConfiguration)); err != nil { return err } return nil @@ -306,44 +283,20 @@ func (am *Alertmanager) SaveAndApplyConfig(cfg *apimodels.PostableUserConfig) er return nil } -// SyncAndApplyConfigFromDatabase picks the latest config from database and restarts -// the components with the new config. -func (am *Alertmanager) SyncAndApplyConfigFromDatabase() error { +// ApplyConfig applies the configuration to the Alertmanager. +func (am *Alertmanager) ApplyConfig(dbCfg *ngmodels.AlertConfiguration) error { + var err error + cfg, err := Load([]byte(dbCfg.AlertmanagerConfiguration)) + if err != nil { + return fmt.Errorf("failed to parse Alertmanager config: %w", err) + } + am.reloadConfigMtx.Lock() defer am.reloadConfigMtx.Unlock() - // First, let's get the configuration we need from the database. - q := &ngmodels.GetLatestAlertmanagerConfigurationQuery{OrgID: am.orgID} - if err := am.Store.GetLatestAlertmanagerConfiguration(q); err != nil { - // If there's no configuration in the database, let's use the default configuration. - if errors.Is(err, store.ErrNoAlertmanagerConfiguration) { - // First, let's save it to the database. We don't need to use a transaction here as we'll always succeed. - am.logger.Info("no Alertmanager configuration found, saving and applying a default") - savecmd := &ngmodels.SaveAlertmanagerConfigurationCmd{ - AlertmanagerConfiguration: alertmanagerDefaultConfiguration, - Default: true, - ConfigurationVersion: fmt.Sprintf("v%d", ngmodels.AlertConfigurationVersion), - OrgID: am.orgID, - } - if err := am.Store.SaveAlertmanagerConfiguration(savecmd); err != nil { - return err - } - - q.Result = &ngmodels.AlertConfiguration{AlertmanagerConfiguration: alertmanagerDefaultConfiguration, Default: true} - } else { - return fmt.Errorf("unable to get Alertmanager configuration from the database: %w", err) - } + if err = am.applyConfig(cfg, nil); err != nil { + return fmt.Errorf("unable to apply configuration: %w", err) } - - cfg, err := Load([]byte(q.Result.AlertmanagerConfiguration)) - if err != nil { - return err - } - - if err := am.applyConfig(cfg, nil); err != nil { - return fmt.Errorf("unable to reload configuration: %w", err) - } - return nil } diff --git a/pkg/services/ngalert/notifier/alertmanager_test.go b/pkg/services/ngalert/notifier/alertmanager_test.go index f790b2bce15..32983f8807e 100644 --- a/pkg/services/ngalert/notifier/alertmanager_test.go +++ b/pkg/services/ngalert/notifier/alertmanager_test.go @@ -53,12 +53,6 @@ func setupAMTest(t *testing.T) *Alertmanager { return am } -func TestAlertmanager_ShouldUseDefaultConfigurationWhenNoConfiguration(t *testing.T) { - am := setupAMTest(t) - require.NoError(t, am.SyncAndApplyConfigFromDatabase()) - require.NotNil(t, am.config) -} - func TestPutAlert(t *testing.T) { am := setupAMTest(t) diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager.go b/pkg/services/ngalert/notifier/multiorg_alertmanager.go index 39ad4b47f00..1aab783df98 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager.go @@ -15,6 +15,7 @@ import ( "github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/services/ngalert/metrics" + "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/ngalert/store" "github.com/grafana/grafana/pkg/setting" ) @@ -116,20 +117,41 @@ func (moa *MultiOrgAlertmanager) LoadAndSyncAlertmanagersForOrgs(ctx context.Con // Then, sync them by creating or deleting Alertmanagers as necessary. moa.metrics.DiscoveredConfigurations.Set(float64(len(orgIDs))) - moa.SyncAlertmanagersForOrgs(orgIDs) + moa.SyncAlertmanagersForOrgs(ctx, orgIDs) moa.logger.Debug("done synchronizing Alertmanagers for orgs") return nil } -func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(orgIDs []int64) { +// getLatestConfigs retrieves the latest Alertmanager configuration for every organization. It returns a map where the key is the ID of each organization and the value is the configuration. +func (moa *MultiOrgAlertmanager) getLatestConfigs(ctx context.Context) (map[int64]*models.AlertConfiguration, error) { + configs, err := moa.configStore.GetAllLatestAlertmanagerConfiguration(ctx) + if err != nil { + return nil, err + } + + result := make(map[int64]*models.AlertConfiguration, len(configs)) + for _, config := range configs { + result[config.OrgID] = config + } + + return result, nil +} + +// SyncAlertmanagersForOrgs syncs configuration of the Alertmanager required by each organization. +func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(ctx context.Context, orgIDs []int64) { orgsFound := make(map[int64]struct{}, len(orgIDs)) + dbConfigs, err := moa.getLatestConfigs(ctx) + if err != nil { + moa.logger.Error("failed to load Alertmanager configurations", "err", err) + return + } moa.alertmanagersMtx.Lock() for _, orgID := range orgIDs { orgsFound[orgID] = struct{}{} - existing, found := moa.alertmanagers[orgID] + alertmanager, found := moa.alertmanagers[orgID] if !found { // These metrics are not exported by Grafana and are mostly a placeholder. // To export them, we need to translate the metrics from each individual registry and, @@ -139,14 +161,30 @@ func (moa *MultiOrgAlertmanager) SyncAlertmanagersForOrgs(orgIDs []int64) { if err != nil { moa.logger.Error("unable to create Alertmanager for org", "org", orgID, "err", err) } - moa.alertmanagers[orgID] = am - existing = am + alertmanager = am } - //TODO: This will create an N+1 query - if err := existing.SyncAndApplyConfigFromDatabase(); err != nil { - moa.logger.Error("failed to apply Alertmanager config for org", "org", orgID, "err", err) + dbConfig, cfgFound := dbConfigs[orgID] + if !cfgFound { + if found { + // This means that the configuration is gone but the organization, as well as the Alertmanager, exists. + moa.logger.Warn("Alertmanager exists for org but the configuration is gone. Applying the default configuration", "org", orgID) + } + err := alertmanager.SaveAndApplyDefaultConfig() + if err != nil { + moa.logger.Error("failed to apply the default Alertmanager configuration", "org", orgID) + continue + } + moa.alertmanagers[orgID] = alertmanager + continue } + + err := alertmanager.ApplyConfig(dbConfig) + if err != nil { + moa.logger.Error("failed to apply Alertmanager config for org", "org", orgID, "id", dbConfig.ID, "err", err) + continue + } + moa.alertmanagers[orgID] = alertmanager } amsToStop := map[int64]*Alertmanager{} diff --git a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go index de9f4e0afd5..5e4c2ecba45 100644 --- a/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go +++ b/pkg/services/ngalert/notifier/multiorg_alertmanager_test.go @@ -33,7 +33,7 @@ func TestMultiOrgAlertmanager_SyncAlertmanagersForOrgs(t *testing.T) { m := metrics.NewNGAlert(reg) cfg := &setting.Cfg{ DataPath: tmpDir, - UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute}, // do not poll in tests. + UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: setting.AlertmanagerDefaultConfiguration}, // do not poll in tests. } mam, err := NewMultiOrgAlertmanager(cfg, configStore, orgStore, kvStore, m.GetMultiOrgAlertmanagerMetrics(), log.New("testlogger")) require.NoError(t, err) @@ -95,7 +95,7 @@ func TestMultiOrgAlertmanager_AlertmanagerFor(t *testing.T) { require.NoError(t, err) cfg := &setting.Cfg{ DataPath: tmpDir, - UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute}, // do not poll in tests. + UnifiedAlerting: setting.UnifiedAlertingSettings{AlertmanagerConfigPollInterval: 3 * time.Minute, DefaultConfiguration: setting.AlertmanagerDefaultConfiguration}, // do not poll in tests. } kvStore := newFakeKVStore(t) reg := prometheus.NewPedanticRegistry() diff --git a/pkg/services/ngalert/notifier/testing.go b/pkg/services/ngalert/notifier/testing.go index cc93778341a..005547d57c1 100644 --- a/pkg/services/ngalert/notifier/testing.go +++ b/pkg/services/ngalert/notifier/testing.go @@ -13,6 +13,14 @@ type FakeConfigStore struct { configs map[int64]*models.AlertConfiguration } +func (f *FakeConfigStore) GetAllLatestAlertmanagerConfiguration(context.Context) ([]*models.AlertConfiguration, error) { + result := make([]*models.AlertConfiguration, 0, len(f.configs)) + for _, configuration := range f.configs { + result = append(result, configuration) + } + return result, nil +} + func (f *FakeConfigStore) GetLatestAlertmanagerConfiguration(query *models.GetLatestAlertmanagerConfigurationQuery) error { var ok bool query.Result, ok = f.configs[query.OrgID] diff --git a/pkg/services/ngalert/state/manager.go b/pkg/services/ngalert/state/manager.go index bbd2f1381ad..a92bd2b5ced 100644 --- a/pkg/services/ngalert/state/manager.go +++ b/pkg/services/ngalert/state/manager.go @@ -205,7 +205,7 @@ func (st *Manager) recordMetrics() { for { select { case <-ticker.C: - st.log.Info("recording state cache metrics", "now", time.Now()) + st.log.Debug("recording state cache metrics", "now", time.Now()) st.cache.recordMetrics() case <-st.quit: st.log.Debug("stopping state cache metrics recording", "now", time.Now()) diff --git a/pkg/services/ngalert/state/state.go b/pkg/services/ngalert/state/state.go index 85bd2e0081c..3f72ae58ca5 100644 --- a/pkg/services/ngalert/state/state.go +++ b/pkg/services/ngalert/state/state.go @@ -158,7 +158,7 @@ func (a *State) TrimResults(alertRule *ngModels.AlertRule) { func (a *State) setEndsAt(alertRule *ngModels.AlertRule, result eval.Result) { ends := ResendDelay if alertRule.IntervalSeconds > int64(ResendDelay.Seconds()) { - ends = time.Duration(alertRule.IntervalSeconds) + ends = time.Second * time.Duration(alertRule.IntervalSeconds) } a.EndsAt = result.EvaluatedAt.Add(ends * 3) diff --git a/pkg/services/ngalert/state/state_test.go b/pkg/services/ngalert/state/state_test.go index a22fa98cb39..e8d5cdd2bc0 100644 --- a/pkg/services/ngalert/state/state_test.go +++ b/pkg/services/ngalert/state/state_test.go @@ -149,14 +149,14 @@ func TestSetEndsAt(t *testing.T) { }, { name: "more than resend delay: for=unset,interval=1m - endsAt = interval * 3", - expected: evaluationTime.Add(60 * 3), + expected: evaluationTime.Add(time.Second * 60 * 3), testRule: &ngmodels.AlertRule{ IntervalSeconds: 60, }, }, { name: "more than resend delay: for=0s,interval=1m - endsAt = resendDelay * 3", - expected: evaluationTime.Add(60 * 3), + expected: evaluationTime.Add(time.Second * 60 * 3), testRule: &ngmodels.AlertRule{ For: 0 * time.Second, IntervalSeconds: 60, @@ -164,7 +164,7 @@ func TestSetEndsAt(t *testing.T) { }, { name: "more than resend delay: for=1m,interval=5m - endsAt = interval * 3", - expected: evaluationTime.Add(300 * 3), + expected: evaluationTime.Add(time.Second * 300 * 3), testRule: &ngmodels.AlertRule{ For: 60 * time.Second, IntervalSeconds: 300, @@ -172,7 +172,7 @@ func TestSetEndsAt(t *testing.T) { }, { name: "more than resend delay: for=5m,interval=1m - endsAt = interval * 3", - expected: evaluationTime.Add(60 * 3), + expected: evaluationTime.Add(time.Second * 60 * 3), testRule: &ngmodels.AlertRule{ For: 300 * time.Second, IntervalSeconds: 60, diff --git a/pkg/services/ngalert/store/alert_rule.go b/pkg/services/ngalert/store/alert_rule.go index c1ee47b8071..9804a5978c8 100644 --- a/pkg/services/ngalert/store/alert_rule.go +++ b/pkg/services/ngalert/store/alert_rule.go @@ -404,7 +404,7 @@ func (st DBstore) GetNamespaceByTitle(ctx context.Context, namespace string, org } if withCanSave { - g := guardian.New(folder.Id, orgID, user) + g := guardian.New(ctx, folder.Id, orgID, user) if canSave, err := g.CanSave(); err != nil || !canSave { if err != nil { st.Logger.Error("checking can save permission has failed", "userId", user.UserId, "username", user.Login, "namespace", namespace, "orgId", orgID, "error", err) diff --git a/pkg/services/ngalert/store/alertmanager.go b/pkg/services/ngalert/store/alertmanager.go index 12a8e9d3357..5f979e69f26 100644 --- a/pkg/services/ngalert/store/alertmanager.go +++ b/pkg/services/ngalert/store/alertmanager.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "xorm.io/builder" + "github.com/grafana/grafana/pkg/services/ngalert/models" "github.com/grafana/grafana/pkg/services/sqlstore" ) @@ -33,6 +35,22 @@ func (st *DBstore) GetLatestAlertmanagerConfiguration(query *models.GetLatestAle }) } +// GetAllLatestAlertmanagerConfiguration returns the latest configuration of every organization +func (st *DBstore) GetAllLatestAlertmanagerConfiguration(ctx context.Context) ([]*models.AlertConfiguration, error) { + var result []*models.AlertConfiguration + err := st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error { + condition := builder.In("id", builder.Select("MAX(id)").From("alert_configuration").GroupBy("org_id")) + if err := sess.Table("alert_configuration").Where(condition).Find(&result); err != nil { + return err + } + return nil + }) + if err != nil { + return nil, err + } + return result, nil +} + // SaveAlertmanagerConfiguration creates an alertmanager configuration. func (st DBstore) SaveAlertmanagerConfiguration(cmd *models.SaveAlertmanagerConfigurationCmd) error { return st.SaveAlertmanagerConfigurationWithCallback(cmd, func() error { return nil }) @@ -41,7 +59,7 @@ func (st DBstore) SaveAlertmanagerConfiguration(cmd *models.SaveAlertmanagerConf type SaveCallback func() error // SaveAlertmanagerConfigurationWithCallback creates an alertmanager configuration version and then executes a callback. -// If the callback results in error in rollsback the transaction. +// If the callback results in error it rolls back the transaction. func (st DBstore) SaveAlertmanagerConfigurationWithCallback(cmd *models.SaveAlertmanagerConfigurationCmd, callback SaveCallback) error { return st.SQLStore.WithTransactionalDbSession(context.Background(), func(sess *sqlstore.DBSession) error { config := models.AlertConfiguration{ diff --git a/pkg/services/ngalert/store/database.go b/pkg/services/ngalert/store/database.go index 9fdad89718a..f247ed7cd28 100644 --- a/pkg/services/ngalert/store/database.go +++ b/pkg/services/ngalert/store/database.go @@ -1,6 +1,7 @@ package store import ( + "context" "time" "github.com/grafana/grafana/pkg/infra/log" @@ -17,6 +18,7 @@ const AlertDefinitionMaxTitleLength = 190 // AlertingStore is the database interface used by the Alertmanager service. type AlertingStore interface { GetLatestAlertmanagerConfiguration(*models.GetLatestAlertmanagerConfigurationQuery) error + GetAllLatestAlertmanagerConfiguration(ctx context.Context) ([]*models.AlertConfiguration, error) SaveAlertmanagerConfiguration(*models.SaveAlertmanagerConfigurationCmd) error SaveAlertmanagerConfigurationWithCallback(*models.SaveAlertmanagerConfigurationCmd, SaveCallback) error } diff --git a/pkg/services/quota/quota.go b/pkg/services/quota/quota.go index 7cb1cb115bd..7e2a923ceeb 100644 --- a/pkg/services/quota/quota.go +++ b/pkg/services/quota/quota.go @@ -63,7 +63,7 @@ func (qs *QuotaService) QuotaReached(c *models.ReqContext, target string) (bool, continue } query := models.GetGlobalQuotaByTargetQuery{Target: scope.Target, IsNgAlertEnabled: qs.Cfg.IsNgAlertEnabled()} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil { return true, err } if query.Result.Used >= scope.DefaultLimit { @@ -79,7 +79,7 @@ func (qs *QuotaService) QuotaReached(c *models.ReqContext, target string) (bool, Default: scope.DefaultLimit, IsNgAlertEnabled: qs.Cfg.IsNgAlertEnabled(), } - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil { return true, err } if query.Result.Limit < 0 { @@ -97,7 +97,7 @@ func (qs *QuotaService) QuotaReached(c *models.ReqContext, target string) (bool, continue } query := models.GetUserQuotaByTargetQuery{UserId: c.UserId, Target: scope.Target, Default: scope.DefaultLimit, IsNgAlertEnabled: qs.Cfg.IsNgAlertEnabled()} - if err := bus.Dispatch(&query); err != nil { + if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil { return true, err } if query.Result.Limit < 0 { diff --git a/pkg/services/sqlstore/dashboard_acl.go b/pkg/services/sqlstore/dashboard_acl.go index 2cf15c4fe2a..1327d8cc313 100644 --- a/pkg/services/sqlstore/dashboard_acl.go +++ b/pkg/services/sqlstore/dashboard_acl.go @@ -8,12 +8,16 @@ import ( "github.com/grafana/grafana/pkg/models" ) -func init() { - bus.AddHandler("sql", GetDashboardAclInfoList) +func (ss *SQLStore) addDashboardACLQueryAndCommandHandlers() { + bus.AddHandlerCtx("sql", ss.GetDashboardAclInfoList) } func (ss *SQLStore) UpdateDashboardACL(dashboardID int64, items []*models.DashboardAcl) error { - return ss.WithTransactionalDbSession(context.Background(), func(sess *DBSession) error { + return ss.UpdateDashboardACLCtx(context.TODO(), dashboardID, items) +} + +func (ss *SQLStore) UpdateDashboardACLCtx(ctx context.Context, dashboardID int64, items []*models.DashboardAcl) error { + return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error { // delete existing items _, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID) if err != nil { @@ -47,13 +51,13 @@ func (ss *SQLStore) UpdateDashboardACL(dashboardID int64, items []*models.Dashbo // 1) Permissions for the dashboard // 2) permissions for its parent folder // 3) if no specific permissions have been set for the dashboard or its parent folder then get the default permissions -func GetDashboardAclInfoList(query *models.GetDashboardAclInfoListQuery) error { - var err error +func (ss *SQLStore) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error { + outerErr := ss.WithDbSession(ctx, func(dbSession *DBSession) error { + query.Result = make([]*models.DashboardAclInfoDTO, 0) + falseStr := dialect.BooleanStr(false) - falseStr := dialect.BooleanStr(false) - - if query.DashboardID == 0 { - sql := `SELECT + if query.DashboardID == 0 { + sql := `SELECT da.id, da.org_id, da.dashboard_id, @@ -69,13 +73,13 @@ func GetDashboardAclInfoList(query *models.GetDashboardAclInfoListQuery) error { '' as title, '' as slug, '' as uid,` + - falseStr + ` AS is_folder,` + - falseStr + ` AS inherited + falseStr + ` AS is_folder,` + + falseStr + ` AS inherited FROM dashboard_acl as da WHERE da.dashboard_id = -1` - query.Result = make([]*models.DashboardAclInfoDTO, 0) - err = x.SQL(sql).Find(&query.Result) - } else { + return dbSession.SQL(sql).Find(&query.Result) + } + rawSQL := ` -- get permissions for the dashboard and its parent folder SELECT @@ -115,13 +119,16 @@ func GetDashboardAclInfoList(query *models.GetDashboardAclInfoListQuery) error { ORDER BY da.id ASC ` - query.Result = make([]*models.DashboardAclInfoDTO, 0) - err = x.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&query.Result) + return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&query.Result) + }) + + if outerErr != nil { + return outerErr } for _, p := range query.Result { p.PermissionName = p.Permission.String() } - return err + return nil } diff --git a/pkg/services/sqlstore/dashboard_acl_test.go b/pkg/services/sqlstore/dashboard_acl_test.go index 13128fcb5af..24d6aea954d 100644 --- a/pkg/services/sqlstore/dashboard_acl_test.go +++ b/pkg/services/sqlstore/dashboard_acl_test.go @@ -4,6 +4,7 @@ package sqlstore import ( + "context" "testing" "github.com/grafana/grafana/pkg/models" @@ -32,7 +33,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading folder acl should include default acl", func() { query := models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 2) @@ -48,7 +49,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading dashboard acl should include acl for parent folder", func() { query := models.GetDashboardAclInfoListQuery{DashboardID: childDash.Id, OrgID: 1} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 2) @@ -69,7 +70,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading dashboard acl should return no acl items", func() { query := models.GetDashboardAclInfoListQuery{DashboardID: childDash.Id, OrgID: 1} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 0) @@ -88,7 +89,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading dashboard acl should include acl for parent folder", func() { query := models.GetDashboardAclInfoListQuery{DashboardID: childDash.Id, OrgID: 1} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 1) @@ -107,7 +108,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading dashboard acl should include acl for parent folder and child", func() { query := models.GetDashboardAclInfoListQuery{OrgID: 1, DashboardID: childDash.Id} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 2) @@ -131,7 +132,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading dashboard acl should include default acl for parent folder and the child acl", func() { query := models.GetDashboardAclInfoListQuery{OrgID: 1, DashboardID: childDash.Id} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) defaultPermissionsId := -1 @@ -157,7 +158,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) q1 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1} - err = GetDashboardAclInfoList(q1) + err = sqlStore.GetDashboardAclInfoList(context.Background(), q1) So(err, ShouldBeNil) So(q1.Result[0].DashboardId, ShouldEqual, savedFolder.Id) @@ -172,7 +173,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) q3 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1} - err = GetDashboardAclInfoList(q3) + err = sqlStore.GetDashboardAclInfoList(context.Background(), q3) So(err, ShouldBeNil) So(len(q3.Result), ShouldEqual, 0) }) @@ -192,7 +193,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) q1 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1} - err = GetDashboardAclInfoList(q1) + err = sqlStore.GetDashboardAclInfoList(context.Background(), q1) So(err, ShouldBeNil) So(q1.Result[0].DashboardId, ShouldEqual, savedFolder.Id) So(q1.Result[0].Permission, ShouldEqual, models.PERMISSION_EDIT) @@ -209,7 +210,7 @@ func TestDashboardAclDataAccess(t *testing.T) { So(err, ShouldBeNil) q3 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1} - err = GetDashboardAclInfoList(q3) + err = sqlStore.GetDashboardAclInfoList(context.Background(), q3) So(err, ShouldBeNil) So(len(q3.Result), ShouldEqual, 1) So(q3.Result[0].DashboardId, ShouldEqual, savedFolder.Id) @@ -225,7 +226,7 @@ func TestDashboardAclDataAccess(t *testing.T) { Convey("When reading dashboard acl should return default permissions", func() { query := models.GetDashboardAclInfoListQuery{DashboardID: rootFolderId, OrgID: 1} - err := GetDashboardAclInfoList(&query) + err := sqlStore.GetDashboardAclInfoList(context.Background(), &query) So(err, ShouldBeNil) So(len(query.Result), ShouldEqual, 2) diff --git a/pkg/services/sqlstore/migrations/ualert/silences.go b/pkg/services/sqlstore/migrations/ualert/silences.go index 845fb1adf45..9e47aa32088 100644 --- a/pkg/services/sqlstore/migrations/ualert/silences.go +++ b/pkg/services/sqlstore/migrations/ualert/silences.go @@ -47,13 +47,22 @@ func (m *migration) addSilence(da dashAlert, rule *alertRule) error { ExpiresAt: time.Now().Add(365 * 20 * time.Hour), // 1 year. } - m.silences = append(m.silences, s) + _, ok := m.silences[da.OrgId] + if !ok { + m.silences[da.OrgId] = make([]*pb.MeshSilence, 0) + } + m.silences[da.OrgId] = append(m.silences[da.OrgId], s) return nil } func (m *migration) writeSilencesFile(orgID int64) error { var buf bytes.Buffer - for _, e := range m.silences { + orgSilences, ok := m.silences[orgID] + if !ok { + return nil + } + + for _, e := range orgSilences { if _, err := pbutil.WriteDelimited(&buf, e); err != nil { return err } diff --git a/pkg/services/sqlstore/migrations/ualert/ualert.go b/pkg/services/sqlstore/migrations/ualert/ualert.go index 0dd26b26942..bd2b1e6b84c 100644 --- a/pkg/services/sqlstore/migrations/ualert/ualert.go +++ b/pkg/services/sqlstore/migrations/ualert/ualert.go @@ -19,6 +19,8 @@ const DASHBOARD_FOLDER = "Migrated %s" // during alert migration cleanup. const FOLDER_CREATED_BY = -8 +const KV_NAMESPACE = "alertmanager" + var migTitle = "move dashboard alerts to unified alerting" var rmMigTitle = "remove unified alerting data" @@ -61,6 +63,7 @@ func AddDashAlertMigration(mg *migrator.Migrator) { seenChannelUIDs: make(map[string]struct{}), migratedChannelsPerOrg: make(map[int64]map[*notificationChannel]struct{}), portedChannelGroupsPerOrg: make(map[int64]map[string]string), + silences: make(map[int64][]*pb.MeshSilence), }) case !ngEnabled && migrationRun: // Remove the migration entry that creates unified alerting data. This is so when the feature @@ -101,6 +104,7 @@ func RerunDashAlertMigration(mg *migrator.Migrator) { seenChannelUIDs: make(map[string]struct{}), migratedChannelsPerOrg: make(map[int64]map[*notificationChannel]struct{}), portedChannelGroupsPerOrg: make(map[int64]map[string]string), + silences: make(map[int64][]*pb.MeshSilence), }) case !ngEnabled && migrationRun: @@ -150,7 +154,7 @@ type migration struct { seenChannelUIDs map[string]struct{} migratedChannelsPerOrg map[int64]map[*notificationChannel]struct{} - silences []*pb.MeshSilence + silences map[int64][]*pb.MeshSilence portedChannelGroupsPerOrg map[int64]map[string]string // Org -> Channel group key -> receiver name. lastReceiverID int // For the auto generated receivers. } @@ -415,6 +419,18 @@ func (m *rmMigration) Exec(sess *xorm.Session, mg *migrator.Migrator) error { return err } + exists, err := sess.IsTableExist("kv_store") + if err != nil { + return err + } + + if exists { + _, err = sess.Exec("delete from kv_store where namespace = ?", KV_NAMESPACE) + if err != nil { + return err + } + } + files, err := getSilenceFileNamesForAllOrgs(mg) if err != nil { return err diff --git a/pkg/services/sqlstore/org_test.go b/pkg/services/sqlstore/org_test.go index b94c3f6e35b..fb027d09a78 100644 --- a/pkg/services/sqlstore/org_test.go +++ b/pkg/services/sqlstore/org_test.go @@ -338,7 +338,7 @@ func TestAccountDataAccess(t *testing.T) { Convey("Should remove dependent permissions for deleted org user", func() { permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash1.Id, OrgID: ac1.OrgId} - err = GetDashboardAclInfoList(permQuery) + err = sqlStore.GetDashboardAclInfoList(context.Background(), permQuery) So(err, ShouldBeNil) So(len(permQuery.Result), ShouldEqual, 0) @@ -346,7 +346,7 @@ func TestAccountDataAccess(t *testing.T) { Convey("Should not remove dashboard permissions for same user in another org", func() { permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash2.Id, OrgID: ac3.OrgId} - err = GetDashboardAclInfoList(permQuery) + err = sqlStore.GetDashboardAclInfoList(context.Background(), permQuery) So(err, ShouldBeNil) So(len(permQuery.Result), ShouldEqual, 1) diff --git a/pkg/services/sqlstore/playlist.go b/pkg/services/sqlstore/playlist.go index 9abfc9f3eb2..f8e1a730d09 100644 --- a/pkg/services/sqlstore/playlist.go +++ b/pkg/services/sqlstore/playlist.go @@ -133,7 +133,7 @@ func SearchPlaylists(query *models.GetPlaylistsQuery) error { sess := x.Limit(query.Limit) if query.Name != "" { - sess.Where("name LIKE ?", query.Name) + sess.Where("name LIKE ?", "%"+query.Name+"%") } sess.Where("org_id = ?", query.OrgId) diff --git a/pkg/services/sqlstore/quota.go b/pkg/services/sqlstore/quota.go index 24d3bb9a802..08c85f076d4 100644 --- a/pkg/services/sqlstore/quota.go +++ b/pkg/services/sqlstore/quota.go @@ -1,6 +1,7 @@ package sqlstore import ( + "context" "fmt" "time" @@ -14,108 +15,111 @@ const ( dashboardTarget = "dashboard" ) -func init() { - bus.AddHandler("sql", GetOrgQuotaByTarget) - bus.AddHandler("sql", GetOrgQuotas) - bus.AddHandler("sql", UpdateOrgQuota) - bus.AddHandler("sql", GetUserQuotaByTarget) - bus.AddHandler("sql", GetUserQuotas) - bus.AddHandler("sql", UpdateUserQuota) - bus.AddHandler("sql", GetGlobalQuotaByTarget) +func (ss *SQLStore) addQuotaQueryAndCommandHandlers() { + bus.AddHandlerCtx("sql", ss.GetOrgQuotaByTarget) + bus.AddHandlerCtx("sql", ss.GetOrgQuotas) + bus.AddHandlerCtx("sql", ss.UpdateOrgQuota) + bus.AddHandlerCtx("sql", ss.GetUserQuotaByTarget) + bus.AddHandlerCtx("sql", ss.GetUserQuotas) + bus.AddHandlerCtx("sql", ss.UpdateUserQuota) + bus.AddHandlerCtx("sql", ss.GetGlobalQuotaByTarget) } type targetCount struct { Count int64 } -func GetOrgQuotaByTarget(query *models.GetOrgQuotaByTargetQuery) error { - quota := models.Quota{ - Target: query.Target, - OrgId: query.OrgId, - } - has, err := x.Get("a) - if err != nil { - return err - } else if !has { - quota.Limit = query.Default - } - - var used int64 - if query.Target != alertRuleTarget || query.IsNgAlertEnabled { - // get quota used. - rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s WHERE org_id=?", - dialect.Quote(query.Target)) - - if query.Target == dashboardTarget { - rawSQL += fmt.Sprintf(" AND is_folder=%s", dialect.BooleanStr(false)) +func (ss *SQLStore) GetOrgQuotaByTarget(ctx context.Context, query *models.GetOrgQuotaByTargetQuery) error { + return ss.WithDbSession(ctx, func(sess *DBSession) error { + quota := models.Quota{ + Target: query.Target, + OrgId: query.OrgId, } - - resp := make([]*targetCount, 0) - if err := x.SQL(rawSQL, query.OrgId).Find(&resp); err != nil { + has, err := sess.Get("a) + if err != nil { return err + } else if !has { + quota.Limit = query.Default } - used = resp[0].Count - } - query.Result = &models.OrgQuotaDTO{ - Target: query.Target, - Limit: quota.Limit, - OrgId: query.OrgId, - Used: used, - } - - return nil -} - -func GetOrgQuotas(query *models.GetOrgQuotasQuery) error { - quotas := make([]*models.Quota, 0) - sess := x.Table("quota") - if err := sess.Where("org_id=? AND user_id=0", query.OrgId).Find("as); err != nil { - return err - } - - defaultQuotas := setting.Quota.Org.ToMap() - - seenTargets := make(map[string]bool) - for _, q := range quotas { - seenTargets[q.Target] = true - } - - for t, v := range defaultQuotas { - if _, ok := seenTargets[t]; !ok { - quotas = append(quotas, &models.Quota{ - OrgId: query.OrgId, - Target: t, - Limit: v, - }) - } - } - - result := make([]*models.OrgQuotaDTO, len(quotas)) - for i, q := range quotas { var used int64 - if q.Target != alertRuleTarget || query.IsNgAlertEnabled { + if query.Target != alertRuleTarget || query.IsNgAlertEnabled { // get quota used. - rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", dialect.Quote(q.Target)) + rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s WHERE org_id=?", + dialect.Quote(query.Target)) + + if query.Target == dashboardTarget { + rawSQL += fmt.Sprintf(" AND is_folder=%s", dialect.BooleanStr(false)) + } + resp := make([]*targetCount, 0) - if err := x.SQL(rawSQL, q.OrgId).Find(&resp); err != nil { + if err := sess.SQL(rawSQL, query.OrgId).Find(&resp); err != nil { return err } used = resp[0].Count } - result[i] = &models.OrgQuotaDTO{ - Target: q.Target, - Limit: q.Limit, - OrgId: q.OrgId, + + query.Result = &models.OrgQuotaDTO{ + Target: query.Target, + Limit: quota.Limit, + OrgId: query.OrgId, Used: used, } - } - query.Result = result - return nil + + return nil + }) } -func UpdateOrgQuota(cmd *models.UpdateOrgQuotaCmd) error { - return inTransaction(func(sess *DBSession) error { +func (ss *SQLStore) GetOrgQuotas(ctx context.Context, query *models.GetOrgQuotasQuery) error { + return ss.WithDbSession(ctx, func(sess *DBSession) error { + quotas := make([]*models.Quota, 0) + if err := sess.Table("quota").Where("org_id=? AND user_id=0", query.OrgId).Find("as); err != nil { + return err + } + + defaultQuotas := setting.Quota.Org.ToMap() + + seenTargets := make(map[string]bool) + for _, q := range quotas { + seenTargets[q.Target] = true + } + + for t, v := range defaultQuotas { + if _, ok := seenTargets[t]; !ok { + quotas = append(quotas, &models.Quota{ + OrgId: query.OrgId, + Target: t, + Limit: v, + }) + } + } + + result := make([]*models.OrgQuotaDTO, len(quotas)) + for i, q := range quotas { + var used int64 + if q.Target != alertRuleTarget || query.IsNgAlertEnabled { + // get quota used. + rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where org_id=?", dialect.Quote(q.Target)) + resp := make([]*targetCount, 0) + if err := sess.SQL(rawSQL, q.OrgId).Find(&resp); err != nil { + return err + } + used = resp[0].Count + } + result[i] = &models.OrgQuotaDTO{ + Target: q.Target, + Limit: q.Limit, + OrgId: q.OrgId, + Used: used, + } + } + query.Result = result + return nil + }) +} + +func (ss *SQLStore) UpdateOrgQuota(ctx context.Context, cmd *models.UpdateOrgQuotaCmd) error { + return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error { // Check if quota is already defined in the DB quota := models.Quota{ Target: cmd.Target, @@ -145,88 +149,91 @@ func UpdateOrgQuota(cmd *models.UpdateOrgQuotaCmd) error { }) } -func GetUserQuotaByTarget(query *models.GetUserQuotaByTargetQuery) error { - quota := models.Quota{ - Target: query.Target, - UserId: query.UserId, - } - has, err := x.Get("a) - if err != nil { - return err - } else if !has { - quota.Limit = query.Default - } - - var used int64 - if query.Target != alertRuleTarget || query.IsNgAlertEnabled { - // get quota used. - rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(query.Target)) - resp := make([]*targetCount, 0) - if err := x.SQL(rawSQL, query.UserId).Find(&resp); err != nil { +func (ss *SQLStore) GetUserQuotaByTarget(ctx context.Context, query *models.GetUserQuotaByTargetQuery) error { + return ss.WithDbSession(ctx, func(sess *DBSession) error { + quota := models.Quota{ + Target: query.Target, + UserId: query.UserId, + } + has, err := sess.Get("a) + if err != nil { return err + } else if !has { + quota.Limit = query.Default } - used = resp[0].Count - } - query.Result = &models.UserQuotaDTO{ - Target: query.Target, - Limit: quota.Limit, - UserId: query.UserId, - Used: used, - } - - return nil -} - -func GetUserQuotas(query *models.GetUserQuotasQuery) error { - quotas := make([]*models.Quota, 0) - sess := x.Table("quota") - if err := sess.Where("user_id=? AND org_id=0", query.UserId).Find("as); err != nil { - return err - } - - defaultQuotas := setting.Quota.User.ToMap() - - seenTargets := make(map[string]bool) - for _, q := range quotas { - seenTargets[q.Target] = true - } - - for t, v := range defaultQuotas { - if _, ok := seenTargets[t]; !ok { - quotas = append(quotas, &models.Quota{ - UserId: query.UserId, - Target: t, - Limit: v, - }) - } - } - - result := make([]*models.UserQuotaDTO, len(quotas)) - for i, q := range quotas { var used int64 - if q.Target != alertRuleTarget || query.IsNgAlertEnabled { + if query.Target != alertRuleTarget || query.IsNgAlertEnabled { // get quota used. - rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(q.Target)) + rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(query.Target)) resp := make([]*targetCount, 0) - if err := x.SQL(rawSQL, q.UserId).Find(&resp); err != nil { + if err := sess.SQL(rawSQL, query.UserId).Find(&resp); err != nil { return err } used = resp[0].Count } - result[i] = &models.UserQuotaDTO{ - Target: q.Target, - Limit: q.Limit, - UserId: q.UserId, + + query.Result = &models.UserQuotaDTO{ + Target: query.Target, + Limit: quota.Limit, + UserId: query.UserId, Used: used, } - } - query.Result = result - return nil + + return nil + }) } -func UpdateUserQuota(cmd *models.UpdateUserQuotaCmd) error { - return inTransaction(func(sess *DBSession) error { +func (ss *SQLStore) GetUserQuotas(ctx context.Context, query *models.GetUserQuotasQuery) error { + return ss.WithDbSession(ctx, func(sess *DBSession) error { + quotas := make([]*models.Quota, 0) + if err := sess.Table("quota").Where("user_id=? AND org_id=0", query.UserId).Find("as); err != nil { + return err + } + + defaultQuotas := setting.Quota.User.ToMap() + + seenTargets := make(map[string]bool) + for _, q := range quotas { + seenTargets[q.Target] = true + } + + for t, v := range defaultQuotas { + if _, ok := seenTargets[t]; !ok { + quotas = append(quotas, &models.Quota{ + UserId: query.UserId, + Target: t, + Limit: v, + }) + } + } + + result := make([]*models.UserQuotaDTO, len(quotas)) + for i, q := range quotas { + var used int64 + if q.Target != alertRuleTarget || query.IsNgAlertEnabled { + // get quota used. + rawSQL := fmt.Sprintf("SELECT COUNT(*) as count from %s where user_id=?", dialect.Quote(q.Target)) + resp := make([]*targetCount, 0) + if err := sess.SQL(rawSQL, q.UserId).Find(&resp); err != nil { + return err + } + used = resp[0].Count + } + result[i] = &models.UserQuotaDTO{ + Target: q.Target, + Limit: q.Limit, + UserId: q.UserId, + Used: used, + } + } + query.Result = result + return nil + }) +} + +func (ss *SQLStore) UpdateUserQuota(ctx context.Context, cmd *models.UpdateUserQuotaCmd) error { + return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error { // Check if quota is already defined in the DB quota := models.Quota{ Target: cmd.Target, @@ -256,29 +263,31 @@ func UpdateUserQuota(cmd *models.UpdateUserQuotaCmd) error { }) } -func GetGlobalQuotaByTarget(query *models.GetGlobalQuotaByTargetQuery) error { - var used int64 - if query.Target != alertRuleTarget || query.IsNgAlertEnabled { - // get quota used. - rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s", - dialect.Quote(query.Target)) +func (ss *SQLStore) GetGlobalQuotaByTarget(ctx context.Context, query *models.GetGlobalQuotaByTargetQuery) error { + return ss.WithDbSession(ctx, func(sess *DBSession) error { + var used int64 + if query.Target != alertRuleTarget || query.IsNgAlertEnabled { + // get quota used. + rawSQL := fmt.Sprintf("SELECT COUNT(*) AS count FROM %s", + dialect.Quote(query.Target)) - if query.Target == dashboardTarget { - rawSQL += fmt.Sprintf(" WHERE is_folder=%s", dialect.BooleanStr(false)) + if query.Target == dashboardTarget { + rawSQL += fmt.Sprintf(" WHERE is_folder=%s", dialect.BooleanStr(false)) + } + + resp := make([]*targetCount, 0) + if err := sess.SQL(rawSQL).Find(&resp); err != nil { + return err + } + used = resp[0].Count } - resp := make([]*targetCount, 0) - if err := x.SQL(rawSQL).Find(&resp); err != nil { - return err + query.Result = &models.GlobalQuotaDTO{ + Target: query.Target, + Limit: query.Default, + Used: used, } - used = resp[0].Count - } - query.Result = &models.GlobalQuotaDTO{ - Target: query.Target, - Limit: query.Default, - Used: used, - } - - return nil + return nil + }) } diff --git a/pkg/services/sqlstore/quota_test.go b/pkg/services/sqlstore/quota_test.go index e2751f81c98..81a24316b94 100644 --- a/pkg/services/sqlstore/quota_test.go +++ b/pkg/services/sqlstore/quota_test.go @@ -4,6 +4,7 @@ package sqlstore import ( + "context" "testing" "time" @@ -13,7 +14,7 @@ import ( ) func TestQuotaCommandsAndQueries(t *testing.T) { - InitTestDB(t) + sqlStore := InitTestDB(t) userId := int64(1) orgId := int64(0) @@ -58,12 +59,12 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: "org_user", Limit: 10, } - err := UpdateOrgQuota(&orgCmd) + err := sqlStore.UpdateOrgQuota(context.Background(), &orgCmd) require.NoError(t, err) t.Run("Should be able to get saved quota by org id and target", func(t *testing.T) { query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 1} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(10), query.Result.Limit) @@ -71,7 +72,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get default quota by org id and target", func(t *testing.T) { query := models.GetOrgQuotaByTargetQuery{OrgId: 123, Target: "org_user", Default: 11} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(11), query.Result.Limit) @@ -79,7 +80,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get used org quota when rows exist", func(t *testing.T) { query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 11} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(1), query.Result.Used) @@ -87,7 +88,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get used org quota when no rows exist", func(t *testing.T) { query := models.GetOrgQuotaByTargetQuery{OrgId: 2, Target: "org_user", Default: 11} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(0), query.Result.Used) @@ -95,7 +96,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get zero used org alert quota when table does not exist (ngalert is not enabled - default case)", func(t *testing.T) { query := models.GetOrgQuotaByTargetQuery{OrgId: 2, Target: "alert", Default: 11} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(0), query.Result.Used) @@ -103,7 +104,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to quota list for org", func(t *testing.T) { query := models.GetOrgQuotasQuery{OrgId: orgId} - err = GetOrgQuotas(&query) + err = sqlStore.GetOrgQuotas(context.Background(), &query) require.NoError(t, err) require.Len(t, query.Result, 5) @@ -126,12 +127,12 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: dashboardTarget, Limit: 10, } - err := UpdateOrgQuota(&orgCmd) + err := sqlStore.UpdateOrgQuota(context.Background(), &orgCmd) require.NoError(t, err) t.Run("Should be able to get saved quota by org id and target", func(t *testing.T) { query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: dashboardTarget, Default: 1} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(10), query.Result.Limit) @@ -145,12 +146,12 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: "org_user", Limit: 10, } - err := UpdateUserQuota(&userQuotaCmd) + err := sqlStore.UpdateUserQuota(context.Background(), &userQuotaCmd) require.NoError(t, err) t.Run("Should be able to get saved quota by user id and target", func(t *testing.T) { query := models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 1} - err = GetUserQuotaByTarget(&query) + err = sqlStore.GetUserQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(10), query.Result.Limit) @@ -158,7 +159,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get default quota by user id and target", func(t *testing.T) { query := models.GetUserQuotaByTargetQuery{UserId: 9, Target: "org_user", Default: 11} - err = GetUserQuotaByTarget(&query) + err = sqlStore.GetUserQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(11), query.Result.Limit) @@ -166,7 +167,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get used user quota when rows exist", func(t *testing.T) { query := models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 11} - err = GetUserQuotaByTarget(&query) + err = sqlStore.GetUserQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(1), query.Result.Used) @@ -174,7 +175,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get used user quota when no rows exist", func(t *testing.T) { query := models.GetUserQuotaByTargetQuery{UserId: 2, Target: "org_user", Default: 11} - err = GetUserQuotaByTarget(&query) + err = sqlStore.GetUserQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(0), query.Result.Used) @@ -182,7 +183,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to quota list for user", func(t *testing.T) { query := models.GetUserQuotasQuery{UserId: userId} - err = GetUserQuotas(&query) + err = sqlStore.GetUserQuotas(context.Background(), &query) require.NoError(t, err) require.Len(t, query.Result, 1) @@ -193,7 +194,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to global user quota", func(t *testing.T) { query := models.GetGlobalQuotaByTargetQuery{Target: "user", Default: 5} - err = GetGlobalQuotaByTarget(&query) + err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(5), query.Result.Limit) @@ -202,7 +203,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to global org quota", func(t *testing.T) { query := models.GetGlobalQuotaByTargetQuery{Target: "org", Default: 5} - err = GetGlobalQuotaByTarget(&query) + err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(5), query.Result.Limit) @@ -211,7 +212,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to get zero used global alert quota when table does not exist (ngalert is not enabled - default case)", func(t *testing.T) { query := models.GetGlobalQuotaByTargetQuery{Target: "alert_rule", Default: 5} - err = GetGlobalQuotaByTarget(&query) + err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(5), query.Result.Limit) @@ -220,7 +221,7 @@ func TestQuotaCommandsAndQueries(t *testing.T) { t.Run("Should be able to global dashboard quota", func(t *testing.T) { query := models.GetGlobalQuotaByTargetQuery{Target: dashboardTarget, Default: 5} - err = GetGlobalQuotaByTarget(&query) + err = sqlStore.GetGlobalQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(5), query.Result.Limit) @@ -234,11 +235,11 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: "org_user", Limit: 5, } - err := UpdateOrgQuota(&orgCmd) + err := sqlStore.UpdateOrgQuota(context.Background(), &orgCmd) require.NoError(t, err) query := models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 1} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(5), query.Result.Limit) @@ -250,11 +251,11 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: "org_user", Limit: 10, } - err = UpdateOrgQuota(&orgCmd) + err = sqlStore.UpdateOrgQuota(context.Background(), &orgCmd) require.NoError(t, err) query = models.GetOrgQuotaByTargetQuery{OrgId: orgId, Target: "org_user", Default: 1} - err = GetOrgQuotaByTarget(&query) + err = sqlStore.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(10), query.Result.Limit) }) @@ -266,11 +267,11 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: "org_user", Limit: 5, } - err := UpdateUserQuota(&userQuotaCmd) + err := sqlStore.UpdateUserQuota(context.Background(), &userQuotaCmd) require.NoError(t, err) query := models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 1} - err = GetUserQuotaByTarget(&query) + err = sqlStore.GetUserQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(5), query.Result.Limit) @@ -282,11 +283,11 @@ func TestQuotaCommandsAndQueries(t *testing.T) { Target: "org_user", Limit: 10, } - err = UpdateUserQuota(&userQuotaCmd) + err = sqlStore.UpdateUserQuota(context.Background(), &userQuotaCmd) require.NoError(t, err) query = models.GetUserQuotaByTargetQuery{UserId: userId, Target: "org_user", Default: 1} - err = GetUserQuotaByTarget(&query) + err = sqlStore.GetUserQuotaByTarget(context.Background(), &query) require.NoError(t, err) require.Equal(t, int64(10), query.Result.Limit) }) diff --git a/pkg/services/sqlstore/sqlstore.go b/pkg/services/sqlstore/sqlstore.go index 122d2470a7f..c37d6370cac 100644 --- a/pkg/services/sqlstore/sqlstore.go +++ b/pkg/services/sqlstore/sqlstore.go @@ -113,6 +113,8 @@ func newSQLStore(cfg *setting.Cfg, cacheService *localcache.CacheService, bus bu ss.addAlertNotificationUidByIdHandler() ss.addPreferencesQueryAndCommandHandlers() ss.addDashboardQueryAndCommandHandlers() + ss.addDashboardACLQueryAndCommandHandlers() + ss.addQuotaQueryAndCommandHandlers() // if err := ss.Reset(); err != nil { // return nil, err diff --git a/pkg/services/sqlstore/team_test.go b/pkg/services/sqlstore/team_test.go index 981285442f7..7ac44d142b6 100644 --- a/pkg/services/sqlstore/team_test.go +++ b/pkg/services/sqlstore/team_test.go @@ -262,7 +262,7 @@ func TestTeamCommandsAndQueries(t *testing.T) { So(err, ShouldEqual, models.ErrTeamNotFound) permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: testOrgID} - err = GetDashboardAclInfoList(permQuery) + err = sqlStore.GetDashboardAclInfoList(context.Background(), permQuery) So(err, ShouldBeNil) So(len(permQuery.Result), ShouldEqual, 0) diff --git a/pkg/services/sqlstore/user_test.go b/pkg/services/sqlstore/user_test.go index ae0ed8369d8..5306b8d47da 100644 --- a/pkg/services/sqlstore/user_test.go +++ b/pkg/services/sqlstore/user_test.go @@ -261,7 +261,7 @@ func TestUserDataAccess(t *testing.T) { require.Len(t, query1.Result, 1) permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: users[0].OrgId} - err = GetDashboardAclInfoList(permQuery) + err = ss.GetDashboardAclInfoList(context.Background(), permQuery) require.Nil(t, err) require.Len(t, permQuery.Result, 0) @@ -347,7 +347,7 @@ func TestUserDataAccess(t *testing.T) { require.Len(t, query2.Result, 1) permQuery = &models.GetDashboardAclInfoListQuery{DashboardID: 1, OrgID: users[0].OrgId} - err = GetDashboardAclInfoList(permQuery) + err = ss.GetDashboardAclInfoList(context.Background(), permQuery) require.Nil(t, err) require.Len(t, permQuery.Result, 0) diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 20102cba6fd..3e4201a1f6d 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -19,7 +19,7 @@ import ( "time" "github.com/grafana/grafana-aws-sdk/pkg/awsds" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/util" diff --git a/pkg/setting/setting_unified_alerting.go b/pkg/setting/setting_unified_alerting.go index 97c2e3cb49c..637e7d96998 100644 --- a/pkg/setting/setting_unified_alerting.go +++ b/pkg/setting/setting_unified_alerting.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/prometheus/alertmanager/cluster" "gopkg.in/ini.v1" @@ -17,6 +17,28 @@ const ( AlertmanagerDefaultPushPullInterval = cluster.DefaultPushPullInterval SchedulerDefaultAdminConfigPollInterval = 60 * time.Second AlertmanagerDefaultConfigPollInterval = 60 * time.Second + // To start, the alertmanager needs at least one route defined. + // TODO: we should move this to Grafana settings and define this as the default. + AlertmanagerDefaultConfiguration = `{ + "alertmanager_config": { + "route": { + "receiver": "grafana-default-email" + }, + "receivers": [{ + "name": "grafana-default-email", + "grafana_managed_receiver_configs": [{ + "uid": "", + "name": "email receiver", + "type": "email", + "isDefault": true, + "settings": { + "addresses": "" + } + }] + }] + } +} +` ) type UnifiedAlertingSettings struct { @@ -28,6 +50,7 @@ type UnifiedAlertingSettings struct { HAPeerTimeout time.Duration HAGossipInterval time.Duration HAPushPullInterval time.Duration + DefaultConfiguration string } func (cfg *Cfg) ReadUnifiedAlertingSettings(iniFile *ini.File) error { @@ -64,6 +87,8 @@ func (cfg *Cfg) ReadUnifiedAlertingSettings(iniFile *ini.File) error { uaCfg.HAPeers = append(uaCfg.HAPeers, peer) } } + // TODO load from ini file + uaCfg.DefaultConfiguration = AlertmanagerDefaultConfiguration cfg.UnifiedAlerting = uaCfg return nil } diff --git a/pkg/tests/api/alerting/api_alertmanager_test.go b/pkg/tests/api/alerting/api_alertmanager_test.go index 9ad29cdfbd6..2db8b6687f8 100644 --- a/pkg/tests/api/alerting/api_alertmanager_test.go +++ b/pkg/tests/api/alerting/api_alertmanager_test.go @@ -2018,7 +2018,7 @@ func TestQuota(t *testing.T) { t.Run("when quota limit exceed creating new rule should fail", func(t *testing.T) { // get existing org quota query := models.GetOrgQuotaByTargetQuery{OrgId: 1, Target: "alert_rule"} - err = sqlstore.GetOrgQuotaByTarget(&query) + err = store.GetOrgQuotaByTarget(context.Background(), &query) require.NoError(t, err) used := query.Result.Used limit := query.Result.Limit @@ -2029,7 +2029,7 @@ func TestQuota(t *testing.T) { Target: "alert_rule", Limit: used, } - err := sqlstore.UpdateOrgQuota(&orgCmd) + err := store.UpdateOrgQuota(context.Background(), &orgCmd) require.NoError(t, err) t.Cleanup(func() { @@ -2039,7 +2039,7 @@ func TestQuota(t *testing.T) { Target: "alert_rule", Limit: limit, } - err := sqlstore.UpdateOrgQuota(&orgCmd) + err := store.UpdateOrgQuota(context.Background(), &orgCmd) require.NoError(t, err) }) diff --git a/pkg/tsdb/cloudmonitoring/cloudmonitoring_test.go b/pkg/tsdb/cloudmonitoring/cloudmonitoring_test.go index fcc627c3c10..0125970af44 100644 --- a/pkg/tsdb/cloudmonitoring/cloudmonitoring_test.go +++ b/pkg/tsdb/cloudmonitoring/cloudmonitoring_test.go @@ -942,7 +942,7 @@ func TestCloudMonitoring(t *testing.T) { query := &cloudMonitoringTimeSeriesQuery{ ProjectName: "test-proj", Query: "test-query", - AliasBy: "{{project}} - {{resource.label.zone}} - {{resource.label.instance_id}}", + AliasBy: "{{project}} - {{resource.label.zone}} - {{resource.label.instance_id}} - {{metric.label.response_code_class}}", timeRange: plugins.DataTimeRange{ From: fmt.Sprintf("%v", fromStart.Unix()*1000), To: fmt.Sprintf("%v", fromStart.Add(34*time.Minute).Unix()*1000), @@ -952,7 +952,7 @@ func TestCloudMonitoring(t *testing.T) { require.NoError(t, err) frames, err := res.Dataframes.Decoded() require.NoError(t, err) - assert.Equal(t, "test-proj - asia-northeast1-c - 6724404429462225363", frames[0].Fields[1].Name) + assert.Equal(t, "test-proj - asia-northeast1-c - 6724404429462225363 - 200", frames[0].Fields[1].Name) }) }) }) diff --git a/pkg/tsdb/cloudmonitoring/test-data/7-series-response-mql.json b/pkg/tsdb/cloudmonitoring/test-data/7-series-response-mql.json index 0bb57fc4116..62233e23d8d 100644 --- a/pkg/tsdb/cloudmonitoring/test-data/7-series-response-mql.json +++ b/pkg/tsdb/cloudmonitoring/test-data/7-series-response-mql.json @@ -9,6 +9,10 @@ }, { "key": "resource.instance_id" + }, + { + "key": "metric.response_code_class", + "valueType": "INT64" } ], "pointDescriptors": [ @@ -30,6 +34,9 @@ }, { "stringValue": "6724404429462225363" + }, + { + "int64Value": "200" } ], "pointData": [ diff --git a/pkg/tsdb/cloudmonitoring/time_series_query.go b/pkg/tsdb/cloudmonitoring/time_series_query.go index 86b9b6bfc88..2fb54136ec2 100644 --- a/pkg/tsdb/cloudmonitoring/time_series_query.go +++ b/pkg/tsdb/cloudmonitoring/time_series_query.go @@ -123,9 +123,8 @@ func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) parseResponse(queryRes *pl labels[key][strVal] = true seriesLabels[key] = strVal case "INT64": - intVal := strconv.FormatInt(labelValue.Int64Value, 10) - labels[key][intVal] = true - seriesLabels[key] = intVal + labels[key][labelValue.Int64Value] = true + seriesLabels[key] = labelValue.Int64Value default: labels[key][labelValue.StringValue] = true seriesLabels[key] = labelValue.StringValue @@ -285,8 +284,7 @@ func (timeSeriesQuery cloudMonitoringTimeSeriesQuery) parseToAnnotations(queryRe strVal := strconv.FormatBool(labelValue.BoolValue) value = strVal case "INT64": - intVal := strconv.FormatInt(labelValue.Int64Value, 10) - value = intVal + value = labelValue.Int64Value default: value = labelValue.StringValue } diff --git a/pkg/tsdb/cloudmonitoring/types.go b/pkg/tsdb/cloudmonitoring/types.go index 25a911b9227..95c6dc76a51 100644 --- a/pkg/tsdb/cloudmonitoring/types.go +++ b/pkg/tsdb/cloudmonitoring/types.go @@ -118,7 +118,7 @@ type timeSeriesDescriptor struct { type timeSeriesData []struct { LabelValues []struct { BoolValue bool `json:"boolValue"` - Int64Value int64 `json:"int64Value"` + Int64Value string `json:"int64Value"` StringValue string `json:"stringValue"` } `json:"labelValues"` PointData []struct { diff --git a/pkg/tsdb/cloudwatch/metric_data_query_builder.go b/pkg/tsdb/cloudwatch/metric_data_query_builder.go index ab5cbed0505..34c6a8b246f 100644 --- a/pkg/tsdb/cloudwatch/metric_data_query_builder.go +++ b/pkg/tsdb/cloudwatch/metric_data_query_builder.go @@ -18,6 +18,7 @@ func (e *cloudWatchExecutor) buildMetricDataQuery(query *cloudWatchQuery) (*clou if query.Expression != "" { mdq.Expression = aws.String(query.Expression) + mdq.Period = aws.Int64(int64(query.Period)) } else { if query.isSearchExpression() { mdq.Expression = aws.String(buildSearchExpression(query, query.Statistic)) diff --git a/pkg/tsdb/cloudwatch/metric_data_query_builder_test.go b/pkg/tsdb/cloudwatch/metric_data_query_builder_test.go index 407dc917307..80ffb3ec54b 100644 --- a/pkg/tsdb/cloudwatch/metric_data_query_builder_test.go +++ b/pkg/tsdb/cloudwatch/metric_data_query_builder_test.go @@ -4,9 +4,32 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMetricDataQueryBuilder_buildSearchExpression(t *testing.T) { + t.Run("buildMetricDataQuery", func(t *testing.T) { + t.Run("should set period in user defined expression", func(t *testing.T) { + executor := newExecutor(nil, nil, newTestConfig(), fakeSessionCache{}) + query := &cloudWatchQuery{ + Namespace: "AWS/EC2", + MetricName: "CPUUtilization", + Dimensions: map[string][]string{ + "LoadBalancer": {"lb1"}, + }, + Period: 300, + Expression: "SUM([a,b])", + MatchExact: true, + } + query.MatchExact = false + mdq, err := executor.buildMetricDataQuery(query) + require.NoError(t, err) + require.Nil(t, mdq.MetricStat) + assert.Equal(t, int64(300), *mdq.Period) + assert.Equal(t, `SUM([a,b])`, *mdq.Expression) + }) + }) + t.Run("Query should be matched exact", func(t *testing.T) { const matchExact = true diff --git a/pkg/tsdb/cloudwatch/metric_find_query.go b/pkg/tsdb/cloudwatch/metric_find_query.go index 5cd5de842f9..a960a6671b1 100644 --- a/pkg/tsdb/cloudwatch/metric_find_query.go +++ b/pkg/tsdb/cloudwatch/metric_find_query.go @@ -111,6 +111,7 @@ var metricsMap = map[string][]string{ "AWS/NATGateway": {"ActiveConnectionCount", "BytesInFromDestination", "BytesInFromSource", "BytesOutToDestination", "BytesOutToSource", "ConnectionAttemptCount", "ConnectionEstablishedCount", "ErrorPortAllocation", "IdleTimeoutCount", "PacketsDropCount", "PacketsInFromDestination", "PacketsInFromSource", "PacketsOutToDestination", "PacketsOutToSource"}, "AWS/Neptune": {"CPUUtilization", "ClusterReplicaLag", "ClusterReplicaLagMaximum", "ClusterReplicaLagMinimum", "EngineUptime", "FreeLocalStorage", "FreeableMemory", "GremlinErrors", "GremlinHttp1xx", "GremlinHttp2xx", "GremlinHttp4xx", "GremlinHttp5xx", "GremlinRequests", "GremlinRequestsPerSec", "GremlinWebSocketAvailableConnections", "GremlinWebSocketClientErrors", "GremlinWebSocketServerErrors", "GremlinWebSocketSuccess", "Http100", "Http101", "Http1xx", "Http200", "Http2xx", "Http400", "Http403", "Http405", "Http413", "Http429", "Http4xx", "Http500", "Http501", "Http5xx", "LoaderErrors", "LoaderRequests", "NetworkReceiveThroughput", "NetworkThroughput", "NetworkTransmitThroughput", "SparqlErrors", "SparqlHttp1xx", "SparqlHttp2xx", "SparqlHttp4xx", "SparqlHttp5xx", "SparqlRequests", "SparqlRequestsPerSec", "StatusErrors", "StatusRequests", "VolumeBytesUsed", "VolumeReadIOPs", "VolumeWriteIOPs"}, "AWS/NetworkELB": {"ActiveFlowCount", "ActiveFlowCount_TLS", "ClientTLSNegotiationErrorCount", "ConsumedLCUs", "HealthyHostCount", "NewFlowCount", "NewFlowCount_TLS", "ProcessedBytes", "ProcessedBytes_TLS", "TCP_Client_Reset_Count", "TCP_ELB_Reset_Count", "TCP_Target_Reset_Count", "TargetTLSNegotiationErrorCount", "UnHealthyHostCount"}, + "AWS/GatewayELB": {"ActiveFlowCount", "ConsumedLCUs", "HealthyHostCount", "NewFlowCount", "ProcessedBytes", "UnHealthyHostCount"}, "AWS/NetworkFirewall": {"DroppedPackets", "Packets", "PassedPackets", "ReceivedPacketCount"}, "AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_steal", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_15", "load_5", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"}, "AWS/Polly": {"2XXCount", "4XXCount", "5XXCount", "RequestCharacters", "ResponseLatency"}, @@ -215,6 +216,7 @@ var dimensionsMap = map[string][]string{ "AWS/NATGateway": {"NatGatewayId"}, "AWS/Neptune": {"DBClusterIdentifier", "DatabaseClass", "EngineName", "Role"}, "AWS/NetworkELB": {"AvailabilityZone", "LoadBalancer", "TargetGroup"}, + "AWS/GatewayELB": {"AvailabilityZone", "LoadBalancer", "TargetGroup"}, "AWS/NetworkFirewall": {"AvailabilityZone", "CustomAction", "Engine", "FirewallName"}, "AWS/OpsWorks": {"InstanceId", "LayerId", "StackId"}, "AWS/Polly": {"Operation"}, diff --git a/pkg/tsdb/elasticsearch/elasticsearch.go b/pkg/tsdb/elasticsearch/elasticsearch.go index 6dde9658266..e641550d7b0 100644 --- a/pkg/tsdb/elasticsearch/elasticsearch.go +++ b/pkg/tsdb/elasticsearch/elasticsearch.go @@ -84,6 +84,11 @@ func newInstanceSettings() datasource.InstanceFactoryFunc { return nil, fmt.Errorf("error getting http options: %w", err) } + // Set SigV4 service namespace + if httpCliOpts.SigV4 != nil { + httpCliOpts.SigV4.Service = "es" + } + version, err := coerceVersion(jsonData["esVersion"]) if err != nil { diff --git a/pkg/tsdb/influxdb/flux/executor.go b/pkg/tsdb/influxdb/flux/executor.go index 991e3fde6ad..79d6d68b589 100644 --- a/pkg/tsdb/influxdb/flux/executor.go +++ b/pkg/tsdb/influxdb/flux/executor.go @@ -18,11 +18,7 @@ const maxPointsEnforceFactor float64 = 10 func executeQuery(ctx context.Context, query queryModel, runner queryRunner, maxSeries int) (dr backend.DataResponse) { dr = backend.DataResponse{} - flux, err := interpolate(query) - if err != nil { - dr.Error = err - return - } + flux := interpolate(query) glog.Debug("Executing Flux query", "flux", flux) diff --git a/pkg/tsdb/influxdb/flux/macros.go b/pkg/tsdb/influxdb/flux/macros.go index 2db350c99fc..ed3a34d2d20 100644 --- a/pkg/tsdb/influxdb/flux/macros.go +++ b/pkg/tsdb/influxdb/flux/macros.go @@ -2,22 +2,36 @@ package flux import ( "regexp" + "strconv" "strings" "time" + + "github.com/grafana/grafana/pkg/tsdb/intervalv2" ) -const variableFilter = `(?m)([a-zA-Z]+)\.([a-zA-Z]+)` +// $__interval_ms is the exact value in milliseconds +// $__interval is rounded to nice whole values +// v.windowPeriod is the exact value string-formatted -// interpolate processes macros -func interpolate(query queryModel) (string, error) { +func interpolateInterval(flux string, interval time.Duration) string { + intervalMs := int64(interval / time.Millisecond) + intervalText := intervalv2.FormatDuration(interval) + + flux = strings.ReplaceAll(flux, "$__interval_ms", strconv.FormatInt(intervalMs, 10)) + flux = strings.ReplaceAll(flux, "$__interval", intervalText) + return flux +} + +var fluxVariableFilterExp = regexp.MustCompile(`(?m)([a-zA-Z]+)\.([a-zA-Z]+)`) + +func interpolateFluxSpecificVariables(query queryModel) string { flux := query.RawQuery - variableFilterExp, err := regexp.Compile(variableFilter) - matches := variableFilterExp.FindAllStringSubmatch(flux, -1) + matches := fluxVariableFilterExp.FindAllStringSubmatch(flux, -1) if matches != nil { timeRange := query.TimeRange - from := timeRange.From.UTC().Format(time.RFC3339) - to := timeRange.To.UTC().Format(time.RFC3339) + from := timeRange.From.UTC().Format(time.RFC3339Nano) + to := timeRange.To.UTC().Format(time.RFC3339Nano) for _, match := range matches { switch match[2] { case "timeRangeStart": @@ -35,5 +49,11 @@ func interpolate(query queryModel) (string, error) { } } } - return flux, err + return flux +} + +func interpolate(query queryModel) string { + flux := interpolateFluxSpecificVariables(query) + flux = interpolateInterval(flux, query.Interval) + return flux } diff --git a/pkg/tsdb/influxdb/flux/macros_test.go b/pkg/tsdb/influxdb/flux/macros_test.go index 363c2cc41ed..9bf0fa3570a 100644 --- a/pkg/tsdb/influxdb/flux/macros_test.go +++ b/pkg/tsdb/influxdb/flux/macros_test.go @@ -7,16 +7,12 @@ import ( "github.com/google/go-cmp/cmp" "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestInterpolate(t *testing.T) { - // Unix sec: 1500376552 - // Unix ms: 1500376552001 - timeRange := backend.TimeRange{ - From: time.Unix(0, 0), - To: time.Unix(0, 0), + From: time.Unix(1632305571, 310985041), + To: time.Unix(1632309171, 310985042), } options := queryOptions{ @@ -32,8 +28,8 @@ func TestInterpolate(t *testing.T) { }{ { name: "interpolate flux variables", - before: `v.timeRangeStart, something.timeRangeStop, XYZ.bucket, uuUUu.defaultBucket, aBcDefG.organization, window.windowPeriod, a91{}.bucket`, - after: `1970-01-01T00:00:00Z, 1970-01-01T00:00:00Z, "grafana2", "grafana3", "grafana1", 1s, a91{}.bucket`, + before: `v.timeRangeStart, something.timeRangeStop, XYZ.bucket, uuUUu.defaultBucket, aBcDefG.organization, window.windowPeriod, a91{}.bucket, $__interval, $__interval_ms`, + after: `2021-09-22T10:12:51.310985041Z, 2021-09-22T11:12:51.310985042Z, "grafana2", "grafana3", "grafana1", 1m1.258s, a91{}.bucket, 1m, 61258`, }, } for _, tt := range tests { @@ -43,10 +39,9 @@ func TestInterpolate(t *testing.T) { Options: options, TimeRange: timeRange, MaxDataPoints: 1, - Interval: 1000 * 1000 * 1000, + Interval: 61258 * 1000 * 1000, } - interpolatedQuery, err := interpolate(query) - require.NoError(t, err) + interpolatedQuery := interpolate(query) diff := cmp.Diff(tt.after, interpolatedQuery) assert.Equal(t, "", diff) }) diff --git a/pkg/tsdb/interval/interval.go b/pkg/tsdb/interval/interval.go index ab271421dd0..4ee54d03ba6 100644 --- a/pkg/tsdb/interval/interval.go +++ b/pkg/tsdb/interval/interval.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" diff --git a/pkg/tsdb/mssql/macros.go b/pkg/tsdb/mssql/macros.go index e03db2be0e6..9a137ce496d 100644 --- a/pkg/tsdb/mssql/macros.go +++ b/pkg/tsdb/mssql/macros.go @@ -7,7 +7,7 @@ import ( "time" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/tsdb/sqleng" ) diff --git a/pkg/tsdb/mysql/macros.go b/pkg/tsdb/mysql/macros.go index 634cb348a70..f653e811e81 100644 --- a/pkg/tsdb/mysql/macros.go +++ b/pkg/tsdb/mysql/macros.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/tsdb/sqleng" ) diff --git a/pkg/tsdb/postgres/macros.go b/pkg/tsdb/postgres/macros.go index 9fe7479e060..c55df5da8a6 100644 --- a/pkg/tsdb/postgres/macros.go +++ b/pkg/tsdb/postgres/macros.go @@ -7,7 +7,7 @@ import ( "time" "github.com/grafana/grafana-plugin-sdk-go/backend" - "github.com/grafana/grafana/pkg/components/gtime" + "github.com/grafana/grafana-plugin-sdk-go/backend/gtime" "github.com/grafana/grafana/pkg/tsdb/sqleng" ) diff --git a/pkg/tsdb/prometheus/prometheus.go b/pkg/tsdb/prometheus/prometheus.go index dff5757e53d..013763e9cf0 100644 --- a/pkg/tsdb/prometheus/prometheus.go +++ b/pkg/tsdb/prometheus/prometheus.go @@ -74,6 +74,11 @@ func newInstanceSettings() datasource.InstanceFactoryFunc { return nil, fmt.Errorf("error getting http options: %w", err) } + // Set SigV4 service namespace + if httpCliOpts.SigV4 != nil { + httpCliOpts.SigV4.Service = "aps" + } + httpMethod, ok := jsonData["httpMethod"].(string) if !ok { httpMethod = defaultHttpMethod diff --git a/plugins-bundled/internal/input-datasource/package.json b/plugins-bundled/internal/input-datasource/package.json index 638507d9417..98028843f83 100644 --- a/plugins-bundled/internal/input-datasource/package.json +++ b/plugins-bundled/internal/input-datasource/package.json @@ -1,6 +1,6 @@ { "name": "@grafana-plugins/input-datasource", - "version": "8.2.0-pre", + "version": "8.3.0-pre", "description": "Input Datasource", "private": true, "repository": { @@ -15,9 +15,9 @@ }, "author": "Grafana Labs", "devDependencies": { - "@grafana/data": "8.2.0-pre", - "@grafana/toolkit": "8.2.0-pre", - "@grafana/ui": "8.2.0-pre" + "@grafana/data": "8.3.0-pre", + "@grafana/toolkit": "8.3.0-pre", + "@grafana/ui": "8.3.0-pre" }, "volta": { "extends": "../../../package.json" diff --git a/public/app/AppWrapper.tsx b/public/app/AppWrapper.tsx index b4a79094bba..89c1b48eab2 100644 --- a/public/app/AppWrapper.tsx +++ b/public/app/AppWrapper.tsx @@ -9,7 +9,7 @@ import { getAppRoutes } from 'app/routes/routes'; import { ConfigContext, ThemeProvider } from './core/utils/ConfigProvider'; import { RouteDescriptor } from './core/navigation/types'; import { contextSrv } from './core/services/context_srv'; -import { SideMenu } from './core/components/sidemenu/SideMenu'; +import { NavBar } from './core/components/NavBar/NavBar'; import { GrafanaRoute } from './core/navigation/GrafanaRoute'; import { AppNotificationList } from './core/components/AppNotifications/AppNotificationList'; import { SearchWrapper } from 'app/features/search'; @@ -96,7 +96,7 @@ export class AppWrapper extends React.Component
- +
{!isSignedIn && ( - + - + )} {bottomNav.map((link, index) => { let menuItems = link.children || []; @@ -75,7 +75,7 @@ export default function BottomSection() { } return ( - {link.icon && } {link.img && {`${link.text}} - + ); })} {showSwitcherModal && } diff --git a/public/app/core/components/sidemenu/DropDownChild.test.tsx b/public/app/core/components/NavBar/DropdownChild.test.tsx similarity index 81% rename from public/app/core/components/sidemenu/DropDownChild.test.tsx rename to public/app/core/components/NavBar/DropdownChild.test.tsx index 99bf45df025..1552b1a5958 100644 --- a/public/app/core/components/sidemenu/DropDownChild.test.tsx +++ b/public/app/core/components/NavBar/DropdownChild.test.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; -import DropDownChild from './DropDownChild'; +import DropdownChild from './DropdownChild'; -describe('DropDownChild', () => { +describe('DropdownChild', () => { const mockText = 'MyChildItem'; const mockUrl = '/route'; const mockIcon = 'home-alt'; it('displays the text', () => { - render(); + render(); const text = screen.getByText(mockText); expect(text).toBeInTheDocument(); }); @@ -17,7 +17,7 @@ describe('DropDownChild', () => { it('attaches the url to the text if provided', () => { render( - + ); const link = screen.getByRole('link', { name: mockText }); @@ -26,13 +26,13 @@ describe('DropDownChild', () => { }); it('displays an icon if a valid icon is provided', () => { - render(); + render(); const icon = screen.getByTestId('dropdown-child-icon'); expect(icon).toBeInTheDocument(); }); it('displays a divider instead when isDivider is true', () => { - render(); + render(); // Check the divider is shown const divider = screen.getByTestId('dropdown-child-divider'); diff --git a/public/app/core/components/sidemenu/DropDownChild.tsx b/public/app/core/components/NavBar/DropdownChild.tsx similarity index 93% rename from public/app/core/components/sidemenu/DropDownChild.tsx rename to public/app/core/components/NavBar/DropdownChild.tsx index b69f4b233fe..6badadb67d7 100644 --- a/public/app/core/components/sidemenu/DropDownChild.tsx +++ b/public/app/core/components/NavBar/DropdownChild.tsx @@ -12,7 +12,7 @@ export interface Props { url?: string; } -const DropDownChild = ({ isDivider = false, icon, onClick, target, text, url }: Props) => { +const DropdownChild = ({ isDivider = false, icon, onClick, target, text, url }: Props) => { const theme = useTheme2(); const styles = getStyles(theme); @@ -44,7 +44,7 @@ const DropDownChild = ({ isDivider = false, icon, onClick, target, text, url }: return isDivider ?
  • :
  • {element}
  • ; }; -export default DropDownChild; +export default DropdownChild; const getStyles = (theme: GrafanaTheme2) => ({ element: css` diff --git a/public/app/core/components/sidemenu/SideMenu.test.tsx b/public/app/core/components/NavBar/NavBar.test.tsx similarity index 94% rename from public/app/core/components/sidemenu/SideMenu.test.tsx rename to public/app/core/components/NavBar/NavBar.test.tsx index f0798c2c13a..751a7d2f58d 100644 --- a/public/app/core/components/sidemenu/SideMenu.test.tsx +++ b/public/app/core/components/NavBar/NavBar.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { SideMenu } from './SideMenu'; +import { NavBar } from './NavBar'; import { render, screen } from '@testing-library/react'; import { Router } from 'react-router-dom'; import { locationService } from '@grafana/runtime'; @@ -23,7 +23,7 @@ const setup = () => { return render( - + ); diff --git a/public/app/core/components/sidemenu/SideMenu.tsx b/public/app/core/components/NavBar/NavBar.tsx similarity index 94% rename from public/app/core/components/sidemenu/SideMenu.tsx rename to public/app/core/components/NavBar/NavBar.tsx index f22e7a2b91b..19296b11984 100644 --- a/public/app/core/components/sidemenu/SideMenu.tsx +++ b/public/app/core/components/NavBar/NavBar.tsx @@ -12,14 +12,14 @@ import BottomSection from './BottomSection'; const homeUrl = config.appSubUrl || '/'; -export const SideMenu: FC = React.memo(() => { +export const NavBar: FC = React.memo(() => { const theme = useTheme2(); const styles = getStyles(theme); const location = useLocation(); const query = new URLSearchParams(location.search); const kiosk = query.get('kiosk') as KioskMode; - const toggleSideMenuSmallBreakpoint = useCallback(() => { + const toggleNavBarSmallBreakpoint = useCallback(() => { appEvents.emit(CoreEvents.toggleSidemenuMobile); }, []); @@ -32,7 +32,7 @@ export const SideMenu: FC = React.memo(() => { -
    +
    @@ -45,7 +45,7 @@ export const SideMenu: FC = React.memo(() => { ); }); -SideMenu.displayName = 'SideMenu'; +NavBar.displayName = 'NavBar'; const getStyles = (theme: GrafanaTheme2) => ({ sidemenu: css` diff --git a/public/app/core/components/sidemenu/SideMenuDropDown.test.tsx b/public/app/core/components/NavBar/NavBarDropdown.test.tsx similarity index 75% rename from public/app/core/components/sidemenu/SideMenuDropDown.test.tsx rename to public/app/core/components/NavBar/NavBarDropdown.test.tsx index 287427ff9b2..8083daed70a 100644 --- a/public/app/core/components/sidemenu/SideMenuDropDown.test.tsx +++ b/public/app/core/components/NavBar/NavBarDropdown.test.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { BrowserRouter } from 'react-router-dom'; -import SideMenuDropDown from './SideMenuDropDown'; +import NavBarDropdown from './NavBarDropdown'; -describe('SideMenuDropDown', () => { +describe('NavBarDropdown', () => { const mockHeaderText = 'MyHeaderText'; const mockHeaderUrl = '/route'; const mockOnHeaderClick = jest.fn(); @@ -18,7 +18,7 @@ describe('SideMenuDropDown', () => { ]; it('displays the header text', () => { - render(); + render(); const text = screen.getByText(mockHeaderText); expect(text).toBeInTheDocument(); }); @@ -26,7 +26,7 @@ describe('SideMenuDropDown', () => { it('attaches the header url to the header text if provided', () => { render( - + ); const link = screen.getByRole('link', { name: mockHeaderText }); @@ -35,7 +35,7 @@ describe('SideMenuDropDown', () => { }); it('calls the onHeaderClick function when the header is clicked', () => { - render(); + render(); const text = screen.getByText(mockHeaderText); expect(text).toBeInTheDocument(); userEvent.click(text); @@ -43,7 +43,7 @@ describe('SideMenuDropDown', () => { }); it('displays the items', () => { - render(); + render(); mockItems.forEach(({ text }) => { const childItem = screen.getByText(text); expect(childItem).toBeInTheDocument(); diff --git a/public/app/core/components/sidemenu/SideMenuDropDown.tsx b/public/app/core/components/NavBar/NavBarDropdown.tsx similarity index 96% rename from public/app/core/components/sidemenu/SideMenuDropDown.tsx rename to public/app/core/components/NavBar/NavBarDropdown.tsx index 5f92097198a..1c2bea6b726 100644 --- a/public/app/core/components/sidemenu/SideMenuDropDown.tsx +++ b/public/app/core/components/NavBar/NavBarDropdown.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { css } from '@emotion/css'; import { GrafanaTheme2, NavModelItem } from '@grafana/data'; import { IconName, Link, useTheme2 } from '@grafana/ui'; -import DropDownChild from './DropDownChild'; +import DropdownChild from './DropdownChild'; interface Props { headerTarget?: HTMLAnchorElement['target']; @@ -14,7 +14,7 @@ interface Props { subtitleText?: string; } -const SideMenuDropDown = ({ +const NavBarDropdown = ({ headerTarget, headerText, headerUrl, @@ -50,7 +50,7 @@ const SideMenuDropDown = ({ {items .filter((item) => !item.hideFromMenu) .map((child, index) => ( - ({ header: css` diff --git a/public/app/core/components/sidemenu/SideMenuItem.test.tsx b/public/app/core/components/NavBar/NavBarItem.test.tsx similarity index 80% rename from public/app/core/components/sidemenu/SideMenuItem.test.tsx rename to public/app/core/components/NavBar/NavBarItem.test.tsx index e93f83b29b5..402b2a589f7 100644 --- a/public/app/core/components/sidemenu/SideMenuItem.test.tsx +++ b/public/app/core/components/NavBar/NavBarItem.test.tsx @@ -2,16 +2,16 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { BrowserRouter } from 'react-router-dom'; -import SideMenuItem from './SideMenuItem'; +import NavBarItem from './NavBarItem'; -describe('SideMenuItem', () => { +describe('NavBarItem', () => { it('renders the children', () => { const mockLabel = 'Hello'; render( - +
    - + ); @@ -24,9 +24,9 @@ describe('SideMenuItem', () => { const mockUrl = '/route'; render( - +
    - + ); @@ -41,9 +41,9 @@ describe('SideMenuItem', () => { const mockOnClick = jest.fn(); render( - +
    - + ); diff --git a/public/app/core/components/sidemenu/SideMenuItem.tsx b/public/app/core/components/NavBar/NavBarItem.tsx similarity index 96% rename from public/app/core/components/sidemenu/SideMenuItem.tsx rename to public/app/core/components/NavBar/NavBarItem.tsx index c3a5d21cbdd..134d67b2b61 100644 --- a/public/app/core/components/sidemenu/SideMenuItem.tsx +++ b/public/app/core/components/NavBar/NavBarItem.tsx @@ -2,7 +2,7 @@ import React, { ReactNode } from 'react'; import { css, cx } from '@emotion/css'; import { GrafanaTheme2, NavModelItem } from '@grafana/data'; import { Link, useTheme2 } from '@grafana/ui'; -import SideMenuDropDown from './SideMenuDropDown'; +import NavBarDropdown from './NavBarDropdown'; export interface Props { isActive?: boolean; @@ -16,7 +16,7 @@ export interface Props { url?: string; } -const SideMenuItem = ({ +const NavBarItem = ({ isActive = false, children, label, @@ -58,7 +58,7 @@ const SideMenuItem = ({ return (
    {element} - ({ container: css` diff --git a/public/app/core/components/sidemenu/TopSection.test.tsx b/public/app/core/components/NavBar/TopSection.test.tsx similarity index 100% rename from public/app/core/components/sidemenu/TopSection.test.tsx rename to public/app/core/components/NavBar/TopSection.test.tsx diff --git a/public/app/core/components/sidemenu/TopSection.tsx b/public/app/core/components/NavBar/TopSection.tsx similarity index 88% rename from public/app/core/components/sidemenu/TopSection.tsx rename to public/app/core/components/NavBar/TopSection.tsx index e385aa297cd..4c2b0ad2357 100644 --- a/public/app/core/components/sidemenu/TopSection.tsx +++ b/public/app/core/components/NavBar/TopSection.tsx @@ -7,7 +7,7 @@ import { locationService } from '@grafana/runtime'; import { Icon, IconName, useTheme2 } from '@grafana/ui'; import config from '../../config'; import { isLinkActive, isSearchActive } from './utils'; -import SideMenuItem from './SideMenuItem'; +import NavBarItem from './NavBarItem'; const TopSection = () => { const location = useLocation(); @@ -23,12 +23,12 @@ const TopSection = () => { return (
    - + - + {mainLinks.map((link, index) => { return ( - { > {link.icon && } {link.img && {`${link.text}} - + ); })}
    diff --git a/public/app/core/components/sidemenu/utils.test.ts b/public/app/core/components/NavBar/utils.test.ts similarity index 100% rename from public/app/core/components/sidemenu/utils.test.ts rename to public/app/core/components/NavBar/utils.test.ts diff --git a/public/app/core/components/sidemenu/utils.ts b/public/app/core/components/NavBar/utils.ts similarity index 100% rename from public/app/core/components/sidemenu/utils.ts rename to public/app/core/components/NavBar/utils.ts diff --git a/public/app/features/admin/AdminEditOrgPage.tsx b/public/app/features/admin/AdminEditOrgPage.tsx index 87b3dd13e59..8853af76cc2 100644 --- a/public/app/features/admin/AdminEditOrgPage.tsx +++ b/public/app/features/admin/AdminEditOrgPage.tsx @@ -66,7 +66,7 @@ export const AdminEditOrgPage: FC = ({ match }) => { {({ register, errors }) => ( <> - + diff --git a/public/app/features/admin/AdminOrgsTable.tsx b/public/app/features/admin/AdminOrgsTable.tsx index e1deb92ac1e..c2a92e5f0e9 100644 --- a/public/app/features/admin/AdminOrgsTable.tsx +++ b/public/app/features/admin/AdminOrgsTable.tsx @@ -28,7 +28,13 @@ export const AdminOrgsTable: FC = ({ orgs, onDelete }) => { {org.name} -