Build plugin with grafana toolkit (#1539)

* Use grafana toolkit template for building plugin

* Fix linter and type errors

* Update styles building

* Fix sass deprecation warning

* Remove empty js files produced by webpack building sass

* Fix signing script

* Replace classnames with cx

* Fix data source config page

* Use custom webpack config instead of overriding original one

* Use gpx_ prefix for plugin executable

* Remove unused configs

* Roll back react hooks dependencies usage

* Move plugin-specific ts config to root config file

* Temporary do not use rst2html for function description tooltip

* Remove unused code

* remove unused dependencies

* update react table dependency

* Migrate tests to typescript

* remove unused dependencies

* Remove old webpack configs

* Add sign target to makefile

* Add magefile

* Update CI test job

* Update go packages

* Update build instructions

* Downgrade go version to 1.18

* Fix go version in ci

* Fix metric picker

* Add comment to webpack config

* remove angular mocks

* update bra config

* Rename datasource-zabbix to datasource (fix mage build)

* Add instructions for building backend with mage

* Fix webpack targets

* Fix ci backend tests

* Add initial e2e tests

* Fix e2e ci tests

* Update docker compose for cypress tests

* build grafana docker image

* Fix docker stop task

* CI: add Grafana compatibility check
This commit is contained in:
Alexander Zobnin
2022-12-09 14:14:34 +03:00
committed by GitHub
parent 26ed740945
commit e3e896742b
136 changed files with 5765 additions and 4636 deletions

View File

@@ -1,21 +1,22 @@
# default configuration created by the `mage watch` command.
# this file can be edited and should be checked into source control.
# see https://github.com/unknwon/bra/blob/master/templates/default.bra.toml for more configuration options.
[run]
init_cmds = [
["make", "build-backend"],
["pkill", "zabbix-plugin"]
] # Commands run in start
watch_all = true # Watch all sub-directories
watch_dirs = ["pkg"] # Directories to watch
watch_exts = [".go"] # Extensions to watch
ignore = [".git", "node_modules"] # Directories to exclude from watching
ignore_files = [] # Regexps for ignoring specific notifies
build_delay = 1500 # Minimal interval to Trigger build event
interrupt_timout = 15 # Time to wait until force kill
graceful_kill = false # Wait for exit and before directly kill
["mage", "-v", "build:backend"],
["mage", "-v" , "reloadPlugin"]
]
watch_all = true
follow_symlinks = false
ignore = [".git", "node_modules", "dist"]
ignore_files = ["mage_output_file.go"]
watch_dirs = [
"pkg",
"src",
]
watch_exts = [".go", ".json"]
build_delay = 2000
cmds = [
["make", "build-backend"],
["pkill", "zabbix-plugin"]
] # Commands to run
[sync]
listen_addr = ":5050"
remote_addr = ":5050"
["mage", "-v", "build:backend"],
["mage", "-v" , "reloadPlugin"]
]

13
.config/.eslintrc Normal file
View File

@@ -0,0 +1,13 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/
{
"extends": ["@grafana/eslint-config"],
"root": true,
"ignorePatterns": ["**/*.js", "./src/test-setup/**/*.*"],
"rules": {
"react/prop-types": "off"
}
}

16
.config/.prettierrc.js Normal file
View File

@@ -0,0 +1,16 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/
module.exports = {
"endOfLine": "auto",
"printWidth": 120,
"trailingComma": "es5",
"semi": true,
"jsxSingleQuote": false,
"singleQuote": true,
"useTabs": false,
"tabWidth": 2
};

15
.config/Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
ARG grafana_version=latest
FROM grafana/grafana:${grafana_version}
# Make it as simple as possible to access the grafana instance for development purposes
# Do NOT enable these settings in a public facing / production grafana instance
ENV GF_AUTH_ANONYMOUS_ORG_ROLE "Admin"
ENV GF_AUTH_ANONYMOUS_ENABLED "true"
ENV GF_AUTH_BASIC_ENABLED "false"
# Set development mode so plugins can be loaded without the need to sign
ENV GF_DEFAULT_APP_MODE "development"
# Inject livereload script into grafana index.html
USER root
RUN sed -i 's/<\/body><\/html>/<script src=\"http:\/\/localhost:35729\/livereload.js\"><\/script><\/body><\/html>/g' /usr/share/grafana/public/views/index.html

141
.config/README.md Normal file
View File

@@ -0,0 +1,141 @@
# Default build configuration by Grafana
**This is an auto-generated directory and is not intended to be changed! ⚠️**
The `.config/` directory holds basic configuration for the different tools
that are used to develop, test and build the project. In order to make it updates easier we ask you to
not edit files in this folder to extend configuration.
## How to extend the basic configs?
Bear in mind that you are doing it at your own risk, and that extending any of the basic configuration can lead
to issues around working with the project.
### Extending the ESLint config
Edit the `.eslintrc` file in the project root in order to extend the ESLint configuration.
**Example:**
```json
{
"extends": "./.config/.eslintrc",
"rules": {
"react/prop-types": "off"
}
}
```
---
### Extending the Prettier config
Edit the `.prettierrc.js` file in the project root in order to extend the Prettier configuration.
**Example:**
```javascript
module.exports = {
// Prettier configuration provided by Grafana scaffolding
...require('./.config/.prettierrc.js'),
semi: false,
};
```
---
### Extending the Jest config
There are two configuration in the project root that belong to Jest: `jest-setup.js` and `jest.config.js`.
**`jest-setup.js`:** A file that is run before each test file in the suite is executed. We are using it to
set up the Jest DOM for the testing library and to apply some polyfills. ([link to Jest docs](https://jestjs.io/docs/configuration#setupfilesafterenv-array))
**`jest.config.js`:** The main Jest configuration file that extends the Grafana recommended setup. ([link to Jest docs](https://jestjs.io/docs/configuration))
#### ESM errors with Jest
A common issue found with the current jest config involves importing an npm package which only offers an ESM build. These packages cause jest to error with `SyntaxError: Cannot use import statement outside a module`. To work around this we provide a list of known packages to pass to the `[transformIgnorePatterns](https://jestjs.io/docs/configuration#transformignorepatterns-arraystring)` jest configuration property. If need be this can be extended in the following way:
```javascript
process.env.TZ = 'UTC';
const { grafanaESModules, nodeModulesToTransform } = require('./jest/utils');
module.exports = {
// Jest configuration provided by Grafana
...require('./.config/jest.config'),
// Inform jest to only transform specific node_module packages.
transformIgnorePatterns: [nodeModulesToTransform([...grafanaESModules, 'packageName'])],
};
```
---
### Extending the TypeScript config
Edit the `tsconfig.json` file in the project root in order to extend the TypeScript configuration.
**Example:**
```json
{
"extends": "./.config/tsconfig.json",
"compilerOptions": {
"preserveConstEnums": true
}
}
```
---
### Extending the Webpack config
Follow these steps to extend the basic Webpack configuration that lives under `.config/`:
#### 1. Create a new Webpack configuration file
Create a new config file that is going to extend the basic one provided by Grafana.
It can live in the project root, e.g. `webpack.config.ts`.
#### 2. Merge the basic config provided by Grafana and your custom setup
We are going to use [`webpack-merge`](https://github.com/survivejs/webpack-merge) for this.
```typescript
// webpack.config.ts
import type { Configuration } from 'webpack';
import { merge } from 'webpack-merge';
import grafanaConfig from './.config/webpack/webpack.config';
const config = async (env): Promise<Configuration> => {
const baseConfig = await grafanaConfig(env);
return merge(baseConfig, {
// Add custom config here...
output: {
asyncChunks: true,
},
});
};
export default config;
```
#### 3. Update the `package.json` to use the new Webpack config
We need to update the `scripts` in the `package.json` to use the extended Webpack configuration.
**Update for `build`:**
```diff
-"build": "webpack -c ./.config/webpack/webpack.config.ts --env production",
+"build": "webpack -c ./webpack.config.ts --env production",
```
**Update for `dev`:**
```diff
-"dev": "webpack -w -c ./.config/webpack/webpack.config.ts --env development",
+"dev": "webpack -w -c ./webpack.config.ts --env development",
```

24
.config/jest-setup.js Normal file
View File

@@ -0,0 +1,24 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/
import '@testing-library/jest-dom';
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
Object.defineProperty(global, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});
HTMLCanvasElement.prototype.getContext = () => {};

42
.config/jest.config.js Normal file
View File

@@ -0,0 +1,42 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/
const path = require('path');
const { grafanaESModules, nodeModulesToTransform } = require('./jest/utils');
module.exports = {
moduleNameMapper: {
'\\.(css|scss|sass)$': 'identity-obj-proxy',
'react-inlinesvg': path.resolve(__dirname, 'jest', 'mocks', 'react-inlinesvg.tsx'),
},
modulePaths: ['<rootDir>/src'],
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
testEnvironment: 'jest-environment-jsdom',
testMatch: [
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
],
transform: {
'^.+\\.(t|j)sx?$': [
'@swc/jest',
{
sourceMaps: true,
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
decorators: false,
dynamicImport: true,
},
},
},
],
},
// Jest will throw `Cannot use import statement outside module` if it tries to load an
// ES module without it being transformed first. ./config/README.md#esm-errors-with-jest
transformIgnorePatterns: [nodeModulesToTransform(grafanaESModules)],
};

View File

@@ -0,0 +1,25 @@
// Due to the grafana/ui Icon component making fetch requests to
// `/public/img/icon/<icon_name>.svg` we need to mock react-inlinesvg to prevent
// the failed fetch requests from displaying errors in console.
import React from 'react';
type Callback = (...args: any[]) => void;
export interface StorageItem {
content: string;
queue: Callback[];
status: string;
}
export const cacheStore: { [key: string]: StorageItem } = Object.create(null);
const SVG_FILE_NAME_REGEX = /(.+)\/(.+)\.svg$/;
const InlineSVG = ({ src }: { src: string }) => {
// testId will be the file name without extension (e.g. `public/img/icons/angle-double-down.svg` -> `angle-double-down`)
const testId = src.replace(SVG_FILE_NAME_REGEX, '$2');
return <svg xmlns="http://www.w3.org/2000/svg" data-testid={testId} viewBox="0 0 24 24" />;
};
export default InlineSVG;

19
.config/jest/utils.js Normal file
View File

@@ -0,0 +1,19 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/
/*
* This utility function is useful in combination with jest `transformIgnorePatterns` config
* to transform specific packages (e.g.ES modules) in a projects node_modules folder.
*/
const nodeModulesToTransform = (moduleNames) => `node_modules\/(?!(${moduleNames.join('|')})\/)`;
// Array of known nested grafana package dependencies that only bundle an ESM version
const grafanaESModules = ['ol', 'react-colorful', 'uuid'];
module.exports = {
nodeModulesToTransform,
grafanaESModules
}

25
.config/tsconfig.json Normal file
View File

@@ -0,0 +1,25 @@
/*
* THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY.
*
* In order to extend the configuration follow the steps in .config/README.md
*/
{
"compilerOptions": {
"alwaysStrict": true,
"declaration": false,
"rootDir": "../src",
"baseUrl": "../src",
"typeRoots": ["../node_modules/@types"],
"resolveJsonModule": true,
},
"ts-node": {
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"esModuleInterop": true
},
"transpileOnly": true
},
"include": ["../src", "./types", "../test-setup"],
"extends": "@grafana/tsconfig"
}

37
.config/types/custom.d.ts vendored Normal file
View File

@@ -0,0 +1,37 @@
// Image declarations
declare module '*.gif' {
const src: string;
export default src;
}
declare module '*.jpg' {
const src: string;
export default src;
}
declare module '*.jpeg' {
const src: string;
export default src;
}
declare module '*.png' {
const src: string;
export default src;
}
declare module '*.webp' {
const src: string;
export default src;
}
declare module '*.svg' {
const content: string;
export default content;
}
// Font declarations
declare module '*.woff';
declare module '*.woff2';
declare module '*.eot';
declare module '*.ttf';
declare module '*.otf';

View File

@@ -0,0 +1,2 @@
export const SOURCE_DIR = 'src';
export const DIST_DIR = 'dist';

45
.config/webpack/utils.ts Normal file
View File

@@ -0,0 +1,45 @@
import fs from 'fs';
import path from 'path';
import util from 'util';
import glob from 'glob';
import { SOURCE_DIR } from './constants';
const globAsync = util.promisify(glob);
export function getPackageJson() {
return require(path.resolve(process.cwd(), 'package.json'));
}
export function getPluginId() {
const { id } = require(path.resolve(process.cwd(), `${SOURCE_DIR}/plugin.json`));
return id;
}
export function hasReadme() {
return fs.existsSync(path.resolve(process.cwd(), SOURCE_DIR, 'README.md'));
}
export async function getEntries(): Promise<Record<string, string>> {
const parent = '..';
const pluginsJson = await globAsync('**/src/**/plugin.json');
const plugins = await Promise.all(
pluginsJson.map((pluginJson) => {
const folder = path.dirname(pluginJson);
return globAsync(`${folder}/module.{ts,tsx,js}`);
})
);
const entries = plugins.reduce((result, modules) => {
return modules.reduce((result, module) => {
const pluginPath = path.resolve(path.dirname(module), parent);
const pluginName = path.basename(pluginPath);
const entryName = plugins.length > 1 ? `${pluginName}/module` : 'module';
result[entryName] = path.join(parent, module);
return result;
}, result);
}, {});
return entries;
}

View File

@@ -0,0 +1,200 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/
import CopyWebpackPlugin from 'copy-webpack-plugin';
import ESLintPlugin from 'eslint-webpack-plugin';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import LiveReloadPlugin from 'webpack-livereload-plugin';
import path from 'path';
import ReplaceInFileWebpackPlugin from 'replace-in-file-webpack-plugin';
import { Configuration } from 'webpack';
import { getPackageJson, getPluginId, hasReadme, getEntries } from './utils';
import { SOURCE_DIR, DIST_DIR } from './constants';
const config = async (env): Promise<Configuration> => ({
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
},
context: path.join(process.cwd(), SOURCE_DIR),
devtool: env.production ? 'source-map' : 'eval-source-map',
// Entries from getEntries() work incorrect, so declare it manually in root webpack config
// entry: await getEntries(),
externals: [
'lodash',
'jquery',
'moment',
'slate',
'emotion',
'@emotion/react',
'@emotion/css',
'prismjs',
'slate-plain-serializer',
'@grafana/slate-react',
'react',
'react-dom',
'react-redux',
'redux',
'rxjs',
'react-router',
'react-router-dom',
'd3',
'angular',
'@grafana/ui',
'@grafana/runtime',
'@grafana/data',
// Mark legacy SDK imports as external if their name starts with the "grafana/" prefix
({ request }, callback) => {
const prefix = 'grafana/';
const hasPrefix = (request) => request.indexOf(prefix) === 0;
const stripPrefix = (request) => request.substr(prefix.length);
if (hasPrefix(request)) {
return callback(undefined, stripPrefix(request));
}
callback();
},
],
mode: env.production ? 'production' : 'development',
module: {
rules: [
{
exclude: /(node_modules)/,
test: /\.[tj]sx?$/,
use: {
loader: 'swc-loader',
options: {
jsc: {
baseUrl: './src',
target: 'es2015',
loose: false,
parser: {
syntax: 'typescript',
tsx: true,
decorators: false,
dynamicImport: true,
},
},
},
},
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
exclude: /(node_modules)/,
test: /\.s[ac]ss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
type: 'asset/resource',
generator: {
// Keep publicPath relative for host.com/grafana/ deployments
publicPath: `public/plugins/${getPluginId()}/img/`,
outputPath: 'img/',
filename: Boolean(env.production) ? '[hash][ext]' : '[name][ext]',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)(\?v=\d+\.\d+\.\d+)?$/,
type: 'asset/resource',
generator: {
// Keep publicPath relative for host.com/grafana/ deployments
publicPath: `public/plugins/${getPluginId()}/fonts`,
outputPath: 'fonts/',
filename: Boolean(env.production) ? '[hash][ext]' : '[name][ext]',
},
},
],
},
output: {
clean: {
keep: /gpx_.*/,
},
filename: '[name].js',
library: {
type: 'amd',
},
path: path.resolve(process.cwd(), DIST_DIR),
publicPath: '/',
},
plugins: [
new CopyWebpackPlugin({
patterns: [
// If src/README.md exists use it; otherwise the root README
// To `compiler.options.output`
{ from: hasReadme() ? 'README.md' : '../README.md', to: '.', force: true },
{ from: 'plugin.json', to: '.' },
{ from: '../LICENSE', to: '.' },
{ from: '../CHANGELOG.md', to: '.', force: true },
{ from: '**/*.json', to: '.' }, // TODO<Add an error for checking the basic structure of the repo>
{ from: '**/*.svg', to: '.', noErrorOnMissing: true }, // Optional
{ from: '**/*.png', to: '.', noErrorOnMissing: true }, // Optional
{ from: '**/*.html', to: '.', noErrorOnMissing: true }, // Optional
{ from: 'img/**/*', to: '.', noErrorOnMissing: true }, // Optional
{ from: 'libs/**/*', to: '.', noErrorOnMissing: true }, // Optional
{ from: 'static/**/*', to: '.', noErrorOnMissing: true }, // Optional
],
}),
// Replace certain template-variables in the README and plugin.json
new ReplaceInFileWebpackPlugin([
{
dir: DIST_DIR,
files: ['plugin.json', 'README.md'],
rules: [
{
search: /\%VERSION\%/g,
replace: getPackageJson().version,
},
{
search: /\%TODAY\%/g,
replace: new Date().toISOString().substring(0, 10),
},
{
search: /\%PLUGIN_ID\%/g,
replace: getPluginId(),
},
],
},
]),
new ForkTsCheckerWebpackPlugin({
async: Boolean(env.development),
issue: {
include: [{ file: '**/*.{ts,tsx}' }],
},
typescript: { configFile: path.join(process.cwd(), 'tsconfig.json') },
}),
new ESLintPlugin({
extensions: ['.ts', '.tsx'],
lintDirtyModulesOnly: Boolean(env.development), // don't lint on start, only lint changed files
}),
...(env.development ? [new LiveReloadPlugin()] : []),
],
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
// handle resolving "rootDir" paths
modules: [path.resolve(process.cwd(), 'src'), 'node_modules'],
unsafeCache: true,
},
});
export default config;

6
.eslintrc Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "./.config/.eslintrc",
"rules": {
"react-hooks/exhaustive-deps": "off"
}
}

View File

@@ -2,9 +2,13 @@ name: CI
on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main
jobs:
build:
runs-on: ubuntu-latest
@@ -17,9 +21,9 @@ jobs:
node-version: '16.x'
- name: Setup Go environment
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: '1.17'
go-version: '1.19'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
@@ -49,7 +53,11 @@ jobs:
run: yarn build
- name: Build backend
run: make build-backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v1
with:
version: latest
args: buildAll
test:
runs-on: ubuntu-latest
@@ -62,9 +70,9 @@ jobs:
node-version: '16.x'
- name: Setup Go environment
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: '1.17'
go-version: '1.19'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
@@ -90,10 +98,52 @@ jobs:
run: yarn install --frozen-lockfile
- name: Test backend
run: make test-backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v1
with:
version: latest
args: coverage
- name: Test frontend
run: yarn test
run: yarn test:ci
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable --prefer-offline
- name: Build frontend
run: yarn build
- name: Setup Go environment
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: actions/setup-go@v3
with:
go-version: '1.19'
- name: Build backend
if: steps.check-for-backend.outputs.has-backend == 'true'
uses: magefile/mage-action@v1
with:
version: latest
args: buildAll
- name: Start grafana docker
run: yarn server -d
- name: Run e2e tests
run: yarn e2e
- name: Stop grafana docker
run: yarn server:stop
lint:
runs-on: ubuntu-latest
@@ -108,7 +158,7 @@ jobs:
- name: Setup Go environment
uses: actions/setup-go@v2
with:
go-version: '1.17'
go-version: '1.19'
- name: Get yarn cache directory path
id: yarn-cache-dir-path

18
.github/workflows/is-compatible.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Latest Grafana API compatibility check
on: [pull_request]
jobs:
compatibilitycheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable --prefer-offline
- name: Build plugin
run: yarn build
- name: Compatibility check
run: npx @grafana/levitate@latest is-compatible --path src/module.ts --target @grafana/data,@grafana/ui,@grafana/runtime

8
.gitignore vendored
View File

@@ -25,6 +25,12 @@ node_modules
coverage/
/tmp
artifacts/
work/
e2e-results/
**/cypress/videos
**/cypress/report.json
# Tools logs
npm-debug.log
yarn-error.log
@@ -34,7 +40,7 @@ dist/
ci/
# Grafana toolkit configs
.prettierrc.js
# .prettierrc.js
# locally required config files
public/css/*.min.css

View File

@@ -1,13 +0,0 @@
{
"disallowImplicitTypeConversion": ["string"],
"disallowKeywords": ["with"],
"disallowMultipleLineBreaks": true,
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"disallowSpacesInsideArrayBrackets": true,
"disallowSpacesInsideParentheses": true,
"validateIndentation": 2
}

View File

@@ -1,49 +0,0 @@
{
"browser": true,
"bitwise":false,
"curly": true,
"eqnull": true,
"strict": true,
"module": true,
"devel": true,
"eqeqeq": true,
"forin": false,
"immed": true,
"supernew": true,
"expr": true,
"indent": 2,
"latedef": false,
"newcap": true,
"noarg": true,
"noempty": true,
"undef": true,
"boss": true,
"trailing": true,
"laxbreak": true,
"laxcomma": true,
"sub": true,
"unused": true,
"maxdepth": 6,
"maxlen": 140,
"esversion": 8,
"globals": {
"System": true,
"Promise": true,
"define": true,
"require": true,
"Chromath": false,
"setImmediate": true,
"jest": true,
"expect": true,
"it": true,
"describe": true,
"sinon": true,
"module": true,
"beforeEach": true,
"inject": true,
"__dirname": true,
"process": true
}
}

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
16

4
.prettierrc.js Normal file
View File

@@ -0,0 +1,4 @@
module.exports = {
// Prettier configuration provided by Grafana scaffolding
...require("./.config/.prettierrc.js")
};

View File

@@ -1,6 +1,23 @@
# Plugin development
### Debugging backend plugin
## Building plugin
```sh
# install frontend deps
yarn install --pure-lockfile
# build frontend
yarn build
#build backend for current platform
mage -v build:backend
```
## Rebuild backend on changes
```sh
mage watch
```
## Debugging backend plugin
For debugging backend part written on Go, you should go through a few steps. First, build a plugin with special flags for debugging:

12
Magefile.go Normal file
View File

@@ -0,0 +1,12 @@
//go:build mage
// +build mage
package main
import (
// mage:import
build "github.com/grafana/grafana-plugin-sdk-go/build"
)
// Default configures the default target.
var Default = build.BuildAll

View File

@@ -13,19 +13,19 @@ deps-go:
build: build-frontend build-backend
build-frontend:
yarn dev-build
yarn build
build-backend:
env GOOS=linux go build -o ./dist/zabbix-plugin_linux_amd64 ./pkg
mage -v build:backend
build-debug:
env GOOS=linux go build -gcflags="all=-N -l" -o ./dist/zabbix-plugin_linux_amd64 ./pkg
env GOOS=linux go build -gcflags="all=-N -l" -o ./dist/gpx_zabbix-plugin_linux_amd64 ./pkg
# Build for specific platform
build-backend-windows: extension = .exe
build-backend-%-arm64:
$(eval filename = zabbix-plugin_$*_arm64$(extension))
$(eval filename = gpx_zabbix-plugin_$*_arm64$(extension))
env GOOS=$* GOARCH=arm64 go build -o ./dist/$(filename) ./pkg
build-backend-%:
$(eval filename = zabbix-plugin_$*_amd64$(extension))
$(eval filename = gpx_zabbix-plugin_$*_amd64$(extension))
env GOOS=$* GOARCH=amd64 go build -o ./dist/$(filename) ./pkg
run-frontend:
@@ -45,17 +45,17 @@ dist-frontend:
dist-backend: dist-backend-linux dist-backend-darwin dist-backend-freebsd dist-backend-windows dist-arm
dist-backend-windows: extension = .exe
dist-backend-%:
$(eval filename = zabbix-plugin_$*_amd64$(extension))
$(eval filename = gpx_zabbix-plugin_$*_amd64$(extension))
env GOOS=$* GOARCH=amd64 go build -ldflags="-s -w" -o ./dist/$(filename) ./pkg
# ARM
dist-arm: dist-arm-linux-arm-v6 dist-arm-linux-arm64 dist-arm-darwin-arm64 dist-arm-freebsd-arm64
dist-arm-linux-arm-v6:
env GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o ./dist/zabbix-plugin_linux_arm ./pkg
env GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o ./dist/gpx_zabbix-plugin_linux_arm ./pkg
dist-arm-linux-arm-v7:
env GOOS=linux GOARCH=arm GOARM=7 go build -ldflags="-s -w" -o ./dist/zabbix-plugin_linux_arm ./pkg
env GOOS=linux GOARCH=arm GOARM=7 go build -ldflags="-s -w" -o ./dist/gpx_zabbix-plugin_linux_arm ./pkg
dist-arm-%-arm64:
$(eval filename = zabbix-plugin_$*_arm64$(extension))
$(eval filename = gpx_zabbix-plugin_$*_arm64$(extension))
env GOOS=$* GOARCH=arm64 go build -ldflags="-s -w" -o ./dist/$(filename) ./pkg
.PHONY: test
@@ -77,3 +77,8 @@ clean:
lint:
yarn lint
golint -min_confidence=1.1 -set_exit_status pkg/...
sign-package:
yarn sign
package: install dist sign-package

View File

@@ -1,7 +0,0 @@
module.exports = {
"presets": [
[ "@babel/preset-env", { "targets": { "node": "current" } } ],
"@babel/react"
],
"retainLines": true
};

View File

@@ -0,0 +1,10 @@
import { e2e } from '@grafana/e2e';
e2e.scenario({
describeName: 'Smoke test',
itName: 'Smoke test',
scenario: () => {
e2e.pages.Home.visit();
e2e().contains('Welcome to Grafana').should('be.visible');
},
});

View File

@@ -5,7 +5,7 @@ if [ "$1" == "-h" ]; then
fi
PORT="${2:-3222}"
PLUGIN_NAME="${1:-zabbix-plugin_}"
PLUGIN_NAME="${1:-gpx_zabbix-plugin_}"
# Build optimized for debug
make build-debug

15
devenv/default/Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
ARG grafana_version=latest
FROM grafana/grafana:${grafana_version}
# Make it as simple as possible to access the grafana instance for development purposes
# Do NOT enable these settings in a public facing / production grafana instance
ENV GF_AUTH_ANONYMOUS_ORG_ROLE "Admin"
ENV GF_AUTH_ANONYMOUS_ENABLED "true"
ENV GF_AUTH_BASIC_ENABLED "false"
# Set development mode so plugins can be loaded without the need to sign
ENV GF_DEFAULT_APP_MODE "development"
# Inject livereload script into grafana index.html
USER root
RUN sed -i 's/<\/body><\/html>/<script src=\"http:\/\/localhost:35729\/livereload.js\"><\/script><\/body><\/html>/g' /usr/share/grafana/public/views/index.html

View File

@@ -0,0 +1,17 @@
FROM python:2.7
ENV ZBX_API_URL=http://zabbix-web:8080
ENV ZBX_API_USER="Admin"
ENV ZBX_API_PASSWORD="zabbix"
ENV ZBX_CONFIG="zbx_export_hosts.xml"
ENV ZBX_BOOTSTRAP_SCRIPT="bootstrap_config.py"
RUN pip install pyzabbix
ADD ./bootstrap_config.py /bootstrap_config.py
ADD ${ZBX_CONFIG} /${ZBX_CONFIG}
WORKDIR /
# Run bootstrap_config.py when the container launches
CMD ["python", "/bootstrap_config.py"]

View File

@@ -0,0 +1,80 @@
import os
from time import sleep
from pyzabbix import ZabbixAPI, ZabbixAPIException
zabbix_url = os.environ['ZBX_API_URL']
zabbix_user = os.environ['ZBX_API_USER']
zabbix_password = os.environ['ZBX_API_PASSWORD']
print(zabbix_url, zabbix_user, zabbix_password)
zapi = ZabbixAPI(zabbix_url, timeout=5)
for i in range(10):
print("Trying to connected to Zabbix API %s" % zabbix_url)
try:
zapi.login(zabbix_user, zabbix_password)
print("Connected to Zabbix API Version %s" % zapi.api_version())
break
except ZabbixAPIException as e:
print e
sleep(5)
except:
print("Waiting")
sleep(5)
config_path = os.environ['ZBX_CONFIG']
import_rules = {
'discoveryRules': {
'createMissing': True,
'updateExisting': True
},
'graphs': {
'createMissing': True,
'updateExisting': True
},
'groups': {
'createMissing': True
},
'hosts': {
'createMissing': True,
'updateExisting': True
},
'images': {
'createMissing': True,
'updateExisting': True
},
'items': {
'createMissing': True,
'updateExisting': True
},
'maps': {
'createMissing': True,
'updateExisting': True
},
'templateLinkage': {
'createMissing': True,
},
'templates': {
'createMissing': True,
'updateExisting': True
},
'triggers': {
'createMissing': True,
'updateExisting': True
},
}
print("Importing Zabbix config from %s" % config_path)
with open(config_path, 'r') as f:
config = f.read()
try:
# https://github.com/lukecyca/pyzabbix/issues/62
import_result = zapi.confimport("xml", config, import_rules)
print(import_result)
except ZabbixAPIException as e:
print e
for h in zapi.host.get(output="extend"):
print(h['name'])

View File

@@ -0,0 +1,432 @@
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
<version>6.0</version>
<date>2022-04-28T13:04:18Z</date>
<groups>
<group>
<uuid>2e427c268ac1468b9add94b65e2d6c14</uuid>
<name>Backend</name>
</group>
<group>
<uuid>d97ba66b283544339628b71975a6e68d</uuid>
<name>Frontend</name>
</group>
<group>
<uuid>dc579cd7a1a34222933f24f52a68bcd8</uuid>
<name>Linux servers</name>
</group>
<group>
<uuid>6f6799aa69e844b4b3918f779f2abf08</uuid>
<name>Zabbix servers</name>
</group>
<group>
<uuid>7df96b18c230490a9a0a9e2307226338</uuid>
<name>Templates</name>
</group>
</groups>
<hosts>
<host>
<host>backend01</host>
<name>backend01</name>
<templates>
<template>
<name>Template ZAS Agent</name>
</template>
</templates>
<groups>
<group>
<name>Backend</name>
</group>
<group>
<name>Linux servers</name>
</group>
</groups>
<interfaces>
<interface>
<useip>NO</useip>
<dns>zas_backend_01</dns>
<interface_ref>if1</interface_ref>
</interface>
</interfaces>
<tags>
<tag>
<tag>backend</tag>
</tag>
<tag>
<tag>service</tag>
<value>backend</value>
</tag>
</tags>
<inventory_mode>DISABLED</inventory_mode>
</host>
<host>
<host>backend02</host>
<name>backend02</name>
<templates>
<template>
<name>Template ZAS Agent</name>
</template>
</templates>
<groups>
<group>
<name>Backend</name>
</group>
<group>
<name>Linux servers</name>
</group>
</groups>
<interfaces>
<interface>
<useip>NO</useip>
<dns>zas_backend_02</dns>
<interface_ref>if1</interface_ref>
</interface>
</interfaces>
<tags>
<tag>
<tag>backend</tag>
</tag>
<tag>
<tag>service</tag>
<value>backend</value>
</tag>
</tags>
<inventory_mode>DISABLED</inventory_mode>
</host>
<host>
<host>frontend01</host>
<name>frontend01</name>
<templates>
<template>
<name>Template ZAS Agent</name>
</template>
</templates>
<groups>
<group>
<name>Frontend</name>
</group>
<group>
<name>Linux servers</name>
</group>
</groups>
<interfaces>
<interface>
<useip>NO</useip>
<dns>zas_frontend_01</dns>
<interface_ref>if1</interface_ref>
</interface>
</interfaces>
<tags>
<tag>
<tag>frontend</tag>
</tag>
<tag>
<tag>service</tag>
<value>frontend</value>
</tag>
</tags>
<inventory_mode>DISABLED</inventory_mode>
</host>
<host>
<host>frontend02</host>
<name>frontend02</name>
<templates>
<template>
<name>Template ZAS Agent</name>
</template>
</templates>
<groups>
<group>
<name>Frontend</name>
</group>
<group>
<name>Linux servers</name>
</group>
</groups>
<interfaces>
<interface>
<useip>NO</useip>
<dns>zas_frontend_02</dns>
<interface_ref>if1</interface_ref>
</interface>
</interfaces>
<tags>
<tag>
<tag>frontend</tag>
</tag>
<tag>
<tag>service</tag>
<value>frontend</value>
</tag>
</tags>
<inventory_mode>DISABLED</inventory_mode>
</host>
<host>
<host>Zabbix server</host>
<name>Zabbix server</name>
<templates>
<template>
<name>Linux by Zabbix agent</name>
</template>
<template>
<name>Zabbix server health</name>
</template>
</templates>
<groups>
<group>
<name>Zabbix servers</name>
</group>
</groups>
<interfaces>
<interface>
<useip>NO</useip>
<dns>zabbix-agent</dns>
<interface_ref>if1</interface_ref>
</interface>
</interfaces>
<inventory_mode>DISABLED</inventory_mode>
</host>
</hosts>
<templates>
<template>
<uuid>2d7a65bb369c48199361913b223b1695</uuid>
<template>Template ZAS Agent</template>
<name>Template ZAS Agent</name>
<templates>
<template>
<name>Zabbix agent</name>
</template>
</templates>
<groups>
<group>
<name>Templates</name>
</group>
</groups>
<items>
<item>
<uuid>e79d4215ec014b74923b905bb8f82410</uuid>
<name>Incoming network traffic on eth0</name>
<key>net.if.in[eth0]</key>
<history>1d</history>
<units>bps</units>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>Network interfaces</value>
</tag>
</tags>
</item>
<item>
<uuid>18b377dae9fe48d093c16ee7a7c93320</uuid>
<name>Outgoing network traffic on eth0</name>
<key>net.if.out[eth0]</key>
<history>1d</history>
<units>bps</units>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>Network interfaces</value>
</tag>
</tags>
</item>
<item>
<uuid>2479e055e91c476f9be93b5f363cfa2f</uuid>
<name>Processor load (1 min average per core)</name>
<key>system.cpu.load[percpu,avg1]</key>
<history>1d</history>
<value_type>FLOAT</value_type>
<description>The processor load is calculated as system CPU load divided by number of CPU cores.</description>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>CPU</value>
</tag>
<tag>
<tag>Application</tag>
<value>Performance</value>
</tag>
</tags>
<triggers>
<trigger>
<uuid>60e5484b60ca4061b21bd23f8364bd6e</uuid>
<expression>last(/Template ZAS Agent/system.cpu.load[percpu,avg1])&gt;2</expression>
<name>Processor load is too high on {HOST.NAME}</name>
<priority>WARNING</priority>
<tags>
<tag>
<tag>app</tag>
<value>performance</value>
</tag>
<tag>
<tag>type</tag>
<value>cpu</value>
</tag>
</tags>
</trigger>
</triggers>
</item>
<item>
<uuid>f0dd4221793c49889cf2789806afa597</uuid>
<name>Processor load (15 min average per core)</name>
<key>system.cpu.load[percpu,avg15]</key>
<history>1d</history>
<value_type>FLOAT</value_type>
<description>The processor load is calculated as system CPU load divided by number of CPU cores.</description>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>CPU</value>
</tag>
<tag>
<tag>Application</tag>
<value>Performance</value>
</tag>
</tags>
</item>
<item>
<uuid>9a8b4a1f173b4f209723d820dc2e054a</uuid>
<name>CPU $2 time</name>
<key>system.cpu.util[,iowait]</key>
<history>1d</history>
<value_type>FLOAT</value_type>
<units>%</units>
<description>Amount of time the CPU has been waiting for I/O to complete.</description>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>CPU</value>
</tag>
<tag>
<tag>Application</tag>
<value>Performance</value>
</tag>
</tags>
<triggers>
<trigger>
<uuid>ceb468b9eb434fa6bd4c8a5d7507fd87</uuid>
<expression>avg(/Template ZAS Agent/system.cpu.util[,iowait],5m)&gt;20</expression>
<name>Disk I/O is overloaded on {HOST.NAME}</name>
<priority>WARNING</priority>
<description>OS spends significant time waiting for I/O (input/output) operations. It could be indicator of performance issues with storage system.</description>
<tags>
<tag>
<tag>disk</tag>
</tag>
<tag>
<tag>type</tag>
<value>disk</value>
</tag>
</tags>
</trigger>
</triggers>
</item>
<item>
<uuid>e6d19d47cf60452ead1e791da2d5c0dc</uuid>
<name>CPU $2 time</name>
<key>system.cpu.util[,system]</key>
<history>1d</history>
<value_type>FLOAT</value_type>
<units>%</units>
<description>The time the CPU has spent running the kernel and its processes.</description>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>CPU</value>
</tag>
<tag>
<tag>Application</tag>
<value>Performance</value>
</tag>
</tags>
</item>
<item>
<uuid>2d81fbc139774306959712a627c99b9a</uuid>
<name>CPU $2 time</name>
<key>system.cpu.util[,user]</key>
<history>1d</history>
<value_type>FLOAT</value_type>
<units>%</units>
<description>The time the CPU has spent running users' processes that are not niced.</description>
<request_method>POST</request_method>
<tags>
<tag>
<tag>Application</tag>
<value>CPU</value>
</tag>
<tag>
<tag>Application</tag>
<value>Performance</value>
</tag>
</tags>
</item>
</items>
</template>
</templates>
<graphs>
<graph>
<uuid>7aac0ec0c0e04b7a8bb6472d1faa7a09</uuid>
<name>CPU load</name>
<ymin_type_1>FIXED</ymin_type_1>
<graph_items>
<graph_item>
<color>009900</color>
<item>
<host>Template ZAS Agent</host>
<key>system.cpu.load[percpu,avg1]</key>
</item>
</graph_item>
<graph_item>
<sortorder>2</sortorder>
<color>990000</color>
<item>
<host>Template ZAS Agent</host>
<key>system.cpu.load[percpu,avg15]</key>
</item>
</graph_item>
</graph_items>
</graph>
<graph>
<uuid>f25064d88b964a678fac7ea6095b238a</uuid>
<name>CPU utilization</name>
<show_triggers>NO</show_triggers>
<type>STACKED</type>
<ymin_type_1>FIXED</ymin_type_1>
<ymax_type_1>FIXED</ymax_type_1>
<graph_items>
<graph_item>
<sortorder>4</sortorder>
<drawtype>FILLED_REGION</drawtype>
<color>999900</color>
<item>
<host>Template ZAS Agent</host>
<key>system.cpu.util[,iowait]</key>
</item>
</graph_item>
<graph_item>
<sortorder>5</sortorder>
<drawtype>FILLED_REGION</drawtype>
<color>990000</color>
<item>
<host>Template ZAS Agent</host>
<key>system.cpu.util[,system]</key>
</item>
</graph_item>
<graph_item>
<sortorder>6</sortorder>
<drawtype>FILLED_REGION</drawtype>
<color>000099</color>
<item>
<host>Template ZAS Agent</host>
<key>system.cpu.util[,user]</key>
</item>
</graph_item>
</graph_items>
</graph>
</graphs>
</zabbix_export>

View File

@@ -0,0 +1,123 @@
version: "3"
services:
# Grafana
grafana:
container_name: 'alexanderzobnin-boilerplate-app'
build:
context: ./
args:
grafana_version: ${GRAFANA_VERSION:-9.2.5}
ports:
- 3000:3000/tcp
volumes:
- ../../dist:/grafana-zabbix
- ../dashboards:/devenv/dashboards
- ../grafana.ini:/etc/grafana/grafana.ini:ro
- "../datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml"
- "../dashboards.yaml:/etc/grafana/provisioning/dashboards/dashboards.yaml"
# Zabbix
zabbix-server:
image: zabbix/zabbix-server-pgsql:alpine-6.0-latest
ports:
- "10051:10051"
depends_on:
- database
environment:
DB_SERVER_HOST: database
DB_SERVER_PORT: 5432
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: zabbix
POSTGRES_DB: zabbix
ZBX_TIMEOUT: 10
ZBX_STARTPOLLERS: 10
ZBX_STARTPOLLERSUNREACHABLE: 5
ZBX_DEBUGLEVEL: 3
zabbix-web:
image: zabbix/zabbix-web-apache-pgsql:alpine-6.0-latest
ports:
- "8188:8080"
depends_on:
- database
- zabbix-server
environment:
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_PORT: 10051
DB_SERVER_HOST: database
DB_SERVER_PORT: 5432
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: zabbix
POSTGRES_DB: zabbix
database:
image: postgres
ports:
- "15432:5432"
command: postgres -c 'max_connections=1000'
environment:
POSTGRES_USER: zabbix
POSTGRES_PASSWORD: zabbix
zabbix-agent:
image: zabbix/zabbix-agent:alpine-6.0-latest
environment:
ZBX_SERVER_HOST: zabbix-server
ZBX_SERVER_PORT: 10051
#########################################################
# Bootstrap config
#########################################################
bootstrap:
build: ./bootstrap
environment:
ZBX_API_URL: http://zabbix-web:8080
ZBX_API_USER: Admin
ZBX_API_PASSWORD: zabbix
depends_on:
- database
- zabbix-server
- zabbix-web
#########################################################
# Fake agents
#########################################################
# backend
redis_backend:
image: redis:alpine
zas_backend_01:
build: ../zas-agent
volumes:
- ../zas-agent/conf/zas_scenario_backend.cfg:/etc/zas_scenario.cfg
environment:
REDIS_HOST: redis_backend
# restart: always
zas_backend_02:
build: ../zas-agent
volumes:
- ../zas-agent/conf/zas_scenario_backend.cfg:/etc/zas_scenario.cfg
environment:
REDIS_HOST: redis_backend
# frontend
redis_frontend:
image: redis:alpine
zas_frontend_01:
build: ../zas-agent
volumes:
- ../zas-agent/conf/zas_scenario_frontend.cfg:/etc/zas_scenario.cfg
environment:
REDIS_HOST: redis_frontend
zas_frontend_02:
build: ../zas-agent
volumes:
- ../zas-agent/conf/zas_scenario_frontend.cfg:/etc/zas_scenario.cfg
environment:
REDIS_HOST: redis_frontend

78
go.mod
View File

@@ -1,16 +1,80 @@
module github.com/alexanderzobnin/grafana-zabbix
go 1.15
go 1.19
require github.com/grafana/grafana-plugin-sdk-go v0.145.0
require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/getkin/kin-openapi v0.94.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/flatbuffers v22.11.23+incompatible // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/hashicorp/go-plugin v1.4.8 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.12 // indirect
github.com/magefile/mage v1.13.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattetti/filebuffer v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.38.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 // indirect
github.com/unknwon/com v1.0.1 // indirect
github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3 // indirect
github.com/urfave/cli v1.22.1 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 // indirect
google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (
github.com/bitly/go-simplejson v0.5.0
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/dlclark/regexp2 v1.4.0
github.com/grafana/grafana-plugin-sdk-go v0.133.0
github.com/hashicorp/go-hclog v0.16.1 // indirect
github.com/dlclark/regexp2 v1.7.0
github.com/hashicorp/go-hclog v1.4.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/prometheus/client_golang v1.12.1
github.com/stretchr/testify v1.7.0
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
github.com/prometheus/client_golang v1.14.0
github.com/stretchr/testify v1.8.1
golang.org/x/net v0.4.0
gotest.tools v2.2.0+incompatible
)

487
go.sum
View File

@@ -1,50 +1,14 @@
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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
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=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 h1:q4dksr6ICHXqG5hm0ZW5IHyeEJXoIJSOZeBLmWPNeIQ=
github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs=
github.com/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=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
@@ -53,81 +17,67 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4Yn
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
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/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
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-20220208224320-6efb837e6bc2 h1:XCdvHbz3LhewBHN7+mQPx0sg/Hxil/1USnBmxkjHcmY=
github.com/chromedp/cdproto v0.0.0-20220208224320-6efb837e6bc2/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
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/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac h1:XDAn206aIqKPdF5YczuuJXSQPx+WOen0Pxbxp5Fq8Pg=
github.com/elazarl/goproxy v0.0.0-20220115173737-adb46da277ac/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20220115173737-adb46da277ac/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20220115173737-adb46da277ac h1:9yrT5tmn9Zc0ytWPASlaPwQfQMQYnRf0RSDe1XvHw0Q=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
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.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
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/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/getkin/kin-openapi v0.94.0 h1:bAxg2vxgnHHHoeefVdmGbR+oxtJlcv5HsJJa3qmAHuo=
github.com/getkin/kin-openapi v0.94.0/go.mod h1:LWZfzOd7PRy8GJ1dJ6mCU6tNdSfOwRac1BUPam4aw6Q=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY=
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-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/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
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/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -140,79 +90,55 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
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/flatbuffers v22.11.23+incompatible h1:334TygA7iuxt0hoamawsM36xoui01YiouEZnr0qeFMI=
github.com/google/flatbuffers v22.11.23+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=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/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/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grafana/grafana-plugin-sdk-go v0.133.0 h1:0PnrJmEUX+6Cxg8tDYNwJmg7331KmRGrej9ki36i9zw=
github.com/grafana/grafana-plugin-sdk-go v0.133.0/go.mod h1:jmrxelOJKrIK0yrsIzcotS8pbqPZozbmJgGy7k3hK1k=
github.com/grafana/grafana-plugin-sdk-go v0.145.0 h1:ZlRxxV3C6RA+wNWeGr+rLVD70pgsZwiLI9etzE0zu+Q=
github.com/grafana/grafana-plugin-sdk-go v0.145.0/go.mod h1:dFof/7GenWBFTmrfcPRCpLau7tgIED0ykzupWAlB0o0=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o=
github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I=
github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM=
github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
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/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ=
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -220,40 +146,39 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magefile/mage v1.12.1/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magefile/mage v1.13.0 h1:XtLJl8bcCM7EFoO8FyH8XK3t7G5hQAeK+i4tq+veT9M=
github.com/magefile/mage v1.13.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=
github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
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/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
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=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
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/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
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=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
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/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
@@ -261,70 +186,70 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4=
github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
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=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/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.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.38.0 h1:VTQitp6mXTdUoCmDMugDVOJ1opi6ADftKfp/yeqTR/E=
github.com/prometheus/common v0.38.0/go.mod h1:MBXfmBQZrK5XpbCkjofnXs96LD2QQ7fEq4C0xjC/yec=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
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.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 h1:aVGB3YnaS/JNfOW3tiHIlmNmTDg618va+eT0mVomgyI=
github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8/go.mod h1:fVle4kNr08ydeohzYafr20oZzbAkhQT39gKK/pFQ5M4=
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/unknwon/log v0.0.0-20150304194804-e617c87089d3 h1:4EYQaWAatQokdji3zqZloVIW/Ke1RQjYw2zHULyrHJg=
github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3/go.mod h1:1xEUf2abjfP92w2GZTV+GgaRxXErwRXcClbUwrNJffU=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -332,16 +257,8 @@ golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3 h1:n9HxLrNxWWtEb1cA950nuEEj3QnKbtsCJ6KjcgisNUs=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -353,265 +270,112 @@ golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+o
golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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-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=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/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=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/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-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/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-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/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-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/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-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=
gonum.org/v1/gonum v0.9.3 h1:DnoIG+QAMaF5NvxnGe/oKsgKcAc6PcUyl8q0VetfQ8s=
gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
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.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
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-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/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=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79 h1:s1jFTXJryg4a1mew7xv03VZD8N9XjxFhk1o4Js4WvPQ=
google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37 h1:jmIfw8+gSvXcZSgaFAGyInDXeWzUhvYH57G/5GKMn70=
google.golang.org/genproto v0.0.0-20221207170731-23e4bf6bdc37/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -620,40 +384,29 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.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=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
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=

3
jest-setup.js Normal file
View File

@@ -0,0 +1,3 @@
// Jest setup provided by Grafana scaffolding
import './.config/jest-setup';
import './src/test-setup/jest-setup';

View File

@@ -1,33 +1,8 @@
// force timezone to UTC to allow tests to work regardless of local timezone
// generally used by snapshots, but can affect specific tests
process.env.TZ = 'UTC';
module.exports = {
"roots": [
// "<rootDir>/dist/test"
"<rootDir>/src"
],
"setupFiles": [
// "<rootDir>/dist/test/test-setup/jest-setup.js"
"<rootDir>/src/test-setup/jest-setup.js"
],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json"
],
"moduleNameMapper": {
"^[./a-zA-Z0-9$_-]+\.css\!?$": "<rootDir>/src/test-setup/cssStub.js",
},
"testRegex": "(\\.|/)(test|spec)\\.(jsx?|tsx?)$",
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.(ts|tsx)$": "ts-jest"
},
"coverageDirectory": "<rootDir>/tmp/coverage/node/",
"collectCoverage": false,
"testEnvironment": "jest-environment-jsdom-fifteen",
"globals": {
"ts-jest": {
"tsConfig": "tsconfig.test.json"
}
}
// Jest configuration provided by Grafana scaffolding
...require('./.config/jest.config'),
};

View File

@@ -5,15 +5,19 @@
"description": "Zabbix plugin for Grafana",
"homepage": "http://grafana-zabbix.org",
"scripts": {
"build": "webpack --config webpack/webpack.prod.conf.js --progress --colors",
"dev": "webpack --config webpack/webpack.dev.conf.js --watch --progress --colors",
"dev-build": "webpack --config webpack/webpack.dev.conf.js",
"watch": "webpack --config webpack/webpack.dev.conf.js --watch --progress --colors",
"test": "jest",
"jest": "jest --notify --watch",
"codecov": "jest --coverage && codecov",
"ci-test": "jest --coverage",
"lint": "jshint --reporter=node_modules/jshint-stylish src/ & jscs src/"
"build": "webpack -c ./webpack.config.ts --env production",
"dev": "webpack -w -c ./webpack.config.ts --env development",
"test": "jest --watch --onlyChanged",
"test:ci": "jest --maxWorkers 4",
"typecheck": "tsc --noEmit",
"lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx .",
"lint:fix": "yarn lint --fix",
"e2e": "yarn cypress install && yarn grafana-e2e run",
"e2e:update": "yarn cypress install && yarn grafana-e2e run --update-screenshots",
"server": "docker-compose --file ./devenv/default/docker-compose.yml up --build",
"server:stop": "docker-compose --file ./devenv/default/docker-compose.yml stop",
"server:down": "docker-compose --file ./devenv/default/docker-compose.yml down",
"sign": "grafana-toolkit plugin:sign"
},
"repository": {
"type": "git",
@@ -25,39 +29,56 @@
"url": "https://github.com/alexanderzobnin/grafana-zabbix/issues"
},
"devDependencies": {
"@babel/core": "7.7.7",
"@babel/preset-env": "7.7.7",
"@babel/preset-react": "7.6.3",
"@emotion/css": "11.1.3",
"@emotion/react": "11.1.5",
"@grafana/data": "9.1.2",
"@grafana/e2e": "9.2.5",
"@grafana/e2e-selectors": "9.2.5",
"@grafana/eslint-config": "^5.1.0",
"@grafana/runtime": "9.1.2",
"@grafana/toolkit": "9.1.2",
"@grafana/tsconfig": "^1.2.0-rc1",
"@grafana/ui": "9.1.2",
"@popperjs/core": "2.4.0",
"@swc/core": "^1.2.144",
"@swc/helpers": "^0.4.12",
"@swc/jest": "^0.2.23",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@types/classnames": "2.2.9",
"@types/glob": "^8.0.0",
"@types/grafana": "github:CorpGlory/types-grafana",
"@types/jest": "24.0.13",
"@types/jest": "^29.2.2",
"@types/jquery": "3.3.32",
"@types/lodash": "4.14.161",
"@types/lodash": "^4.14.188",
"@types/node": "^18.11.9",
"@types/react": "17.0.42",
"@types/react-dom": "17.0.14",
"@types/react-router-dom": "^5.3.3",
"@types/react-transition-group": "4.2.4",
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"autoprefixer": "10.4.7",
"axios": "^0.21.1",
"babel-jest": "24.8.0",
"babel-loader": "8.0.6",
"babel-plugin-angularjs-annotate": "0.10.0",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
"benchmark": "^2.1.4",
"classnames": "2.2.6",
"clean-webpack-plugin": "^0.1.19",
"codecov": "^3.1.0",
"copy-webpack-plugin": "^5.1.1",
"css-loader": "3.4.2",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"eslint": "8.26.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^39.6.2",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-webpack-plugin": "^3.1.1",
"fork-ts-checker-webpack-plugin": "^7.2.0",
"glob": "^8.0.3",
"html-loader": "0.5.5",
"jest": "24.8.0",
"identity-obj-proxy": "3.0.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"jest-environment-jsdom-fifteen": "^1.0.2",
"jscs": "^3.0.7",
"jsdom": "~11.3.0",
@@ -65,29 +86,43 @@
"jshint-stylish": "^2.1.0",
"lodash": "4.17.21",
"memoize-one": "5.1.1",
"mini-css-extract-plugin": "2.6.1",
"moment": "2.24.0",
"ng-annotate-webpack-plugin": "0.3.0",
"node-sass": "^7.0.1",
"postcss": "8.4.14",
"postcss-loader": "7.0.1",
"postcss-reporter": "7.0.5",
"postcss-scss": "4.0.4",
"prettier": "^2.5.0",
"prop-types": "15.7.2",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-popper": "^2.2.3",
"react-table-6": "^6.8.6",
"react-table-6": "6.11.0",
"react-test-renderer": "17.0.2",
"react-transition-group": "4.3.0",
"react-use": "17.4.0",
"rst2html": "github:thoward/rst2html#990cb89",
"replace-in-file-webpack-plugin": "^1.0.6",
"rxjs": "6.6.3",
"sass-loader": "10.2.1",
"sass": "1.56.1",
"sass-loader": "13.2.0",
"semver": "^7.3.2",
"style-loader": "1.1.3",
"style-loader": "3.3.1",
"swc-loader": "^0.2.3",
"tether-drop": "^1.4.2",
"ts-jest": "24.1.0",
"ts-jest": "26.4.1",
"ts-loader": "4.4.1",
"ts-node": "^10.5.0",
"tsconfig-paths": "^4.1.0",
"tslint": "^6.1.3",
"typescript": "4.8.2",
"webpack": "4.41.5",
"webpack-cli": "3.3.10"
"webpack": "^5.69.1",
"webpack-cli": "^4.9.2",
"webpack-livereload-plugin": "^3.0.2",
"webpack-remove-empty-scripts": "^1.0.1"
},
"engines": {
"node": ">=16"
},
"resolutions": {
"js-yaml": "^3.13.1",

View File

@@ -1,10 +1,10 @@
import React, { FC } from 'react';
import { locationService } from '@grafana/runtime';
import { ExploreUrlState, TimeRange, urlUtil } from '@grafana/data';
import { MODE_ITEMID, MODE_METRICS } from '../../datasource-zabbix/constants';
import { MODE_ITEMID, MODE_METRICS } from '../../datasource/constants';
import { ActionButton } from '../ActionButton/ActionButton';
import { expandItemName } from '../../datasource-zabbix/utils';
import { ProblemDTO } from '../../datasource-zabbix/types';
import { expandItemName } from '../../datasource/utils';
import { ProblemDTO } from '../../datasource/types';
interface Props {
problem: ProblemDTO;

View File

@@ -1,14 +1,14 @@
import { css, cx } from '@emotion/css';
import React, { FormEvent, useCallback, useEffect, useState, useRef } from 'react';
import { ClickOutsideWrapper, Icon, Input, Spinner, useStyles2 } from '@grafana/ui';
import { ClickOutsideWrapper, Input, Spinner, useStyles2 } from '@grafana/ui';
import { MetricPickerMenu } from './MetricPickerMenu';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { isRegex } from '../../datasource-zabbix/utils';
import { isRegex } from '../../datasource/utils';
export interface Props {
value: string;
isLoading?: boolean;
options: SelectableValue<string>[];
options: Array<SelectableValue<string>>;
width?: number;
onChange: (value: string) => void;
}
@@ -18,7 +18,7 @@ export const MetricPicker = ({ value, options, isLoading, width, onChange }: Pro
const [query, setQuery] = useState(value);
const [filteredOptions, setFilteredOptions] = useState(options);
const [selectedOptionIdx, setSelectedOptionIdx] = useState(-1);
const [offset, setOffset] = useState({ vertical: 0, horizontal: 0 });
const [offset] = useState({ vertical: 0, horizontal: 0 });
const ref = useRef<HTMLDivElement>(null);
const customStyles = useStyles2(getStyles);
@@ -50,7 +50,7 @@ export const MetricPicker = ({ value, options, isLoading, width, onChange }: Pro
const newQuery = v?.currentTarget?.value;
if (newQuery) {
setQuery(newQuery);
if (value != newQuery) {
if (value !== newQuery) {
const filtered = options.filter(
(option) =>
option.value?.toLowerCase().includes(newQuery.toLowerCase()) ||
@@ -74,10 +74,7 @@ export const MetricPicker = ({ value, options, isLoading, width, onChange }: Pro
};
const onBlurInternal = () => {
if (!isOpen) {
// Only call if menu isn't opened
onChange(query);
}
};
const onKeyDown = (e: React.KeyboardEvent) => {

View File

@@ -5,7 +5,7 @@ import { CustomScrollbar, getSelectStyles, Icon, Tooltip, useStyles2, useTheme2
import { MENU_MAX_HEIGHT } from './constants';
interface Props {
options: SelectableValue<string>[];
options: Array<SelectableValue<string>>;
onSelect: (option: SelectableValue<string>) => void;
offset: { vertical: number; horizontal: number };
minWidth?: number;

View File

@@ -10,7 +10,7 @@ import { MetricPicker } from '../../components';
import { getVariableOptions } from './QueryEditor/utils';
import { prepareAnnotation } from '../migrations';
const severityOptions: SelectableValue<number>[] = [
const severityOptions: Array<SelectableValue<number>> = [
{ value: 0, label: 'Not classified' },
{ value: 1, label: 'Information' },
{ value: 2, label: 'Warning' },
@@ -46,7 +46,7 @@ export const AnnotationQueryEditor = ({ annotation, onAnnotationChange, datasour
const loadHostOptions = async (group: string) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hosts = await datasource.zabbix.getAllHosts(groupFilter);
let options: SelectableValue<string>[] = hosts?.map((host) => ({
let options: Array<SelectableValue<string>> = hosts?.map((host) => ({
value: host.name,
label: host.name,
}));
@@ -65,7 +65,7 @@ export const AnnotationQueryEditor = ({ annotation, onAnnotationChange, datasour
const groupFilter = datasource.replaceTemplateVars(group);
const hostFilter = datasource.replaceTemplateVars(host);
const apps = await datasource.zabbix.getAllApps(groupFilter, hostFilter);
let options: SelectableValue<string>[] = apps?.map((app) => ({
let options: Array<SelectableValue<string>> = apps?.map((app) => ({
value: app.name,
label: app.name,
}));

View File

@@ -44,10 +44,11 @@ export const ConfigEditor = (props: Props) => {
if (options.jsonData.dbConnectionEnable) {
if (!options.jsonData.dbConnectionDatasourceId) {
const dsName = options.jsonData.dbConnectionDatasourceName;
getDataSourceSrv().get(dsName)
.then(ds => {
getDataSourceSrv()
.get(dsName)
.then((ds) => {
if (ds) {
const selectedDs = getDirectDBDatasources().find(dsOption => dsOption.id === ds.id);
const selectedDs = getDirectDBDatasources().find((dsOption) => dsOption.id === ds.id);
setSelectedDBDatasource({ label: selectedDs.name, value: selectedDs.id });
setCurrentDSType(selectedDs.type);
onOptionsChange({
@@ -60,7 +61,9 @@ export const ConfigEditor = (props: Props) => {
}
});
} else {
const selectedDs = getDirectDBDatasources().find(dsOption => dsOption.id === options.jsonData.dbConnectionDatasourceId);
const selectedDs = getDirectDBDatasources().find(
(dsOption) => dsOption.id === options.jsonData.dbConnectionDatasourceId
);
setSelectedDBDatasource({ label: selectedDs.name, value: selectedDs.id });
setCurrentDSType(selectedDs.type);
}
@@ -89,7 +92,7 @@ export const ConfigEditor = (props: Props) => {
/>
</div>
<div className="gf-form max-width-25">
{options.secureJsonFields?.password ?
{options.secureJsonFields?.password ? (
<>
<FormField
labelWidth={7}
@@ -100,7 +103,8 @@ export const ConfigEditor = (props: Props) => {
placeholder="Configured"
/>
<Button onClick={resetSecureJsonField('password', options, onOptionsChange)}>Reset</Button>
</> :
</>
) : (
<FormField
labelWidth={7}
inputWidth={15}
@@ -110,7 +114,7 @@ export const ConfigEditor = (props: Props) => {
onChange={secureJsonDataChangeHandler('password', options, onOptionsChange)}
required
/>
}
)}
</div>
<Switch
label="Trends"
@@ -118,7 +122,7 @@ export const ConfigEditor = (props: Props) => {
checked={options.jsonData.trends}
onChange={jsonDataSwitchHandler('trends', options, onOptionsChange)}
/>
{options.jsonData.trends &&
{options.jsonData.trends && (
<>
<div className="gf-form">
<FormField
@@ -145,7 +149,7 @@ export const ConfigEditor = (props: Props) => {
/>
</div>
</>
}
)}
<div className="gf-form">
<FormField
labelWidth={7}
@@ -183,7 +187,7 @@ export const ConfigEditor = (props: Props) => {
checked={options.jsonData.dbConnectionEnable}
onChange={jsonDataSwitchHandler('dbConnectionEnable', options, onOptionsChange)}
/>
{options.jsonData.dbConnectionEnable &&
{options.jsonData.dbConnectionEnable && (
<>
<div className="gf-form">
<InlineFormLabel width={9}>Data Source</InlineFormLabel>
@@ -191,10 +195,15 @@ export const ConfigEditor = (props: Props) => {
width={32}
options={getDirectDBDSOptions()}
value={selectedDBDatasource}
onChange={directDBDatasourceChanegeHandler(options, onOptionsChange, setSelectedDBDatasource, setCurrentDSType)}
onChange={directDBDatasourceChanegeHandler(
options,
onOptionsChange,
setSelectedDBDatasource,
setCurrentDSType
)}
/>
</div>
{currentDSType === 'influxdb' &&
{currentDSType === 'influxdb' && (
<div className="gf-form">
<FormField
labelWidth={9}
@@ -207,9 +216,9 @@ export const ConfigEditor = (props: Props) => {
Leave it blank if only default retention policy used."
/>
</div>
}
)}
</>
}
)}
</div>
<div className="gf-form-group">
@@ -235,13 +244,13 @@ export const ConfigEditor = (props: Props) => {
);
};
const jsonDataChangeHandler = (
const jsonDataChangeHandler =
(
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
) => {
) =>
(event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>) => {
onChange({
...value,
jsonData: {
@@ -249,15 +258,15 @@ const jsonDataChangeHandler = (
[key]: event.currentTarget.value,
},
});
};
};
const jsonDataSwitchHandler = (
const jsonDataSwitchHandler =
(
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLInputElement>
) => {
) =>
(event: React.SyntheticEvent<HTMLInputElement>) => {
onChange({
...value,
jsonData: {
@@ -265,15 +274,15 @@ const jsonDataSwitchHandler = (
[key]: (event.target as HTMLInputElement).checked,
},
});
};
};
const secureJsonDataChangeHandler = (
const secureJsonDataChangeHandler =
(
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>
) => {
) =>
(event: React.SyntheticEvent<HTMLInputElement | HTMLSelectElement>) => {
onChange({
...value,
secureJsonData: {
@@ -281,15 +290,15 @@ const secureJsonDataChangeHandler = (
[key]: event.currentTarget.value,
},
});
};
};
const resetSecureJsonField = (
const resetSecureJsonField =
(
key: keyof ZabbixDSOptions,
value: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange']
) => (
event: React.SyntheticEvent<HTMLButtonElement>
) => {
) =>
(event: React.SyntheticEvent<HTMLButtonElement>) => {
onChange({
...value,
secureJsonFields: {
@@ -297,36 +306,40 @@ const resetSecureJsonField = (
[key]: false,
},
});
};
};
const directDBDatasourceChanegeHandler = (
const directDBDatasourceChanegeHandler =
(
options: DataSourceSettings<ZabbixDSOptions, ZabbixSecureJSONData>,
onChange: Props['onOptionsChange'],
setSelectedDS: React.Dispatch<any>,
setSelectedDSType: React.Dispatch<any>,
) => (
value: SelectableValue<number>
) => {
const selectedDs = getDirectDBDatasources().find(dsOption => dsOption.id === value.value);
setSelectedDSType: React.Dispatch<any>
) =>
(value: SelectableValue<number>) => {
const selectedDs = getDirectDBDatasources().find((dsOption) => dsOption.id === value.value);
setSelectedDS({ label: selectedDs.name, value: selectedDs.id });
setSelectedDSType(selectedDs.type);
onChange({
...options,
jsonData: {
...options.jsonData,
dbConnectionDatasourceId: value.value
dbConnectionDatasourceId: value.value,
},
});
};
};
const getDirectDBDatasources = () => {
let dsList = (getDataSourceSrv() as any).getAll();
dsList = dsList.filter(ds => SUPPORTED_SQL_DS.includes(ds.type));
dsList = dsList.filter((ds) => SUPPORTED_SQL_DS.includes(ds.type));
return dsList;
};
const getDirectDBDSOptions = () => {
const dsList = getDirectDBDatasources();
const dsOpts: Array<SelectableValue<number>> = dsList.map(ds => ({ label: ds.name, value: ds.id, description: ds.type }));
const dsOpts: Array<SelectableValue<number>> = dsList.map((ds) => ({
label: ds.name,
value: ds.id,
description: ds.type,
}));
return dsOpts;
};

View File

@@ -1,22 +1,7 @@
import { css, cx } from '@emotion/css';
import React, { useEffect, useMemo, useState } from 'react';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import {
Button,
ClickOutsideWrapper,
ContextMenu,
Dropdown,
Icon,
Input,
Menu,
MenuItem,
Portal,
Segment,
useStyles2,
useTheme2,
} from '@grafana/ui';
import React, { useMemo, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Button, ClickOutsideWrapper, Icon, Input, Menu, useStyles2, useTheme2 } from '@grafana/ui';
import { FuncDef } from '../../types';
import { getCategories } from '../../metricFunctions';

View File

@@ -1,5 +1,5 @@
import React, { Suspense } from 'react';
import { Icon, Tooltip } from '@grafana/ui';
import React from 'react';
import { Icon } from '@grafana/ui';
import { MetricFunc } from '../../types';
const DOCS_FUNC_REF_URL = 'https://alexanderzobnin.github.io/grafana-zabbix/reference/functions/';
@@ -10,30 +10,7 @@ export interface FunctionEditorControlsProps {
onRemove: (func: MetricFunc) => void;
}
const FunctionDescription = React.lazy(async () => {
// @ts-ignore
const { default: rst2html } = await import(/* webpackChunkName: "rst2html" */ 'rst2html');
return {
default(props: { description?: string }) {
return <div dangerouslySetInnerHTML={{ __html: rst2html(props.description ?? '') }} />;
},
};
});
const FunctionHelpButton = (props: { description?: string; name: string }) => {
if (props.description) {
let tooltip = (
<Suspense fallback={<span>Loading description...</span>}>
<FunctionDescription description={props.description} />
</Suspense>
);
return (
<Tooltip content={tooltip} placement={'bottom-end'}>
<Icon className={props.description ? undefined : 'pointer'} name="question-circle" />
</Tooltip>
);
}
return (
<Icon
className="pointer"

View File

@@ -4,7 +4,7 @@ import { InlineField, InlineFieldRow, Select } from '@grafana/ui';
import * as c from '../constants';
import * as migrations from '../migrations';
import { ZabbixDatasource } from '../datasource';
import { MetricFunc, ShowProblemTypes, ZabbixDSOptions, ZabbixMetricsQuery, ZabbixQueryOptions } from '../types';
import { ShowProblemTypes, ZabbixDSOptions, ZabbixMetricsQuery, ZabbixQueryOptions } from '../types';
import { MetricsQueryEditor } from './QueryEditor/MetricsQueryEditor';
import { QueryFunctionsEditor } from './QueryEditor/QueryFunctionsEditor';
import { QueryOptionsEditor } from './QueryEditor/QueryOptionsEditor';
@@ -136,10 +136,6 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: ZabbixQ
onChangeInternal({ ...query, options });
};
const getSelectableValue = (value: string): SelectableValue<string> => {
return { value, label: value };
};
const renderMetricsEditor = () => {
return (
<>

View File

@@ -10,7 +10,7 @@ import { getVariableOptions } from './utils';
import { ZabbixDatasource } from '../../datasource';
import { ZabbixMetricsQuery } from '../../types';
const slaPropertyList: SelectableValue<string>[] = [
const slaPropertyList: Array<SelectableValue<string>> = [
{ label: 'Status', value: 'status' },
{ label: 'SLA', value: 'sla' },
{ label: 'OK time', value: 'okTime' },
@@ -18,7 +18,7 @@ const slaPropertyList: SelectableValue<string>[] = [
{ label: 'Down time', value: 'downtimeTime' },
];
const slaIntervals: SelectableValue<string>[] = [
const slaIntervals: Array<SelectableValue<string>> = [
{ label: 'No interval', value: 'none' },
{ label: 'Auto', value: 'auto' },
{ label: '1 hour', value: '1h' },

View File

@@ -35,7 +35,7 @@ export const MetricsQueryEditor = ({ query, datasource, onChange }: Props) => {
const loadHostOptions = async (group: string) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hosts = await datasource.zabbix.getAllHosts(groupFilter);
let options: SelectableValue<string>[] = hosts?.map((host) => ({
let options: Array<SelectableValue<string>> = hosts?.map((host) => ({
value: host.name,
label: host.name,
}));
@@ -54,7 +54,7 @@ export const MetricsQueryEditor = ({ query, datasource, onChange }: Props) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hostFilter = datasource.replaceTemplateVars(host);
const apps = await datasource.zabbix.getAllApps(groupFilter, hostFilter);
let options: SelectableValue<string>[] = apps?.map((app) => ({
let options: Array<SelectableValue<string>> = apps?.map((app) => ({
value: app.name,
label: app.name,
}));
@@ -78,7 +78,7 @@ export const MetricsQueryEditor = ({ query, datasource, onChange }: Props) => {
showDisabledItems: query.options.showDisabledItems,
};
const items = await datasource.zabbix.getAllItems(groupFilter, hostFilter, appFilter, tagFilter, options);
let itemOptions: SelectableValue<string>[] = items?.map((item) => ({
let itemOptions: Array<SelectableValue<string>> = items?.map((item) => ({
value: item.name,
label: item.name,
}));

View File

@@ -10,13 +10,13 @@ import { getVariableOptions } from './utils';
import { ZabbixDatasource } from '../../datasource';
import { ZabbixMetricsQuery } from '../../types';
const showProblemsOptions: SelectableValue<string>[] = [
const showProblemsOptions: Array<SelectableValue<string>> = [
{ label: 'Problems', value: 'problems' },
{ label: 'Recent problems', value: 'recent' },
{ label: 'History', value: 'history' },
];
const severityOptions: SelectableValue<number>[] = [
const severityOptions: Array<SelectableValue<number>> = [
{ value: 0, label: 'Not classified' },
{ value: 1, label: 'Information' },
{ value: 2, label: 'Warning' },
@@ -50,7 +50,7 @@ export const ProblemsQueryEditor = ({ query, datasource, onChange }: Props) => {
const loadHostOptions = async (group: string) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hosts = await datasource.zabbix.getAllHosts(groupFilter);
let options: SelectableValue<string>[] = hosts?.map((host) => ({
let options: Array<SelectableValue<string>> = hosts?.map((host) => ({
value: host.name,
label: host.name,
}));
@@ -69,7 +69,7 @@ export const ProblemsQueryEditor = ({ query, datasource, onChange }: Props) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hostFilter = datasource.replaceTemplateVars(host);
const apps = await datasource.zabbix.getAllApps(groupFilter, hostFilter);
let options: SelectableValue<string>[] = apps?.map((app) => ({
let options: Array<SelectableValue<string>> = apps?.map((app) => ({
value: app.name,
label: app.name,
}));

View File

@@ -34,7 +34,7 @@ export const QueryFunctionsEditor = ({ query, onChange }: Props) => {
};
const onRemoveFunc = (func: MetricFunc) => {
const functions = query.functions?.filter((f) => f != func);
const functions = query.functions?.filter((f) => f !== func);
onChange({ ...query, functions });
};

View File

@@ -14,13 +14,13 @@ import {
import * as c from '../../constants';
import { ZabbixQueryOptions } from '../../types';
const ackOptions: SelectableValue<number>[] = [
const ackOptions: Array<SelectableValue<number>> = [
{ label: 'all triggers', value: 2 },
{ label: 'unacknowledged', value: 0 },
{ label: 'acknowledged', value: 1 },
];
const sortOptions: SelectableValue<string>[] = [
const sortOptions: Array<SelectableValue<string>> = [
{ label: 'Default', value: 'default' },
{ label: 'Last change', value: 'lastchange' },
{ label: 'Severity', value: 'severity' },

View File

@@ -35,7 +35,7 @@ export const TextMetricsQueryEditor = ({ query, datasource, onChange }: Props) =
const loadHostOptions = async (group: string) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hosts = await datasource.zabbix.getAllHosts(groupFilter);
let options: SelectableValue<string>[] = hosts?.map((host) => ({
let options: Array<SelectableValue<string>> = hosts?.map((host) => ({
value: host.name,
label: host.name,
}));
@@ -54,7 +54,7 @@ export const TextMetricsQueryEditor = ({ query, datasource, onChange }: Props) =
const groupFilter = datasource.replaceTemplateVars(group);
const hostFilter = datasource.replaceTemplateVars(host);
const apps = await datasource.zabbix.getAllApps(groupFilter, hostFilter);
let options: SelectableValue<string>[] = apps?.map((app) => ({
let options: Array<SelectableValue<string>> = apps?.map((app) => ({
value: app.name,
label: app.name,
}));
@@ -78,7 +78,7 @@ export const TextMetricsQueryEditor = ({ query, datasource, onChange }: Props) =
showDisabledItems: query.options.showDisabledItems,
};
const items = await datasource.zabbix.getAllItems(groupFilter, hostFilter, appFilter, tagFilter, options);
let itemOptions: SelectableValue<string>[] = items?.map((item) => ({
let itemOptions: Array<SelectableValue<string>> = items?.map((item) => ({
value: item.name,
label: item.name,
}));

View File

@@ -10,7 +10,7 @@ import { getVariableOptions } from './utils';
import { ZabbixDatasource } from '../../datasource';
import { ZabbixMetricsQuery } from '../../types';
const severityOptions: SelectableValue<number>[] = [
const severityOptions: Array<SelectableValue<number>> = [
{ value: 0, label: 'Not classified' },
{ value: 1, label: 'Information' },
{ value: 2, label: 'Warning' },
@@ -44,7 +44,7 @@ export const TriggersQueryEditor = ({ query, datasource, onChange }: Props) => {
const loadHostOptions = async (group: string) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hosts = await datasource.zabbix.getAllHosts(groupFilter);
let options: SelectableValue<string>[] = hosts?.map((host) => ({
let options: Array<SelectableValue<string>> = hosts?.map((host) => ({
value: host.name,
label: host.name,
}));
@@ -63,7 +63,7 @@ export const TriggersQueryEditor = ({ query, datasource, onChange }: Props) => {
const groupFilter = datasource.replaceTemplateVars(group);
const hostFilter = datasource.replaceTemplateVars(host);
const apps = await datasource.zabbix.getAllApps(groupFilter, hostFilter);
let options: SelectableValue<string>[] = apps?.map((app) => ({
let options: Array<SelectableValue<string>> = apps?.map((app) => ({
value: app.name,
label: app.name,
}));

View File

@@ -69,7 +69,7 @@ function setAliasByRegex(alias: string, frame: DataFrame) {
valueField.config.displayNameFromDS = extractText(valueField.config?.displayNameFromDS, alias);
}
frame.name = extractText(frame.name, alias);
} catch (error) {
} catch (error: any) {
console.error('Failed to apply RegExp:', error?.message || error);
}
return frame;
@@ -79,7 +79,7 @@ function setAliasByRegex(alias: string, frame: DataFrame) {
if (field.type !== FieldType.time) {
try {
field.config.displayNameFromDS = extractText(field.config?.displayNameFromDS, alias);
} catch (error) {
} catch (error: any) {
console.error('Failed to apply RegExp:', error?.message || error);
}
}

View File

@@ -48,11 +48,9 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
replaceTemplateVars: (target: any, scopedVars?: any) => any;
/** @ngInject */
constructor(instanceSettings: DataSourceInstanceSettings<ZabbixDSOptions>, private templateSrv) {
constructor(instanceSettings: DataSourceInstanceSettings<ZabbixDSOptions>) {
super(instanceSettings);
this.templateSrv = templateSrv;
this.enableDebugLog = config.buildInfo.env === 'development';
this.annotations = {
@@ -61,7 +59,8 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
};
// Use custom format for template variables
this.replaceTemplateVars = _.partial(replaceTemplateVars, this.templateSrv);
const templateSrv = getTemplateSrv();
this.replaceTemplateVars = _.partial(replaceTemplateVars, templateSrv);
// General data source settings
this.datasourceId = instanceSettings.id;
@@ -455,7 +454,8 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
*/
queryItemIdData(target, timeRange, useTrends, options) {
let itemids = target.itemids;
itemids = this.templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
const templateSrv = getTemplateSrv();
itemids = templateSrv.replace(itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
itemids = _.map(itemids.split(','), (itemid) => itemid.trim());
if (!itemids) {
@@ -631,7 +631,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
title: 'Success',
message: message,
};
} catch (error) {
} catch (error: any) {
if (error instanceof ZabbixAPIError) {
return {
status: 'error',
@@ -824,6 +824,7 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
// Replace template variables
replaceTargetVariables(target, options) {
const templateSrv = getTemplateSrv();
const parts = ['group', 'host', 'application', 'itemTag', 'item'];
_.forEach(parts, (p) => {
if (target[p] && target[p].filter) {
@@ -836,15 +837,15 @@ export class ZabbixDatasource extends DataSourceApi<ZabbixMetricsQuery, ZabbixDS
}
if (target.itemids) {
target.itemids = this.templateSrv.replace(target.itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
target.itemids = templateSrv.replace(target.itemids, options.scopedVars, zabbixItemIdsTemplateFormat);
}
_.forEach(target.functions, (func) => {
func.params = _.map(func.params, (param) => {
if (typeof param === 'number') {
return +this.templateSrv.replace(param.toString(), options.scopedVars);
return +templateSrv.replace(param.toString(), options.scopedVars);
} else {
return this.templateSrv.replace(param, options.scopedVars);
return templateSrv.replace(param, options.scopedVars);
}
});
});
@@ -935,7 +936,7 @@ function zabbixItemIdsTemplateFormat(value) {
* $variable -> a|b|c -> /a|b|c/
* /$variable/ -> /a|b|c/ -> /a|b|c/
*/
function replaceTemplateVars(templateSrv, target, scopedVars) {
export function replaceTemplateVars(templateSrv, target, scopedVars) {
let replacedTarget = templateSrv.replace(target, scopedVars, zabbixTemplateFormat);
if (target && target !== replacedTarget && !utils.isRegex(replacedTarget)) {
replacedTarget = '/^' + replacedTarget + '$/';

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -1,16 +1,8 @@
import { DataSourcePlugin } from '@grafana/data';
import { loadPluginCss } from '@grafana/runtime';
import { ZabbixDatasource } from './datasource';
import { QueryEditor } from './components/QueryEditor';
import { ZabbixVariableQueryEditor } from './components/VariableQueryEditor';
import { ConfigEditor } from './components/ConfigEditor';
import '../sass/grafana-zabbix.dark.scss';
import '../sass/grafana-zabbix.light.scss';
loadPluginCss({
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
light: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.light.css',
});
export const plugin = new DataSourcePlugin(ZabbixDatasource)
.setConfigEditor(ConfigEditor)

View File

@@ -2,14 +2,11 @@
"type": "datasource",
"name": "Zabbix",
"id": "alexanderzobnin-zabbix-datasource",
"metrics": true,
"annotations": true,
"backend": true,
"alerting": true,
"executable": "../zabbix-plugin",
"executable": "../gpx_zabbix-plugin",
"includes": [
{
"type": "dashboard",
@@ -27,11 +24,9 @@
"path": "dashboards/zabbix_server_dashboard.json"
}
],
"queryOptions": {
"maxDataPoints": true
},
"info": {
"author": {
"name": "Alexander Zobnin",

View File

@@ -1,5 +1,5 @@
import _ from 'lodash';
import * as utils from '../datasource-zabbix/utils';
import * as utils from './utils';
import { DataFrame, Field, FieldType, ArrayVector } from '@grafana/data';
import { ZBXProblem, ZBXTrigger, ProblemDTO, ZBXEvent } from './types';

View File

@@ -1,24 +1,30 @@
import mocks from '../../test-setup/mocks';
import { ZabbixDatasource, zabbixTemplateFormat } from "../datasource";
import _ from 'lodash';
import { templateSrvMock, datasourceSrvMock } from '../../test-setup/mocks';
import { replaceTemplateVars, ZabbixDatasource, zabbixTemplateFormat } from '../datasource';
import { dateMath } from '@grafana/data';
jest.mock('@grafana/runtime', () => ({
jest.mock(
'@grafana/runtime',
() => ({
getBackendSrv: () => ({
datasourceRequest: jest.fn().mockResolvedValue({ data: { result: '' } }),
fetch: () => ({
toPromise: () => jest.fn().mockResolvedValue({ data: { result: '' } })
toPromise: () => jest.fn().mockResolvedValue({ data: { result: '' } }),
}),
}),
loadPluginCss: () => {
},
}), { virtual: true });
getTemplateSrv: () => ({
replace: jest.fn().mockImplementation((query) => query),
}),
}),
{ virtual: true }
);
jest.mock('../components/AnnotationQueryEditor', () => ({
AnnotationQueryEditor: () => {},
}));
describe('ZabbixDatasource', () => {
let ctx = {};
let ctx: any = {};
beforeEach(() => {
ctx.instanceSettings = {
@@ -29,82 +35,89 @@ describe('ZabbixDatasource', () => {
trends: true,
trendsFrom: '14d',
trendsRange: '7d',
dbConnectionEnable: false
}
dbConnectionEnable: false,
},
};
ctx.options = {
targets: [
{
group: { filter: "" },
host: { filter: "" },
application: { filter: "" },
item: { filter: "" }
}
group: { filter: '' },
host: { filter: '' },
application: { filter: '' },
item: { filter: '' },
},
],
range: {
from: dateMath.parse('now-1h'),
to: dateMath.parse('now')
}
to: dateMath.parse('now'),
},
};
ctx.templateSrv = mocks.templateSrvMock;
ctx.datasourceSrv = mocks.datasourceSrvMock;
ctx.datasourceSrv = datasourceSrvMock;
ctx.ds = new ZabbixDatasource(ctx.instanceSettings, ctx.templateSrv);
ctx.ds = new ZabbixDatasource(ctx.instanceSettings);
ctx.ds.templateSrv = templateSrvMock;
});
describe('When querying text data', () => {
beforeEach(() => {
ctx.ds.replaceTemplateVars = (str) => str;
ctx.ds.zabbix.zabbixAPI.getHistory = jest.fn().mockReturnValue(Promise.resolve([
{ clock: "1500010200", itemid: "10100", ns: "900111000", value: "Linux first" },
{ clock: "1500010300", itemid: "10100", ns: "900111000", value: "Linux 2nd" },
{ clock: "1500010400", itemid: "10100", ns: "900111000", value: "Linux last" }
]));
ctx.ds.zabbix.zabbixAPI.getHistory = jest.fn().mockReturnValue(
Promise.resolve([
{ clock: '1500010200', itemid: '10100', ns: '900111000', value: 'Linux first' },
{ clock: '1500010300', itemid: '10100', ns: '900111000', value: 'Linux 2nd' },
{ clock: '1500010400', itemid: '10100', ns: '900111000', value: 'Linux last' },
])
);
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(
Promise.resolve([
{
hosts: [{ hostid: "10001", name: "Zabbix server" }],
itemid: "10100",
name: "System information",
key_: "system.uname",
}
]));
hosts: [{ hostid: '10001', name: 'Zabbix server' }],
itemid: '10100',
name: 'System information',
key_: 'system.uname',
},
])
);
ctx.options.targets = [{
group: { filter: "" },
host: { filter: "Zabbix server" },
application: { filter: "" },
item: { filter: "System information" },
textFilter: "",
ctx.options.targets = [
{
group: { filter: '' },
host: { filter: 'Zabbix server' },
application: { filter: '' },
item: { filter: 'System information' },
textFilter: '',
useCaptureGroups: true,
queryType: 2,
resultFormat: "table",
resultFormat: 'table',
options: {
skipEmptyValues: false
}
}];
skipEmptyValues: false,
},
},
];
});
it('should return data in table format', (done) => {
ctx.ds.query(ctx.options).then(result => {
ctx.ds.query(ctx.options).then((result) => {
expect(result.data.length).toBe(1);
let tableData = result.data[0];
expect(tableData.columns).toEqual([
{ text: 'Host' }, { text: 'Item' }, { text: 'Key' }, { text: 'Last value' }
]);
expect(tableData.rows).toEqual([
['Zabbix server', 'System information', 'system.uname', 'Linux last']
{ text: 'Host' },
{ text: 'Item' },
{ text: 'Key' },
{ text: 'Last value' },
]);
expect(tableData.rows).toEqual([['Zabbix server', 'System information', 'system.uname', 'Linux last']]);
done();
});
});
it('should extract value if regex with capture group is used', (done) => {
ctx.options.targets[0].textFilter = "Linux (.*)";
ctx.ds.query(ctx.options).then(result => {
ctx.options.targets[0].textFilter = 'Linux (.*)';
ctx.ds.query(ctx.options).then((result) => {
let tableData = result.data[0];
expect(tableData.rows[0][3]).toEqual('last');
done();
@@ -112,26 +125,34 @@ describe('ZabbixDatasource', () => {
});
it('should skip item when last value is empty', () => {
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(Promise.resolve([
ctx.ds.zabbix.getItemsFromTarget = jest.fn().mockReturnValue(
Promise.resolve([
{
hosts: [{ hostid: "10001", name: "Zabbix server" }],
itemid: "10100", name: "System information", key_: "system.uname"
hosts: [{ hostid: '10001', name: 'Zabbix server' }],
itemid: '10100',
name: 'System information',
key_: 'system.uname',
},
{
hosts: [{ hostid: "10002", name: "Server02" }],
itemid: "90109", name: "System information", key_: "system.uname"
}
]));
hosts: [{ hostid: '10002', name: 'Server02' }],
itemid: '90109',
name: 'System information',
key_: 'system.uname',
},
])
);
ctx.options.targets[0].options.skipEmptyValues = true;
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(Promise.resolve([
{ clock: "1500010200", itemid: "10100", ns: "900111000", value: "Linux first" },
{ clock: "1500010300", itemid: "10100", ns: "900111000", value: "Linux 2nd" },
{ clock: "1500010400", itemid: "10100", ns: "900111000", value: "Linux last" },
{ clock: "1500010200", itemid: "90109", ns: "900111000", value: "Non empty value" },
{ clock: "1500010500", itemid: "90109", ns: "900111000", value: "" }
]));
return ctx.ds.query(ctx.options).then(result => {
ctx.ds.zabbix.getHistory = jest.fn().mockReturnValue(
Promise.resolve([
{ clock: '1500010200', itemid: '10100', ns: '900111000', value: 'Linux first' },
{ clock: '1500010300', itemid: '10100', ns: '900111000', value: 'Linux 2nd' },
{ clock: '1500010400', itemid: '10100', ns: '900111000', value: 'Linux last' },
{ clock: '1500010200', itemid: '90109', ns: '900111000', value: 'Non empty value' },
{ clock: '1500010500', itemid: '90109', ns: '900111000', value: '' },
])
);
return ctx.ds.query(ctx.options).then((result) => {
let tableData = result.data[0];
expect(tableData.rows.length).toBe(1);
expect(tableData.rows[0][3]).toEqual('Linux last');
@@ -140,11 +161,10 @@ describe('ZabbixDatasource', () => {
});
describe('When replacing template variables', () => {
function testReplacingVariable(target, varValue, expectedResult, done) {
ctx.ds.templateSrv.replace = () => {
return zabbixTemplateFormat(varValue);
};
ctx.ds.replaceTemplateVars = _.partial(replaceTemplateVars, {
replace: jest.fn((target) => zabbixTemplateFormat(varValue)),
});
let result = ctx.ds.replaceTemplateVars(target);
expect(result).toBe(expectedResult);
@@ -198,7 +218,7 @@ describe('ZabbixDatasource', () => {
getGroups: jest.fn().mockReturnValue(Promise.resolve([])),
getHosts: jest.fn().mockReturnValue(Promise.resolve([])),
getApps: jest.fn().mockReturnValue(Promise.resolve([])),
getItems: jest.fn().mockReturnValue(Promise.resolve([]))
getItems: jest.fn().mockReturnValue(Promise.resolve([])),
};
});
@@ -218,7 +238,7 @@ describe('ZabbixDatasource', () => {
});
it('should return empty list for empty query', (done) => {
ctx.ds.metricFindQuery('').then(result => {
ctx.ds.metricFindQuery('').then((result) => {
expect(ctx.ds.zabbix.getGroups).toBeCalledTimes(0);
ctx.ds.zabbix.getGroups.mockClear();
@@ -248,7 +268,7 @@ describe('ZabbixDatasource', () => {
{ query: '*.*.*', expect: ['/.*/', '/.*/', '/.*/'] },
{ query: '.*.', expect: ['', '/.*/', ''] },
{ query: 'Backend.backend01.*', expect: ['Backend', 'backend01', '/.*/'] },
{ query: 'Back*.*.', expect: ['Back*', '/.*/', ''] }
{ query: 'Back*.*.', expect: ['Back*', '/.*/', ''] },
];
for (const test of tests) {
@@ -264,13 +284,18 @@ describe('ZabbixDatasource', () => {
{ query: '*.*.*.*', expect: ['/.*/', '/.*/', '', null, '/.*/'] },
{ query: '.*.*.*', expect: ['', '/.*/', '', null, '/.*/'] },
{ query: 'Backend.backend01.*.*', expect: ['Backend', 'backend01', '', null, '/.*/'] },
{ query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu', null, '/.*/'] }
{ query: 'Back*.*.cpu.*', expect: ['Back*', '/.*/', 'cpu', null, '/.*/'] },
];
for (const test of tests) {
ctx.ds.metricFindQuery(test.query);
expect(ctx.ds.zabbix.getItems)
.toBeCalledWith(test.expect[0], test.expect[1], test.expect[2], test.expect[3], test.expect[4]);
expect(ctx.ds.zabbix.getItems).toBeCalledWith(
test.expect[0],
test.expect[1],
test.expect[2],
test.expect[3],
test.expect[4]
);
ctx.ds.zabbix.getItems.mockClear();
}
done();

View File

@@ -3,14 +3,12 @@ import { compactQuery } from '../utils';
jest.mock('@grafana/runtime', () => ({
getDataSourceSrv: jest.fn(() => ({
get: jest.fn().mockResolvedValue(
{ id: 42, name: 'InfluxDB DS', meta: {} }
),
get: jest.fn().mockResolvedValue({ id: 42, name: 'InfluxDB DS', meta: {} }),
})),
}));
describe('InfluxDBConnector', () => {
let ctx = {};
let ctx: any = {};
beforeEach(() => {
ctx.options = { datasourceName: 'InfluxDB DS', retentionPolicy: 'longterm' };
@@ -20,7 +18,8 @@ describe('InfluxDBConnector', () => {
itemids: ['123', '234'],
range: { timeFrom: 15000, timeTill: 15100 },
intervalSec: 5,
table: 'history', aggFunction: 'MAX'
table: 'history',
aggFunction: 'MAX',
};
});
@@ -57,9 +56,7 @@ describe('InfluxDBConnector', () => {
it('should query proper table depending on item type', () => {
const { timeFrom, timeTill } = ctx.defaultQueryParams.range;
const options = { intervalMs: 5000 };
const items = [
{ itemid: '123', value_type: 3 }
];
const items = [{ itemid: '123', value_type: 3 }];
const expectedQuery = compactQuery(`SELECT MEAN("value")
FROM "history_uint"
WHERE ("itemid" = '123')
@@ -97,9 +94,7 @@ describe('InfluxDBConnector', () => {
ctx.influxDBConnector.retentionPolicy = '';
const { timeFrom, timeTill } = ctx.defaultQueryParams.range;
const options = { intervalMs: 5000 };
const items = [
{ itemid: '123', value_type: 3 }
];
const items = [{ itemid: '123', value_type: 3 }];
const expectedQuery = compactQuery(`SELECT MEAN("value")
FROM "history_uint"
WHERE ("itemid" = '123')
@@ -114,9 +109,7 @@ describe('InfluxDBConnector', () => {
it('should use retention policy name for trends query if it was set', () => {
const { timeFrom, timeTill } = ctx.defaultQueryParams.range;
const options = { intervalMs: 5000 };
const items = [
{ itemid: '123', value_type: 3 }
];
const items = [{ itemid: '123', value_type: 3 }];
const expectedQuery = compactQuery(`SELECT MEAN("value_avg")
FROM "longterm"."history_uint"
WHERE ("itemid" = '123')
@@ -131,9 +124,7 @@ describe('InfluxDBConnector', () => {
it('should use proper value column if retention policy set (trends used)', () => {
const { timeFrom, timeTill } = ctx.defaultQueryParams.range;
const options = { intervalMs: 5000, consolidateBy: 'max' };
const items = [
{ itemid: '123', value_type: 3 }
];
const items = [{ itemid: '123', value_type: 3 }];
const expectedQuery = compactQuery(`SELECT MAX("value_max")
FROM "longterm"."history_uint"
WHERE ("itemid" = '123')

View File

@@ -2,15 +2,15 @@ import _ from 'lodash';
import { migrateDSConfig, DS_CONFIG_SCHEMA } from '../migrations';
describe('Migrations', () => {
let ctx = {};
let ctx: any = {};
describe('When migrating datasource config', () => {
beforeEach(() => {
ctx.jsonData = {
dbConnection: {
enable: true,
datasourceId: 1
}
datasourceId: 1,
},
};
});
@@ -19,7 +19,7 @@ describe('Migrations', () => {
expect(ctx.jsonData).toMatchObject({
dbConnectionEnable: true,
dbConnectionDatasourceId: 1,
schema: DS_CONFIG_SCHEMA
schema: DS_CONFIG_SCHEMA,
});
});
@@ -27,13 +27,13 @@ describe('Migrations', () => {
ctx.jsonData = {
futureOptionOne: 'foo',
futureOptionTwo: 'bar',
schema: DS_CONFIG_SCHEMA
schema: DS_CONFIG_SCHEMA,
};
migrateDSConfig(ctx.jsonData);
expect(ctx.jsonData).toMatchObject({
futureOptionOne: 'foo',
futureOptionTwo: 'bar',
schema: DS_CONFIG_SCHEMA
schema: DS_CONFIG_SCHEMA,
});
expect(ctx.jsonData.dbConnectionEnable).toBeUndefined();
expect(ctx.jsonData.dbConnectionDatasourceId).toBeUndefined();
@@ -55,7 +55,7 @@ describe('Migrations', () => {
disableReadOnlyUsersAck: true,
dbConnectionEnable: true,
dbConnectionDatasourceName: 'MySQL Zabbix',
dbConnectionRetentionPolicy: 'one_year'
dbConnectionRetentionPolicy: 'one_year',
};
});

View File

@@ -1,4 +1,5 @@
import _ from 'lodash';
// eslint-disable-next-line
import moment from 'moment';
import * as c from './constants';
import { VariableQuery, VariableQueryTypes, ZBXItemTag } from './types';
@@ -507,12 +508,12 @@ export function isProblemsDataFrame(data: DataFrame): boolean {
}
// Swap n and k elements.
export function swap<T>(list: Array<T>, n: number, k: number): Array<T> {
export function swap<T>(list: T[], n: number, k: number): T[] {
if (list === null || list.length < 2 || k > list.length - 1 || k < 0 || n > list.length - 1 || n < 0) {
return list;
}
const newList: Array<T> = new Array(list.length);
const newList: T[] = new Array(list.length);
for (let i = 0; i < list.length; i++) {
if (i === n) {
newList[i] = list[k];

View File

@@ -31,14 +31,6 @@ export const consolidateByTrendColumns = {
sum: 'num*value_avg', // sum of sums inside the one-hour trend period
};
export interface IDBConnector {
getHistory(): any;
getTrends(): any;
testDataSource(): any;
}
/**
* Base class for external history database connectors. Subclasses should implement `getHistory()`, `getTrends()` and
* `testDataSource()` methods, which describe how to fetch data from source other than Zabbix API.
@@ -47,13 +39,13 @@ export class DBConnector {
protected datasourceId: any;
private datasourceName: any;
protected datasourceTypeId: any;
private datasourceTypeName: any;
// private datasourceTypeName: any;
constructor(options) {
this.datasourceId = options.datasourceId;
this.datasourceName = options.datasourceName;
this.datasourceTypeId = null;
this.datasourceTypeName = null;
// this.datasourceTypeName = null;
}
static loadDatasource(dsId, dsName) {
@@ -74,7 +66,7 @@ export class DBConnector {
loadDBDataSource() {
return DBConnector.loadDatasource(this.datasourceId, this.datasourceName).then((ds) => {
this.datasourceTypeId = ds.meta.id;
this.datasourceTypeName = ds.meta.name;
// this.datasourceTypeName = ds.meta.name;
if (!this.datasourceName) {
this.datasourceName = ds.name;
}

View File

@@ -2,12 +2,10 @@ import {
ArrayVector,
DataFrame,
dataFrameToJSON,
DataSourceApi,
Field,
FieldType,
MutableDataFrame,
TIME_SERIES_TIME_FIELD_NAME,
toDataFrame,
} from '@grafana/data';
import _ from 'lodash';
import { compactQuery } from '../../../utils';

View File

@@ -20,7 +20,7 @@ const roundInterval: (interval: number) => number = rangeUtil?.roundInterval ||
*/
export class ZabbixAPIConnector {
backendAPIUrl: string;
requestOptions: { basicAuth: any; withCredentials: boolean; };
requestOptions: { basicAuth: any; withCredentials: boolean };
getTrend: (items: any, timeFrom: any, timeTill: any) => Promise<any[]>;
version: string;
getVersionPromise: Promise<string>;
@@ -32,7 +32,7 @@ export class ZabbixAPIConnector {
this.requestOptions = {
basicAuth: basicAuth,
withCredentials: withCredentials
withCredentials: withCredentials,
};
this.getTrend = this.getTrend_ZBXNEXT1193;
@@ -58,7 +58,7 @@ export class ZabbixAPIConnector {
url: this.backendAPIUrl,
method: 'POST',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
hideFromInspector: false,
data: {
@@ -90,7 +90,7 @@ export class ZabbixAPIConnector {
initVersion(): Promise<string> {
if (!this.getVersionPromise) {
this.getVersionPromise = Promise.resolve(
this.getVersion().then(version => {
this.getVersion().then((version) => {
if (version) {
console.log(`Zabbix version detected: ${version}`);
} else {
@@ -122,7 +122,7 @@ export class ZabbixAPIConnector {
const params: any = {
eventids: eventid,
message: message,
action: action
action: action,
};
if (severity !== undefined) {
@@ -136,7 +136,7 @@ export class ZabbixAPIConnector {
const params = {
output: ['name', 'groupid'],
sortfield: 'name',
real_hosts: true
real_hosts: true,
};
return this.request('hostgroup.get', params);
@@ -145,7 +145,7 @@ export class ZabbixAPIConnector {
getHosts(groupids) {
const params: any = {
output: ['hostid', 'name', 'host'],
sortfield: 'name'
sortfield: 'name',
};
if (groupids) {
params.groupids = groupids;
@@ -161,7 +161,7 @@ export class ZabbixAPIConnector {
const params = {
output: 'extend',
hostids: hostids
hostids: hostids,
};
return this.request('application.get', params);
@@ -176,22 +176,11 @@ export class ZabbixAPIConnector {
*/
getItems(hostids, appids, itemtype) {
const params: any = {
output: [
'itemid',
'name',
'key_',
'value_type',
'hostid',
'status',
'state',
'units',
'valuemapid',
'delay'
],
output: ['itemid', 'name', 'key_', 'value_type', 'hostid', 'status', 'state', 'units', 'valuemapid', 'delay'],
sortfield: 'name',
webitems: true,
filter: {},
selectHosts: ['hostid', 'name', 'host']
selectHosts: ['hostid', 'name', 'host'],
};
if (hostids) {
params.hostids = hostids;
@@ -212,41 +201,28 @@ export class ZabbixAPIConnector {
params.selectTags = 'extend';
}
return this.request('item.get', params)
.then(utils.expandItems);
return this.request('item.get', params).then(utils.expandItems);
}
getItemsByIDs(itemids) {
const params: any = {
itemids: itemids,
output: [
'itemid',
'name',
'key_',
'value_type',
'hostid',
'status',
'state',
'units',
'valuemapid',
'delay'
],
output: ['itemid', 'name', 'key_', 'value_type', 'hostid', 'status', 'state', 'units', 'valuemapid', 'delay'],
webitems: true,
selectHosts: ['hostid', 'name']
selectHosts: ['hostid', 'name'],
};
if (this.isZabbix54OrHigher()) {
params.selectTags = 'extend';
}
return this.request('item.get', params)
.then(items => utils.expandItems(items));
return this.request('item.get', params).then((items) => utils.expandItems(items));
}
getMacros(hostids) {
const params = {
output: 'extend',
hostids: hostids
hostids: hostids,
};
return this.request('usermacro.get', params);
@@ -255,7 +231,7 @@ export class ZabbixAPIConnector {
getGlobalMacros() {
const params = {
output: 'extend',
globalmacro: true
globalmacro: true,
};
return this.request('usermacro.get', params);
@@ -264,10 +240,9 @@ export class ZabbixAPIConnector {
getLastValue(itemid) {
const params = {
output: ['lastvalue'],
itemids: itemid
itemids: itemid,
};
return this.request('item.get', params)
.then(items => items.length ? items[0].lastvalue : null);
return this.request('item.get', params).then((items) => (items.length ? items[0].lastvalue : null));
}
/**
@@ -279,7 +254,6 @@ export class ZabbixAPIConnector {
* @return {Array} Array of Zabbix history objects
*/
getHistory(items, timeFrom, timeTill) {
// Group items by value type and perform request for each value type
const grouped_items = _.groupBy(items, 'value_type');
const promises = _.map(grouped_items, (items, value_type) => {
@@ -290,7 +264,7 @@ export class ZabbixAPIConnector {
itemids: itemids,
sortfield: 'clock',
sortorder: 'ASC',
time_from: timeFrom
time_from: timeFrom,
};
// Relative queries (e.g. last hour) don't include an end time
@@ -314,7 +288,6 @@ export class ZabbixAPIConnector {
* @return {Array} Array of Zabbix trend objects
*/
getTrend_ZBXNEXT1193(items, timeFrom, timeTill) {
// Group items by value type and perform request for each value type
const grouped_items = _.groupBy(items, 'value_type');
const promises = _.map(grouped_items, (items, value_type) => {
@@ -325,7 +298,7 @@ export class ZabbixAPIConnector {
itemids: itemids,
sortfield: 'clock',
sortorder: 'ASC',
time_from: timeFrom
time_from: timeFrom,
};
// Relative queries (e.g. last hour) don't include an end time
@@ -344,13 +317,9 @@ export class ZabbixAPIConnector {
const itemids = _.map(items, 'itemid');
const params: any = {
output: [
'itemid',
'clock',
value_type
],
output: ['itemid', 'clock', value_type],
itemids: itemids,
time_from: time_from
time_from: time_from,
};
// Relative queries (e.g. last hour) don't include an end time
@@ -364,7 +333,7 @@ export class ZabbixAPIConnector {
getITService(serviceids?) {
const params = {
output: 'extend',
serviceids: serviceids
serviceids: serviceids,
};
return this.request('service.get', params);
}
@@ -382,7 +351,7 @@ export class ZabbixAPIConnector {
const params: any = {
serviceids,
intervals
intervals,
};
return this.request('service.getsla', params);
@@ -410,10 +379,10 @@ export class ZabbixAPIConnector {
}
const sla = slaObjects[0];
const periods = intervals.map(interval => ({
period_from: interval.from,
period_to: interval.to,
}));
// const periods = intervals.map(interval => ({
// period_from: interval.from,
// period_to: interval.to,
// }));
const sliParams: any = {
slaid: sla.slaid,
serviceids,
@@ -430,7 +399,7 @@ export class ZabbixAPIConnector {
const slaLikeResponse: any = {};
sliResponse.serviceids.forEach((serviceid) => {
slaLikeResponse[serviceid] = {
sla: []
sla: [],
};
});
sliResponse.sli.forEach((sliItem, i) => {
@@ -440,7 +409,7 @@ export class ZabbixAPIConnector {
okTime: sli.uptime,
sla: sli.sli,
from: sliResponse.periods[i].period_from,
to: sliResponse.periods[i].period_to
to: sliResponse.periods[i].period_to,
});
});
});
@@ -526,13 +495,13 @@ export class ZabbixAPIConnector {
skipDependent: true,
//only_true: true,
filter: {
value: 1
value: 1,
},
selectGroups: ['groupid', 'name'],
selectHosts: ['hostid', 'name', 'host', 'maintenance_status', 'proxy_hostid'],
selectItems: ['itemid', 'name', 'key_', 'lastvalue'],
selectLastEvent: 'extend',
selectTags: 'extend'
selectTags: 'extend',
};
if (showTriggers === ShowProblemTypes.Problems) {
@@ -617,7 +586,7 @@ export class ZabbixAPIConnector {
select_acknowledges: 'extend',
selectTags: 'extend',
sortfield: 'clock',
sortorder: 'DESC'
sortorder: 'DESC',
};
return this.request('event.get', params);
@@ -626,13 +595,7 @@ export class ZabbixAPIConnector {
getEventAlerts(eventids) {
const params = {
eventids: eventids,
output: [
'alertid',
'eventid',
'message',
'clock',
'error'
],
output: ['alertid', 'eventid', 'message', 'clock', 'error'],
selectUsers: true,
};
@@ -646,11 +609,10 @@ export class ZabbixAPIConnector {
preservekeys: true,
select_acknowledges: 'extend',
sortfield: 'clock',
sortorder: 'DESC'
sortorder: 'DESC',
};
return this.request('event.get', params)
.then(events => {
return this.request('event.get', params).then((events) => {
return _.filter(events, (event) => event.acknowledges.length);
});
}
@@ -668,7 +630,7 @@ export class ZabbixAPIConnector {
// filter: {
// value: 1
// },
selectLastEvent: 'extend'
selectLastEvent: 'extend',
};
if (timeFrom || timeTo) {
@@ -693,7 +655,7 @@ export class ZabbixAPIConnector {
skipDependent: true,
selectLastEvent: 'extend',
selectGroups: 'extend',
selectHosts: ['hostid', 'host', 'name']
selectHosts: ['hostid', 'host', 'name'],
};
if (count && acknowledged !== 0 && acknowledged !== 1) {
@@ -709,8 +671,7 @@ export class ZabbixAPIConnector {
params.lastChangeTill = timeTo;
}
return this.request('trigger.get', params)
.then((triggers) => {
return this.request('trigger.get', params).then((triggers) => {
if (!count || acknowledged === 0 || acknowledged === 1) {
triggers = filterTriggersByAcknowledge(triggers, acknowledged);
if (count) {
@@ -750,7 +711,7 @@ export class ZabbixAPIConnector {
getValueMappings() {
const params = {
output: 'extend',
selectMappings: "extend",
selectMappings: 'extend',
};
return this.request('valuemap.get', params);
@@ -759,9 +720,9 @@ export class ZabbixAPIConnector {
function filterTriggersByAcknowledge(triggers, acknowledged) {
if (acknowledged === 0) {
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "0");
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === '0');
} else if (acknowledged === 1) {
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "1");
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === '1');
} else {
return triggers;
}
@@ -785,9 +746,8 @@ function buildSLAIntervals(timeRange, interval) {
for (let i = timeFrom; i <= timeTo - interval; i += interval) {
intervals.push({
from: i,
to: (i + interval)
to: i + interval,
});
}
return intervals;
@@ -802,12 +762,12 @@ export class ZabbixAPIError {
constructor(error: JSONRPCError) {
this.code = error.code || null;
this.name = error.message || "";
this.data = error.data || "";
this.message = "Zabbix API Error: " + this.name + " " + this.data;
this.name = error.message || '';
this.data = error.data || '';
this.message = 'Zabbix API Error: ' + this.name + ' ' + this.data;
}
toString() {
return this.name + " " + this.data;
return this.name + ' ' + this.data;
}
}

View File

@@ -1,4 +1,5 @@
import _ from 'lodash';
// eslint-disable-next-line
import moment from 'moment';
import semver from 'semver';
import * as utils from '../utils';

View File

@@ -1,12 +1,9 @@
import { AppPlugin } from '@grafana/data';
import { loadPluginCss } from 'grafana/app/plugins/sdk';
import './sass/grafana-zabbix.dark.scss';
import './sass/grafana-zabbix.light.scss';
loadPluginCss({
dark: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.dark.css',
light: 'plugins/alexanderzobnin-zabbix-app/css/grafana-zabbix.light.css',
dark: 'plugins/alexanderzobnin-zabbix-app/styles/dark.css',
light: 'plugins/alexanderzobnin-zabbix-app/styles/light.css',
});
export const plugin = new AppPlugin<{}>();

View File

@@ -1,12 +1,11 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React from 'react';
import _ from 'lodash';
import { BusEventBase, BusEventWithPayload, dateMath, PanelProps } from '@grafana/data';
import { DataSourceRef, dateMath, PanelProps } from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { useTheme2 } from '@grafana/ui';
import { contextSrv } from 'grafana/app/core/core';
import { ProblemsPanelOptions } from './types';
import { ProblemDTO, ZabbixMetricsQuery, ZBXQueryUpdatedEvent, ZBXTag } from '../datasource-zabbix/types';
import { APIExecuteScriptResponse } from '../datasource-zabbix/zabbix/connectors/zabbix_api/types';
import { ProblemsPanelOptions, RTResized } from './types';
import { ProblemDTO, ZabbixMetricsQuery, ZBXQueryUpdatedEvent, ZBXTag } from '../datasource/types';
import { APIExecuteScriptResponse } from '../datasource/zabbix/connectors/zabbix_api/types';
import ProblemList from './components/Problems/Problems';
import { AckProblemData } from './components/AckModal';
import AlertList from './components/AlertList/AlertList';
@@ -18,7 +17,6 @@ interface ProblemsPanelProps extends PanelProps<ProblemsPanelOptions> {}
export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
const { data, options, timeRange, onOptionsChange } = props;
const { layout, showTriggers, triggerSeverity, sortProblems } = options;
const theme = useTheme2();
const prepareProblems = () => {
const problems: ProblemDTO[] = [];
@@ -63,11 +61,8 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
// Filter triggers by severity
problemsList = problemsList.filter((problem) => {
if (problem.severity) {
return triggerSeverity[problem.severity].show;
} else {
return triggerSeverity[problem.priority].show;
}
const severity = problem.severity !== undefined ? Number(problem.severity) : Number(problem.priority);
return triggerSeverity[severity].show;
});
return problemsList;
@@ -97,7 +92,7 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
// Set tags if present
if (trigger.tags && trigger.tags.length === 0) {
trigger.tags = null;
trigger.tags = undefined;
}
// Handle multi-line description
@@ -109,7 +104,7 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
return trigger;
};
const parseTags = (tagStr: string) => {
const parseTags = (tagStr: string): ZBXTag[] => {
if (!tagStr) {
return [];
}
@@ -126,18 +121,18 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
return _.map(tags, (tag) => `${tag.tag}:${tag.value}`).join(', ');
};
const addTagFilter = (tag, datasource) => {
const targets = data.request.targets;
const addTagFilter = (tag: ZBXTag, datasource: DataSourceRef) => {
const targets = data.request?.targets!;
let updated = false;
for (const target of targets) {
if (target.datasource?.uid === datasource?.uid || target.datasource === datasource) {
const tagFilter = (target as ZabbixMetricsQuery).tags.filter;
const tagFilter = (target as ZabbixMetricsQuery).tags?.filter!;
let targetTags = parseTags(tagFilter);
const newTag = { tag: tag.tag, value: tag.value };
targetTags.push(newTag);
targetTags = _.uniqWith(targetTags, _.isEqual);
const newFilter = tagsToString(targetTags);
(target as ZabbixMetricsQuery).tags.filter = newFilter;
(target as ZabbixMetricsQuery).tags!.filter = newFilter;
updated = true;
}
}
@@ -148,18 +143,18 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
}
};
const removeTagFilter = (tag, datasource) => {
const matchTag = (t) => t.tag === tag.tag && t.value === tag.value;
const targets = data.request.targets;
const removeTagFilter = (tag: ZBXTag, datasource: DataSourceRef) => {
const matchTag = (t: ZBXTag) => t.tag === tag.tag && t.value === tag.value;
const targets = data.request?.targets!;
let updated = false;
for (const target of targets) {
if (target.datasource?.uid === datasource?.uid || target.datasource === datasource) {
const tagFilter = (target as ZabbixMetricsQuery).tags.filter;
const tagFilter = (target as ZabbixMetricsQuery).tags?.filter!;
let targetTags = parseTags(tagFilter);
_.remove(targetTags, matchTag);
targetTags = _.uniqWith(targetTags, _.isEqual);
const newFilter = tagsToString(targetTags);
(target as ZabbixMetricsQuery).tags.filter = newFilter;
(target as ZabbixMetricsQuery).tags!.filter = newFilter;
updated = true;
}
}
@@ -172,8 +167,8 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
const getProblemEvents = async (problem: ProblemDTO) => {
const triggerids = [problem.triggerid];
const timeFrom = Math.ceil(dateMath.parse(timeRange.from).unix());
const timeTo = Math.ceil(dateMath.parse(timeRange.to).unix());
const timeFrom = Math.ceil(dateMath.parse(timeRange.from)!.unix());
const timeTo = Math.ceil(dateMath.parse(timeRange.to)!.unix());
const ds: any = await getDataSourceSrv().get(problem.datasource);
return ds.zabbix.getEvents(triggerids, timeFrom, timeTo, [0, 1], PROBLEM_EVENTS_LIMIT);
};
@@ -216,11 +211,11 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
}
};
const onColumnResize = (newResized) => {
const onColumnResize = (newResized: RTResized) => {
onOptionsChange({ ...options, resizedColumns: newResized });
};
const onTagClick = (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => {
const onTagClick = (tag: ZBXTag, datasource: DataSourceRef, ctrlKey?: boolean, shiftKey?: boolean) => {
if (ctrlKey || shiftKey) {
removeTagFilter(tag, datasource);
} else {
@@ -231,7 +226,7 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
const renderList = () => {
const problems = prepareProblems();
const fontSize = parseInt(options.fontSize.slice(0, options.fontSize.length - 1), 10);
const fontSizeProp = fontSize && fontSize !== 100 ? fontSize : null;
const fontSizeProp = fontSize && fontSize !== 100 ? fontSize : undefined;
return (
<AlertList
@@ -248,7 +243,7 @@ export const ProblemsPanel = (props: ProblemsPanelProps): JSX.Element => {
const renderTable = () => {
const problems = prepareProblems();
const fontSize = parseInt(options.fontSize.slice(0, options.fontSize.length - 1), 10);
const fontSizeProp = fontSize && fontSize !== 100 ? fontSize : null;
const fontSizeProp = fontSize && fontSize !== 100 ? fontSize : undefined;
return (
<ProblemList

View File

@@ -5,7 +5,7 @@ import {
ZBX_ACK_ACTION_ACK,
ZBX_ACK_ACTION_CHANGE_SEVERITY,
ZBX_ACK_ACTION_CLOSE,
} from '../../datasource-zabbix/constants';
} from '../../datasource/constants';
import {
Button,
VerticalGroup,

View File

@@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
import { ProblemDTO } from '../../../datasource-zabbix/types';
import { ProblemDTO } from '../../../datasource/types';
interface AlertAcknowledgesProps {
problem: ProblemDTO;

View File

@@ -1,6 +1,7 @@
import React, { PureComponent, CSSProperties } from 'react';
import classNames from 'classnames';
import { cx } from '@emotion/css';
import _ from 'lodash';
// eslint-disable-next-line
import moment from 'moment';
import { isNewProblem, formatLastChange } from '../../utils';
import { ProblemsPanelOptions, TriggerSeverity } from '../../types';
@@ -8,7 +9,7 @@ import { AckProblemData, AckModal } from '../AckModal';
import EventTag from '../EventTag';
import AlertAcknowledges from './AlertAcknowledges';
import AlertIcon from './AlertIcon';
import { ProblemDTO, ZBXTag } from '../../../datasource-zabbix/types';
import { ProblemDTO, ZBXTag } from '../../../datasource/types';
import { ModalController } from '../../../components';
import { DataSourceRef } from '@grafana/data';
import { Tooltip } from '@grafana/ui';
@@ -36,10 +37,10 @@ export default class AlertCard extends PureComponent<AlertCardProps> {
render() {
const { problem, panelOptions } = this.props;
const showDatasourceName = panelOptions.targets && panelOptions.targets.length > 1;
const cardClass = classNames('alert-rule-item', 'zbx-trigger-card', {
const cardClass = cx('alert-rule-item', 'zbx-trigger-card', {
'zbx-trigger-highlighted': panelOptions.highlightBackground,
});
const descriptionClass = classNames('alert-rule-item__text', {
const descriptionClass = cx('alert-rule-item__text', {
'zbx-description--newline': panelOptions.descriptionAtNewLine,
});
@@ -155,7 +156,7 @@ export default class AlertCard extends PureComponent<AlertCardProps> {
<span>{lastchange || 'last change unknown'}</span>
<div className="trigger-info-block zbx-status-icons">
{problem.url && (
<a href={problem.url} target="_blank">
<a href={problem.url} target="_blank" rel="noreferrer">
<i className="fa fa-external-link"></i>
</a>
)}
@@ -239,19 +240,23 @@ const DEFAULT_PROBLEM_COLOR = 'rgb(215, 0, 0)';
function AlertStatus(props) {
const { problem, okColor, problemColor, blink } = props;
const status = problem.value === '0' ? 'RESOLVED' : 'PROBLEM';
const color = problem.value === '0' ? okColor || DEFAULT_OK_COLOR : problemColor || DEFAULT_PROBLEM_COLOR;
const className = classNames(
const color: string = problem.value === '0' ? okColor || DEFAULT_OK_COLOR : problemColor || DEFAULT_PROBLEM_COLOR;
const className = cx(
'zbx-trigger-state',
{ 'alert-state-critical': problem.value === '1' },
{ 'alert-state-ok': problem.value === '0' },
{ 'zabbix-trigger--blinked': blink }
);
return <span className={className}>{status}</span>;
return (
<span className={className} style={{ color: color }}>
{status}
</span>
);
}
function AlertSeverity(props) {
const { severityDesc, highlightBackground, blink } = props;
const className = classNames('zbx-trigger-severity', { 'zabbix-trigger--blinked': blink });
const className = cx('zbx-trigger-severity', { 'zabbix-trigger--blinked': blink });
const style: CSSProperties = {};
if (!highlightBackground) {
style.color = severityDesc.color;

View File

@@ -1,7 +1,7 @@
import React, { FC } from 'react';
import { cx, css } from '@emotion/css';
import { GFHeartIcon } from '../../../components';
import { ProblemDTO } from '../../../datasource-zabbix/types';
import { ProblemDTO } from '../../../datasource/types';
interface Props {
problem: ProblemDTO;

View File

@@ -1,9 +1,9 @@
import React, { PureComponent, CSSProperties } from 'react';
import classNames from 'classnames';
import React, { PureComponent } from 'react';
import { cx } from '@emotion/css';
import { ProblemsPanelOptions } from '../../types';
import { AckProblemData } from '../AckModal';
import AlertCard from './AlertCard';
import { ProblemDTO, ZBXTag } from '../../../datasource-zabbix/types';
import { ProblemDTO, ZBXTag } from '../../../datasource/types';
import { DataSourceRef } from '@grafana/data';
export interface AlertListProps {
@@ -13,7 +13,7 @@ export interface AlertListProps {
pageSize?: number;
fontSize?: number;
onProblemAck?: (problem: ProblemDTO, data: AckProblemData) => void;
onTagClick?: (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => void;
onTagClick?: (tag: ZBXTag, datasource: DataSourceRef, ctrlKey?: boolean, shiftKey?: boolean) => void;
}
interface AlertListState {
@@ -45,7 +45,7 @@ export default class AlertList extends PureComponent<AlertListProps, AlertListSt
});
};
handleTagClick = (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => {
handleTagClick = (tag: ZBXTag, datasource: DataSourceRef, ctrlKey?: boolean, shiftKey?: boolean) => {
if (this.props.onTagClick) {
this.props.onTagClick(tag, datasource, ctrlKey, shiftKey);
}
@@ -60,7 +60,7 @@ export default class AlertList extends PureComponent<AlertListProps, AlertListSt
const currentProblems = this.getCurrentProblems(this.state.page);
let fontSize = parseInt(panelOptions.fontSize.slice(0, panelOptions.fontSize.length - 1), 10);
fontSize = fontSize && fontSize !== 100 ? fontSize : null;
const alertListClass = classNames('alert-rule-list', { [`font-size--${fontSize}`]: fontSize });
const alertListClass = cx('alert-rule-list', { [`font-size--${fontSize}`]: !!fontSize });
return (
<div className="triggers-panel-container" key="alertListContainer">
@@ -117,7 +117,7 @@ class PaginationControl extends PureComponent<PaginationControlProps> {
const pageLinks = [];
for (let i = startPage; i < endPage; i++) {
const pageLinkClass = classNames('triggers-panel-page-link', 'pointer', { active: i === pageIndex });
const pageLinkClass = cx('triggers-panel-page-link', 'pointer', { active: i === pageIndex });
const value = i + 1;
const pageLinkElem = (
<li key={value.toString()}>

Some files were not shown because too many files have changed in this diff Show More