Compare commits

...
57 Commits
Author SHA1 Message Date
Bill Oley 8f86b20c02 Release version 2.0.0 2024-01-17 10:42:09 -05:00
Bill Oley a3620a3f24 Fixes for intermittent test failures, version to 2.0.0-SNAPSHOT 2024-01-17 10:42:09 -05:00
Bill Oley 9c99e74958 Use InMemoryAccumulo instead of MiniAccumulo, test fixes 2024-01-17 10:42:09 -05:00
Bill Oley 91ec36e819 Changes to support accumulo2 2024-01-17 10:42:08 -05:00
Bill Oley 9ad1b18b74 Delete grafana-auth module 2024-01-17 10:42:08 -05:00
Bill Oley 82c45d4dd4 Bump version to 1.3.7-SNAPSHOT 2023-10-13 10:28:19 -04:00
Bill Oley a0e47d0b48 Release version 1.3.6 2023-10-13 10:25:43 -04:00
dependabot[bot] d3dc324d84 Bump golang.org/x/net from 0.7.0 to 0.17.0 in /grafana/timely-app (#246)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.7.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.7.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-13 10:18:12 -04:00
Bill Oley 4871b3a4a9 Update dependencies, protect against NPE in AuthCache, AuthorizationsUtil 2023-10-13 10:02:33 -04:00
dependabot[bot] 8d5d5eeca8 Bump terser from 4.8.0 to 4.8.1 in /grafana/timely-app (#235)
Bumps [terser](https://github.com/terser/terser) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 14:26:51 -04:00
dependabot[bot] a006a44372 Bump decode-uri-component from 0.2.0 to 0.2.2 in /grafana/timely-app (#240)
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 14:26:07 -04:00
dependabot[bot] 6cfcdc1030 Bump golang.org/x/net in /grafana/timely-app (#241)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20210614182718-04defd469f4e to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/commits/v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 14:25:46 -04:00
dependabot[bot] 4eb7ceff8c Bump semver from 5.7.1 to 5.7.2 in /grafana/timely-app (#244)
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 14:25:13 -04:00
dependabot[bot] 6ad8da2b99 Bump word-wrap from 1.2.3 to 1.2.4 in /grafana/timely-app (#245)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-11 14:24:12 -04:00
dependabot[bot] 7f56a36906 Bump guava from 29.0-jre to 32.0.0-jre (#243)
Bumps [guava](https://github.com/google/guava) from 29.0-jre to 32.0.0-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-15 12:53:29 -04:00
Christopher Tubbs 1443fdceb9 Bump formatter and impsort plugins for newer Maven 2023-06-07 11:01:29 -04:00
Christopher Tubbs 3cff14eb03 Bump NPM/Yarn deps
* This avoids warnings about CVEs from GitHub in the referenced
  dependencies
* This required relaxing the node version constraint, since I didn't
  have version 12, only 16
2022-04-11 15:49:13 -04:00
dependabot[bot] 8fa5b56e62 Bump hadoop-common from 2.7.7 to 2.10.1 (#230)
Bumps hadoop-common from 2.7.7 to 2.10.1.

---
updated-dependencies:
- dependency-name: org.apache.hadoop:hadoop-common
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 14:22:59 -04:00
dependabot[bot] b2f2cef834 Bump follow-redirects from 1.14.1 to 1.14.8 in /grafana/timely-app (#232)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.1 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.1...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 14:22:18 -04:00
dependabot[bot] c6a2988083 Bump accumulo-core from 1.9.3 to 1.10.1 (#231)
Bumps [accumulo-core](https://github.com/apache/accumulo) from 1.9.3 to 1.10.1.
- [Release notes](https://github.com/apache/accumulo/releases)
- [Commits](https://github.com/apache/accumulo/compare/rel/1.9.3...rel/1.10.1)

---
updated-dependencies:
- dependency-name: org.apache.accumulo:accumulo-core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 14:21:50 -04:00
Bill Oley d54817cc9a Bump version to 1.3.6-SNAPSHOT 2022-01-07 14:43:04 -05:00
Bill Oley c4ee035584 Release version 1.3.5 2022-01-07 14:40:06 -05:00
Chromico Rek d4bfc1a3aa Update log4j to 2.17.1 to address CVE-2021-44832 (#227) 2021-12-30 13:50:34 -05:00
Chromico Rek fb315148a1 Update log4j to 2.17 to address CVE-2021-45105. (#226) 2021-12-20 10:44:47 -05:00
dependabot[bot] e8ae575086 Bump @grafana/data from 8.2.2 to 8.2.3 in /grafana/timely-app (#222)
Bumps [@grafana/data](https://github.com/grafana/grafana/tree/HEAD/packages/grafana-data) from 8.2.2 to 8.2.3.
- [Release notes](https://github.com/grafana/grafana/releases)
- [Changelog](https://github.com/grafana/grafana/blob/main/CHANGELOG.md)
- [Commits](https://github.com/grafana/grafana/commits/v8.2.3/packages/grafana-data)

---
updated-dependencies:
- dependency-name: "@grafana/data"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-15 16:59:06 -05:00
Christopher Tubbs da0146c741 Bump log4j and other cleanup
* Update log4j2 to 2.16.0 to address CVEs
* Update impsort and sortpom plugins
* Update spotbugs plugin to build on newer JDKs and suppress common
  minor warnings from that
* Fix a few minor warnings from spotbugs that are easy: remove hamcrest
  matcher, fix null checks that are always or never null
* Suppress module-info.class from shaded jars
2021-12-15 16:53:24 -05:00
Bill Oley 882b4e2587 Bump version to 1.3.5-SNAPSHOT 2021-11-01 10:17:49 -04:00
Bill Oley 8048862f2c Release version 1.3.4 2021-11-01 10:15:01 -04:00
Bill Oley c2f00c3d19 Convert line endings in pom files from dos->unix 2021-11-01 10:11:06 -04:00
Bill Oley 61b1a245e2 Bump version to 1.3.4-SNAPSHOT 2021-10-26 16:07:30 -04:00
Bill Oley a3c33115c4 Release version 1.3.3 2021-10-26 15:57:25 -04:00
Bill Oley bed1ceb9ee Remove yarn-error.log and add to .gitignore 2021-10-26 15:56:12 -04:00
Bill Oley 06e2699a44 Update to [email protected], [email protected], [email protected] 2021-10-26 14:59:25 -04:00
Bill Oley d09faaa087 Correct log message formatting 2021-10-22 14:21:49 -04:00
dependabot[bot] 088f1a5cab Bump jsoup from 1.11.3 to 1.14.2 (#216)
Bumps [jsoup](https://github.com/jhy/jsoup) from 1.11.3 to 1.14.2.
- [Release notes](https://github.com/jhy/jsoup/releases)
- [Changelog](https://github.com/jhy/jsoup/blob/master/CHANGES)
- [Commits](https://github.com/jhy/jsoup/compare/jsoup-1.11.3...jsoup-1.14.2)

---
updated-dependencies:
- dependency-name: org.jsoup:jsoup
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-22 13:47:11 -04:00
dependabot[bot] cf6d4ada3e Bump guava from 27.1-jre to 29.0-jre (#214)
Bumps [guava](https://github.com/google/guava) from 27.1-jre to 29.0-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-22 13:46:44 -04:00
Bill Oley e464a8c9e0 fixes #217 - Improve ageoff iterator remove/add logic in DataStoreImpl (#218)
* fixes #217 - Improve ageoff iterator remove/add logic in DataStoreImpl

* fixes #217 - Use curator LeaderLatch to elect a leader server which will remove/add the age off iterators
2021-10-22 13:13:00 -04:00
Bill Oley 8e4e61c373 fixes #219 Create scripts to help with running and testing multiple instances of server and balancer 2021-10-22 13:11:41 -04:00
dependabot[bot] 729dca23ba Bump httpclient from 4.5.6 to 4.5.13 (#215)
Bumps httpclient from 4.5.6 to 4.5.13.

---
updated-dependencies:
- dependency-name: org.apache.httpcomponents:httpclient
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-03 23:49:36 -04:00
Bill Oley 104d20ad1b Bump version to 1.3.3-SNAPSHOT 2020-11-06 13:30:04 -05:00
Bill Oley f0f005f8fa Release version 1.3.2 2020-11-06 13:23:36 -05:00
Bill Oley 8593218b89 Logging fixes 2020-11-06 12:24:22 -05:00
Bill Oley cbfe6a439f closes #213 Release reference counted netty objects to avoid memory errors 2020-11-06 11:50:24 -05:00
Bill Oley 455616d568 closes #213 Release reference counted netty objects to avoid memory errors 2020-11-05 14:17:01 -05:00
Bill Oley 9d3172cc75 Close objects when TcpClient has problem connecting to Timely 2020-11-04 16:06:08 -05:00
Bill Oley 7aa7b0da2a Remove entries from metricMap when metric is no longer cached on a particular server 2020-11-04 16:04:52 -05:00
Bill Oley 6c61861d83 Fix NPE in BalancedMetricResolver.rebalance where a metric exists in metricMap but not in metricToHostMap 2020-10-29 16:49:55 -04:00
Bill Oley 91882ba363 closes #212 Use writeLock for DataStoreCache.ageOffGorillaStores to avoid ConcurrentModificationException 2020-10-28 15:58:33 -04:00
Bill Oley ed61b5f305 Fix css inconsistent rendering in grafana datasource QueryEditor, remove overridden/unusd css 2020-10-27 14:10:58 -04:00
Bill Oley a083c2d632 Fix oauth issues - intersect TimelyUser auths with Accumulo auths when creating from oauthToken, allow X.509 (PEM) jwt signature check key, increase size of httpHeader max size 2020-10-23 14:41:46 -04:00
Jonathan SteinandJonathan Stein 2891794174 Fixing Nondeterministic Tests (#211)
* Fix MetricAdapterTest and QueryResponseTest flakiness

* change MetricAdapterTest and QueryResponseTest flakiness fix by defining Json key order

* Removed .swp file

* Fix SearchLookupResponse testResponse1

* Fixed flaky AuthCacheTest

Co-authored-by: Jonathan Stein <[email protected]>
2020-10-19 14:01:17 -04:00
Bill Oley c99b2471cf Bump version to 1.3.2-SNAPSHOT 2020-10-14 14:58:07 -04:00
Bill Oley bb479a58d7 Release version 1.3.1 2020-10-14 14:54:59 -04:00
Bill Oley ff37d40801 datasource logging fix, combine datasource golang code for readability 2020-10-14 14:46:09 -04:00
Bill Oley a7d980975e closes #210 Only reload cert and CA when changed
Only reload cert and CA when changed
2020-10-14 13:12:11 -04:00
dependabot[bot] 30f5a0c1b2 Bump junit from 4.12 to 4.13.1 (#209)
Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-10-13 00:54:58 -04:00
Bill Oley 2f9e6ca2d7 Bump version to 1.3.1-SNAPSHOT 2020-09-25 13:04:54 -04:00
202 changed files with 112202 additions and 203180 deletions

No files matched your search

+1
View File
@@ -7,4 +7,5 @@ target/
logs/
server/pki/
client/src/main/python/setup.py
grafana/timely-app/yarn-error.log
+15 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>timely-analytics</artifactId>
<!--
@@ -169,6 +169,12 @@
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
<filter>
<artifact>org.apache.flink:*</artifact>
<excludes>
@@ -246,6 +252,14 @@
<artifactSet>
<excludes combine.self="override" />
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
+8
View File
@@ -15,4 +15,12 @@
<Method name="getMetrics" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
</FindBugsFilter>
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
if [[ `uname` == "Darwin" ]]; then
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
else
THIS_SCRIPT=`readlink -f $0`
fi
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BIN_DIR=${BASE_DIR}/bin
CONF_DIR=${BASE_DIR}/conf
. ${BIN_DIR}/timely-balancer-env.sh
HOST_IP=$(hostname -I | awk '{print $1}')
HOST=$(hostname -s)
HOST_FQDN=$(hostname -f)
for i in $(seq 1 $NUM_PROFILES); do
if [ "$NUM_PROFILES" -eq "1" ]; then
FILENAME=timely-balancer.yml
else
FILENAME=timely-balancer-${i}.yml
fi
echo "creating configuration file ${CONF_DIR}/${FILENAME}"
cp ${CONF_DIR}/timely-balancer-template.yml ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST}/${HOST}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST_FQDN}/${HOST_FQDN}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${HOST_IP}/${HOST_IP}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${ZOOKEEPERS}/${ZOOKEEPERS}/g" ${CONF_DIR}/${FILENAME}
MULTIPLE=$(($i - 1))
TCP_PORT=$(($TCP_PORT_START + $MULTIPLE * $PORT_INCREMENT))
sed -i "s/\${TCP_PORT}/${TCP_PORT}/g" ${CONF_DIR}/${FILENAME}
HTTP_PORT=$(($HTTP_PORT_START + $MULTIPLE * $PORT_INCREMENT))
sed -i "s/\${HTTP_PORT}/${HTTP_PORT}/g" ${CONF_DIR}/${FILENAME}
WEBSOCKET_PORT=$(($WEBSOCKET_PORT_START + $MULTIPLE * $PORT_INCREMENT))
sed -i "s/\${WEBSOCKET_PORT}/${WEBSOCKET_PORT}/g" ${CONF_DIR}/${FILENAME}
UDP_PORT=$(($UDP_PORT_START + $MULTIPLE * $PORT_INCREMENT))
sed -i "s/\${UDP_PORT}/${UDP_PORT}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${INSTANCE}/${i}/g" ${CONF_DIR}/${FILENAME}
sed -i "s#\${SERVER_CERTIFICATE_FILE}#${SERVER_CERTIFICATE_FILE}#g" ${CONF_DIR}/${FILENAME}
sed -i "s#\${SERVER_KEY_FILE}#${SERVER_KEY_FILE}#g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${SERVER_KEY_PASSWORD}/${SERVER_KEY_PASSWORD}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${SERVER_USE_GENERATED_KEYPAIR}/${SERVER_USE_GENERATED_KEYPAIR}/g" ${CONF_DIR}/${FILENAME}
sed -i "s#\${CLIENT_KEY_FILE}#${CLIENT_KEY_FILE}#g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${CLIENT_KEY_TYPE}/${CLIENT_KEY_TYPE}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${CLIENT_KEY_PASSWORD}/${CLIENT_KEY_PASSWORD}/g" ${CONF_DIR}/${FILENAME}
sed -i "s#\${TRUST_STORE_PEM}#${TRUST_STORE_PEM}#g" ${CONF_DIR}/${FILENAME}
sed -i "s#\${TRUST_STORE_JKS}#${TRUST_STORE_JKS}#g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${TRUST_STORE_PASSWORD}/${TRUST_STORE_PASSWORD}/g" ${CONF_DIR}/${FILENAME}
done
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
if [[ `uname` == "Darwin" ]]; then
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
else
THIS_SCRIPT=`readlink -f $0`
fi
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BIN_DIR=${BASE_DIR}/bin
. ${BIN_DIR}/timely-balancer-env.sh
if [ "$NUM_PROFILES" -eq "1" ]; then
echo ${BIN_DIR}/timely-balancer.sh
${BIN_DIR}/timely-balancer.sh
else
for i in $(seq 1 $NUM_PROFILES); do
echo ${BIN_DIR}/timely-balancer.sh $i
${BIN_DIR}/timely-balancer.sh $i
done
fi
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
pkill -9 -f timely.balancer.Balancer
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
NUM_PROFILES=1
ZOOKEEPERS=localhost:2181
TCP_PORT_START=4242
HTTP_PORT_START=4243
WEBSOCKET_PORT_START=4244
UDP_PORT_START=4245
PORT_INCREMENT=100
SERVER_CERTIFICATE_FILE=
SERVER_KEY_FILE=
SERVER_KEY_PASSWORD=
SERVER_USE_GENERATED_KEYPAIR=true
CLIENT_KEY_FILE=
CLIENT_KEY_TYPE=pkcs12
CLIENT_KEY_PASSWORD=
TRUST_STORE_PEM=
TRUST_STORE_JKS=
TRUST_STORE_PASSWORD=
+54 -27
View File
@@ -9,34 +9,61 @@ else
fi
THIS_DIR="${THIS_SCRIPT%/*}"
NATIVE_DIR="${THIS_DIR}/META-INF/native"
BASE_DIR=${THIS_DIR}/..
TMP_DIR="${BASE_DIR}/tmp"
CONF_DIR="${BASE_DIR}/conf"
LIB_DIR="${BASE_DIR}/lib"
NUM_SERVER_THREADS=4
if [[ -e ${TMP_DIR} ]]; then
rm -rf ${TMP_DIR}
if [ -n "$1" ]; then
export PROFILE_NUM=$1
PROFILE_ARG="--spring.profiles.active=${PROFILE_NUM}"
PID=`jps -m | grep timely.balancer.Balancer | grep "spring.profiles.active=${PROFILE_NUM}" | awk '{print $1}'`
else
export PROFILE_NUM=""
PID=`jps -m | grep timely.balancer.Balancer | awk '{print $1}'`
fi
mkdir ${TMP_DIR}
if [[ -e ${NATIVE_DIR} ]]; then
rm -rf ${NATIVE_DIR}
if [ "$PID" == "" ]; then
NATIVE_DIR="${THIS_DIR}/META-INF/native"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
TMP_DIR="${BASE_DIR}/tmp"
CONF_DIR="${BASE_DIR}/conf"
LIB_DIR="${BASE_DIR}/lib"
export LOG_DIR="${BASE_DIR}/logs"
NUM_SERVER_THREADS=4
if [[ -e ${TMP_DIR} ]]; then
rm -rf ${TMP_DIR}
fi
mkdir ${TMP_DIR}
if [[ -e ${NATIVE_DIR} ]]; then
rm -rf ${NATIVE_DIR}
fi
mkdir -p ${NATIVE_DIR}
if [[ ! -e ${LOG_DIR} ]]; then
mkdir ${LOG_DIR}
fi
pushd ${BASE_DIR}/bin
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
popd
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} -Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
JVM_ARGS="${JVM_ARGS} -Xmx2G -Xms2G -XX:NewSize=1G -XX:MaxNewSize=1G"
JVM_ARGS="${JVM_ARGS} -XX:+UseCompressedOops -XX:+UseNUMA -Djava.net.preferIPv4Stack=true"
JVM_ARGS="${JVM_ARGS} -XX:+UseG1GC -XX:MaxGCPauseMillis=4000 -XX:ParallelGCThreads=20 -XX:+UseStringDeduplication"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.balancer.Balancer --spring.config.name=timely-balancer ${PROFILE_ARG}"
nohup $JAVA_HOME/bin/java ${JVM_ARGS} timely.balancer.Balancer --spring.config.name=timely-balancer ${PROFILE_ARG} >> ${LOG_DIR}/timely-balancer${PROFILE_NUM}-startup.log 2>&1 &
else
if [ "$PROFILE_NUM" == ""]; then
echo "timely-balancer already running with pid ${PID}"
else
echo "timely-balancer ${PROFILE_NUM} already running with pid ${PID}"
fi
fi
mkdir -p ${NATIVE_DIR}
pushd ${BASE_DIR}/bin
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
popd
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} -Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
#JVM_ARGS="${JVM_ARGS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.balancer.Balancer --spring.config.name=timely --spring.profiles.active=balancer"
$JAVA_HOME/bin/java ${JVM_ARGS} timely.balancer.Balancer --spring.config.name=timely --spring.profiles.active=balancer
+5 -11
View File
@@ -5,25 +5,19 @@
<Property name="LOG_PATTERN">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%wEx</Property>
</Properties>
<Appenders>
<RollingRandomAccessFile name="Rolling" fileName="/srv/logs/timely/timely-balancer.log"
filePattern="/srv/logs/timely/$${date:yyyy-MM}/timely-balancer-%d{MM-dd-yyyy}-%i.log.gz">
<RollingRandomAccessFile name="Rolling" fileName="${env:LOG_DIR}/timely-balancer${env:PROFILE_NUM}.log"
filePattern="${env:LOG_DIR}/$${date:yyyy-MM}/timely-balancer${env:PROFILE_NUM}-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1024 MB" />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingRandomAccessFile>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace" includeLocation="false">
<AppenderRef ref="Console" level="warn" />
<AppenderRef ref="Rolling" level="trace" />
<Root level="warn" includeLocation="false">
<AppenderRef ref="Rolling"/>
</Root>
<Logger name="timely" additivity="false">
<AppenderRef ref="Console" level="debug" />
</Logger>
<Logger name="timely" level="debug"/>
</Loggers>
</Configuration>
+134
View File
@@ -0,0 +1,134 @@
timely-balancer:
zooKeeper:
servers: ${ZOOKEEPERS}
timeout: 30s
checkServerHealthInterval: 10000
serverFailuresBeforeDown: 6
serverSuccessesBeforeUp: 1
assignmentFile: /timely/balancer/assignments.csv
security:
session-max-age: 86400
cache-expiration-minutes: 60
cache-refresh-minutes: 5
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
serverSsl:
certificate-file: ${SERVER_CERTIFICATE_FILE}
key-file: ${SERVER_KEY_FILE}
key-password: ${SERVER_KEY_PASSWORD}
use-generated-keypair: ${SERVER_USE_GENERATED_KEYPAIR}
trust-store-file: ${TRUST_STORE_PEM}
use-openssl: true
#use-ciphers:
clientSsl:
keyFile: ${CLIENT_KEY_FILE}
keyType: ${CLIENT_KEY_TYPE}
keyPassword: ${CLIENT_KEY_PASSWORD}
trustStoreFile: ${TRUST_STORE_JKS}
trustStoreType: jks
trustStorePassword: ${TRUST_STORE_PASSWORD}
jwtCheckKeyStore:
jwtCheckKeyType:
jwtCheckKeyPassword:
cache:
enabled: false
metric-age-off-hours:
default: 26
nonCachedMetrics:
server:
ip: ${HOST_IP}
tcpPort: ${TCP_PORT}
numTcpPools: 1
tcpBufferSize: 100
tcpClientPool:
minIdlePerKey: 0
maxIdlePerKey: 40
maxTotalPerKey: 40
maxTotal: -1
lifo: true
fairness: false
maxWaitMillis: -1
minEvictableIdleTimeMillis: 1800000
evictorShutdownTimeoutMillis: 10000
softMinEvictableIdleTimeMillis: -1
numTestsPerEvictionRun: 3
timeBetweenEvictionRunsMillis: -1
blockWhenExhausted: true
jmxEnabled: true
testOnBorrow: false
testOnReturn: false
udpPort: ${UDP_PORT}
udpClientPool:
minIdlePerKey: 0
maxIdlePerKey: 40
maxTotalPerKey: 40
maxTotal: -1
lifo: true
fairness: false
maxWaitMillis: -1
minEvictableIdleTimeMillis: 1800000
evictorShutdownTimeoutMillis: 10000
softMinEvictableIdleTimeMillis: -1
numTestsPerEvictionRun: 3
timeBetweenEvictionRunsMillis: -1
blockWhenExhausted: true
jmxEnabled: true
testOnBorrow: false
testOnReturn: false
http:
host: ${HOST}
ip: ${HOST_IP}
port: ${HTTP_PORT}
redirect-path: /secure-me
strict-transport-max-age: 608400
cors:
allow-any-origin: false
allow-null-origin: false
allow-credentials: true
allowed-origins:
allowed-methods: DELETE,GET,HEAD,OPTIONS,PUT,POST
allowed-headers: content-type
httpClientPool:
minIdlePerKey: 0
maxIdlePerKey: 40
maxTotalPerKey: 40
maxTotal: -1
lifo: true
fairness: false
maxWaitMillis: -1
minEvictableIdleTimeMillis: 1800000
evictorShutdownTimeoutMillis: 10000
softMinEvictableIdleTimeMillis: -1
numTestsPerEvictionRun: 3
timeBetweenEvictionRunsMillis: -1
blockWhenExhausted: true
jmxEnabled: true
testOnBorrow: false
testOnReturn: false
websocket:
ip: ${HOST_IP}
port: ${WEBSOCKET_PORT}
timeout: 60
subscription-lag: 120
scanner-batch-size: 10000
flush-interval-seconds: 30
scanner-read-ahead: 1
subscription-batch-size: 5000
incomingBufferSize: 50000000
wsClientPool:
minIdlePerKey: 0
maxIdlePerKey: 40
maxTotalPerKey: 40
maxTotal: -1
lifo: true
fairness: false
maxWaitMillis: -1
minEvictableIdleTimeMillis: 1800000
evictorShutdownTimeoutMillis: 10000
softMinEvictableIdleTimeMillis: -1
numTestsPerEvictionRun: 3
timeBetweenEvictionRunsMillis: -1
blockWhenExhausted: true
jmxEnabled: true
testOnBorrow: false
testOnReturn: false
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>timely-balancer</artifactId>
<dependencies>
@@ -1,5 +1,6 @@
package timely.balancer;
import static org.apache.accumulo.core.conf.ConfigurationTypeHelper.getTimeInMillis;
import static timely.Server.SERVICE_DISCOVERY_PATH;
import static timely.store.cache.DataStoreCache.NON_CACHED_METRICS;
import static timely.store.cache.DataStoreCache.NON_CACHED_METRICS_LOCK_PATH;
@@ -57,7 +58,6 @@ import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.NettyRuntime;
import io.netty.util.internal.SystemPropertyUtil;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -378,15 +378,14 @@ public class Balancer {
// start curator framework
RetryPolicy retryPolicy = new RetryForever(1000);
int timeout = Long.valueOf(AccumuloConfiguration.getTimeInMillis(balancerConfig.getZooKeeper().getTimeout()))
.intValue();
int timeout = Long.valueOf(getTimeInMillis(balancerConfig.getZooKeeper().getTimeout())).intValue();
curatorFramework = CuratorFrameworkFactory.newClient(balancerConfig.getZooKeeper().getServers(), timeout, 10000,
retryPolicy);
curatorFramework.start();
ensureZkPaths(curatorFramework, zkPaths);
AuthCache.configure(balancerConfig.getSecurity());
JWTTokenHandler.init(balancerConfig.getSecurity());
JWTTokenHandler.init(balancerConfig.getSecurity(), null);
final boolean useEpoll = useEpoll();
Class<? extends ServerSocketChannel> channelClass;
Class<? extends Channel> datagramChannelClass;
@@ -529,7 +528,7 @@ public class Balancer {
ch.pipeline().addLast("ssl", new NonSslRedirectHandler(balancerConfig.getHttp(), sslCtx));
ch.pipeline().addLast("encoder", new HttpResponseEncoder());
ch.pipeline().addLast("decoder", new HttpRequestDecoder());
ch.pipeline().addLast("decoder", new HttpRequestDecoder(4096, 32768, 8192, true, 128));
ch.pipeline().addLast("compressor", new HttpContentCompressor());
ch.pipeline().addLast("decompressor", new HttpContentDecompressor());
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
@@ -142,7 +142,7 @@ public class HttpRelayHandler extends SimpleChannelInboundHandler<HttpRequest> i
e.getMessage(), e.getLocalizedMessage(), e));
return;
} finally {
if (request != null && request instanceof AutoCloseable) {
if (request != null) {
ReferenceCountUtil.release(request);
}
}
@@ -88,7 +88,7 @@ public class WsRelayHandler extends SimpleChannelInboundHandler<SubscriptionRequ
if (metricToClientMap != null) {
synchronized (metricToClientMap) {
// close all clients for this subscriptionId
LOG.info("Channel closed, closing subscriptions for subscriptionId:%s",
LOG.debug("Channel closed, closing subscriptions for subscriptionId:{}",
currentSubscriptionId);
for (Map.Entry<String, WsClientHolder> entry : metricToClientMap.entrySet()) {
entry.getValue().close(wsClientPool);
@@ -108,7 +108,7 @@ public class WsRelayHandler extends SimpleChannelInboundHandler<SubscriptionRequ
if (origContext == null) {
// send error because user never sent a CreateSubscription
// and we have nowhere to send the results
LOG.info("ChannelHandlerContext not found for subscriptionId:%s - createSubscription not called?",
LOG.info("ChannelHandlerContext not found for subscriptionId:{} - createSubscription not called?",
subscriptionId);
sendErrorResponse(ctx, HttpResponseStatus.BAD_REQUEST,
new IllegalArgumentException("Must call create first"));
@@ -162,7 +162,7 @@ public class WsRelayHandler extends SimpleChannelInboundHandler<SubscriptionRequ
if (hostClientHolder != null) {
hostClientHolder.getClient().removeSubscription(metric);
} else {
LOG.info("client not found for subscriptionId:%s metric:%s", subscriptionId, metric);
LOG.info("client not found for subscriptionId:{} metric:{}", subscriptionId, metric);
}
}
}
@@ -31,8 +31,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicValue;
@@ -550,7 +550,8 @@ public class BalancedMetricResolver implements MetricResolver {
// sort metrics by rate
Map<Double, String> rateSortedMetrics = new TreeMap<>(Collections.reverseOrder());
for (Map.Entry<String, ArrivalRate> e : tempMetricMap.entrySet()) {
if (metricToHostMap.get(e.getKey()).equals(h)) {
TimelyBalancedHost tbh = metricToHostMap.get(e.getKey());
if (tbh != null && tbh.equals(h)) {
rateSortedMetrics.put(e.getValue().getRate(), e.getKey());
}
}
@@ -737,18 +738,26 @@ public class BalancedMetricResolver implements MetricResolver {
boolean chooseMetricSpecificHost;
try {
chooseMetricSpecificHost = shouldCache(metric) ? true : false;
ArrivalRate rate = metricMap.get(metric);
if ((chooseMetricSpecificHost && rate == null) || (!chooseMetricSpecificHost && rate != null)) {
if (!balancerLock.isWriteLockedByCurrentThread()) {
balancerLock.readLock().unlock();
balancerLock.writeLock().lock();
}
}
if (chooseMetricSpecificHost) {
ArrivalRate rate = metricMap.get(metric);
if (rate == null) {
rate = new ArrivalRate(arrivalRateExecutor);
if (!balancerLock.isWriteLockedByCurrentThread()) {
balancerLock.readLock().unlock();
balancerLock.writeLock().lock();
}
// already write locked above
metricMap.put(metric, rate);
}
rate.arrived();
} else {
if (rate != null) {
// already write locked above
metricMap.remove(metric);
}
metric = null;
}
@@ -964,6 +973,9 @@ public class BalancedMetricResolver implements MetricResolver {
} finally {
nonCachedMetricsLocalLock.readLock().unlock();
}
// remove metric from metricMap (ArrivalRate) if not being cached
metricMap.entrySet().removeIf(e -> !metricToHostMap.containsKey(e.getKey()));
assignmentsLastUpdatedLocal.set(assignmentsLastUpdatedInHdfs.get().postValue());
LOG.info("Read {} assignments from hdfs lastHdfsUpdate = lastLocalUpdate ({})", metricToHostMap.size(),
new Date(assignmentsLastUpdatedLocal.get()));
@@ -1026,6 +1038,8 @@ public class BalancedMetricResolver implements MetricResolver {
}
LOG.debug("Wrote {} assignments to hdfs lastHdfsUpdate = lastLocalUpdate ({})",
metricToHostMap.size(), new Date(assignmentsLastUpdatedLocal.get()));
// remove metric from metricMap (ArrivalRate) if not being cached
metricMap.entrySet().removeIf(e -> !metricToHostMap.containsKey(e.getKey()));
}
} finally {
nonCachedMetricsLocalLock.readLock().unlock();
+8
View File
@@ -10,4 +10,12 @@
<Method name="getBuf" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
</FindBugsFilter>
+2 -2
View File
@@ -4,13 +4,13 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>timely-client</artifactId>
<properties>
<!-- PEP 440 compliant version gets substituted into src/main/python/template/setup.py -->
<!-- use .dev0 instead of -SNAPSHOT -->
<python.client.version>1.3.0</python.client.version>
<python.client.version>2.0.0</python.client.version>
</properties>
<dependencies>
<dependency>
@@ -2,12 +2,14 @@ package timely.api.response;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import timely.model.Metric;
import timely.model.Tag;
@JsonPropertyOrder({ "metric", "timestamp", "value", "tags", "subscriptionId", "complete" })
public class MetricResponse {
private String metric;
@@ -33,7 +33,7 @@ public class TcpClient implements AutoCloseable {
/**
* Opens a TCP connection to the specified host and port
*
*
* @throws IOException
* if an error occurs
*/
@@ -45,7 +45,7 @@ public class TcpClient implements AutoCloseable {
/**
* Write a metric to Timely
*
*
* @param metric
* newline terminated string representation of Timely metric
*/
@@ -69,7 +69,7 @@ public class TcpClient implements AutoCloseable {
/**
* Closes the tcp connection to Timely
*
*
* @throws IOException
* if an error occurs
*/
@@ -96,17 +96,42 @@ public class TcpClient implements AutoCloseable {
private synchronized int connect() {
if (null == sock || !sock.isConnected()) {
if (System.currentTimeMillis() > (connectTime + backoff)) {
OutputStreamWriter osw = null;
try {
connectTime = System.currentTimeMillis();
sock = new Socket(host, port);
out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
osw = new OutputStreamWriter(sock.getOutputStream());
out = new BufferedWriter(osw);
backoff = 2000;
LOG.trace("Connected to Timely at {}:{}", host, port);
} catch (IOException e) {
LOG.error("Error connecting to Timely at {}:" + host + ":" + port + ". Error: " + e.getMessage());
} catch (Exception e) {
LOG.error("Error connecting to Timely at {}:{} - {}", host, port, e.getMessage());
if (sock != null) {
try {
sock.close();
} catch (IOException e1) {
LOG.error(e1.getMessage());
} finally {
sock = null;
}
}
if (osw != null) {
try {
osw.close();
} catch (IOException e1) {
LOG.error(e1.getMessage());
}
}
if (out != null) {
try {
out.close();
} catch (IOException e1) {
LOG.error(e1.getMessage());
} finally {
out = null;
}
}
backoff = backoff * 2;
sock = null;
out = null;
LOG.info("Will retry connection in {} ms.", backoff);
return -1;
}
@@ -6,7 +6,6 @@ import java.util.Map;
import javax.websocket.CloseReason;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import org.slf4j.Logger;
@@ -19,12 +18,8 @@ public abstract class ClientHandler extends Endpoint {
@Override
public void onOpen(Session session, EndpointConfig config) {
LOG.info("Websocket session {} opened.", session.getId());
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
LOG.info("Message received on Websocket session {}: {}", session.getId(), message);
}
session.addMessageHandler(String.class, message -> {
LOG.info("Message received on Websocket session {}: {}", session.getId(), message);
});
}
@@ -6,7 +6,9 @@ import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Logger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A simple interface that objects can implement to return the object size.
@@ -46,7 +48,7 @@ public interface ObjectSizeOf {
public static class Sizer {
private static final Logger log = Logger.getLogger(Sizer.class.getCanonicalName());
private static final Logger LOG = LoggerFactory.getLogger(Sizer.class);
public static final short OBJECT_OVERHEAD = 8;
public static final short ARRAY_OVERHEAD = 12;
public static final short REFERENCE = 4;
@@ -150,7 +152,7 @@ public interface ObjectSizeOf {
}
}
} catch (Throwable t) {
log.warning("Unable to determine object size for " + o);
LOG.warn("Unable to determine object size for " + o, t);
}
if (debug) {
System.out.println(o.getClass().getCanonicalName() + "=" + size);
@@ -46,7 +46,7 @@ public class TagListParser implements Parser<List<Tag>>, Combiner<Collection<Tag
/**
* An alternative combiner for a map of string to string instead of a list of
* tags
*
*
* @return string representation
*/
public String combine(Map<String, String> tags) {
+12
View File
@@ -10,4 +10,16 @@
<!-- https://github.com/spotbugs/spotbugs/issues/756 -->
<Bug pattern="RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="MS_EXPOSE_REP" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<!-- these are probably avoidable, but needs further triage to fix -->
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
</FindBugsFilter>
+9 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>collectd-nsq-plugin</artifactId>
<dependencies>
@@ -34,6 +34,14 @@
<artifactSet>
<includes />
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
@@ -36,6 +36,7 @@ public class WriteNSQPlugin extends CollectDPluginParent
private String topic = "metrics#ephemeral";
private String endpoint = null;
private GenericObjectPool<CloseableHttpClient> clientPool = null;
private Random random = new Random();
// pool should be limited by the number of WriteThreads configured in
// collectd
@@ -88,11 +89,9 @@ public class WriteNSQPlugin extends CollectDPluginParent
if (client != null) {
clientPool.returnObject(client);
}
if (null != out) {
try {
out.close();
} catch (IOException e) {
}
try {
out.close();
} catch (IOException e) {
}
}
return 0;
@@ -141,7 +140,7 @@ public class WriteNSQPlugin extends CollectDPluginParent
if (hosts.length == 1) {
host = hosts[0];
} else {
host = hosts[new Random().nextInt(hosts.length)];
host = hosts[random.nextInt(hosts.length)];
}
break;
case "Port":
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>collectd-plugin-parent</artifactId>
<dependencies>
+9 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>collectd-timely-plugin</artifactId>
<dependencies>
@@ -51,6 +51,14 @@
<artifactSet>
<includes />
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>**/module-info.class</exclude>
</excludes>
</filter>
</filters>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>timely-common</artifactId>
<dependencies>
-42
View File
@@ -1,42 +0,0 @@
#!/bin/bash
if [[ `uname` == "Darwin" ]]; then
THIS_SCRIPT=`python -c 'import os,sys; print os.path.realpath(sys.argv[1])' $0`
TCNATIVE_SUFFIX="jnilib"
else
THIS_SCRIPT=`readlink -f $0`
TCNATIVE_SUFFIX="so"
fi
THIS_DIR="${THIS_SCRIPT%/*}"
NATIVE_DIR="${THIS_DIR}/META-INF/native"
BASE_DIR=${THIS_DIR}/..
TMP_DIR="${BASE_DIR}/tmp"
CONF_DIR="${BASE_DIR}/conf"
LIB_DIR="${BASE_DIR}/lib"
NUM_SERVER_THREADS=4
if [[ -e ${TMP_DIR} ]]; then
rm -rf ${TMP_DIR}
fi
mkdir ${TMP_DIR}
if [[ -e ${NATIVE_DIR} ]]; then
rm -rf ${NATIVE_DIR}
fi
mkdir -p ${NATIVE_DIR}
pushd ${BASE_DIR}/bin
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-tcnative-boringssl-static*.jar META-INF/native/libnetty_tcnative_linux_x86_64.${TCNATIVE_SUFFIX}
$JAVA_HOME/bin/jar xf ${LIB_DIR}/netty-all*.jar META-INF/native/libnetty_transport_native_epoll_x86_64.${TCNATIVE_SUFFIX}
popd
export CLASSPATH="${CONF_DIR}:${LIB_DIR}/*:${HADOOP_CONF_DIR}"
JVM_ARGS="-Xmx1G -Xms1G -Dio.netty.eventLoopThreads=${NUM_SERVER_THREADS} Dlog4j.configurationFile=${CONF_DIR}/log4j2-spring.xml"
JVM_ARGS="${JVM_ARGS} -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector"
JVM_ARGS="${JVM_ARGS} -Djava.library.path=${NATIVE_DIR}"
#JVM_ARGS="${JVM_ARGS} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.grafana.auth.GrafanaAuth --spring.config.name=grafana-auth"
$JAVA_HOME/bin/java ${JVM_ARGS} timely.grafana.auth.GrafanaAuth --spring.config.name=grafana-auth
-55
View File
@@ -1,55 +0,0 @@
grafana-auth:
grafana:
host: localhost
port: 3001
security:
session-max-age: 86400
cache-expiration-minutes: 60
cache-refresh-minutes: 5
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
serverSsl:
certificate-file:
key-file:
#key-password:
use-generated-keypair: true
trust-store-file:
use-openssl: true
#use-ciphers:
clientSsl:
keyFile:
keyType: pkcs12
#keyPassword:
trustStoreFile:
trustStoreType: jks
#trustStorePassword:
http:
host: localhost
ip: 127.0.0.1
port: 3000
redirect-path: /secure-me
strict-transport-max-age: 608400
cors:
allow-any-origin: false
allow-null-origin: false
allow-credentials: true
allowed-origins:
allowed-methods: DELETE,GET,HEAD,OPTIONS,PUT,POST
allowed-headers: content-type
httpClientPool:
minIdlePerKey: 0
maxIdlePerKey: 40
maxTotalPerKey: 40
maxTotal: -1
lifo: true
fairness: false
maxWaitMillis: -1
minEvictableIdleTimeMillis: 1800000
evictorShutdownTimeoutMillis: 10000
softMinEvictableIdleTimeMillis: -1
numTestsPerEvictionRun: 3
timeBetweenEvictionRunsMillis: -1
blockWhenExhausted: true
jmxEnabled: true
testOnBorrow: false
testOnReturn: false
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="60">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error" includeLocation="false">
<AppenderRef ref="Console" level="error" />
</Root>
</Loggers>
</Configuration>
-29
View File
@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="60">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_PATTERN">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%wEx</Property>
</Properties>
<Appenders>
<RollingRandomAccessFile name="Rolling" fileName="/srv/logs/timely/grafana-auth.log"
filePattern="/srv/logs/timely/$${date:yyyy-MM}/grafana-auth-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1024 MB" />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingRandomAccessFile>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace" includeLocation="false">
<AppenderRef ref="Console" level="warn" />
<AppenderRef ref="Rolling" level="trace" />
</Root>
<Logger name="timely" additivity="false">
<AppenderRef ref="Console" level="debug" />
</Logger>
</Loggers>
</Configuration>
-71
View File
@@ -1,71 +0,0 @@
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<beans:bean id="x509PrincipalExtractor" class="org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor">
<beans:property name="subjectDnRegex" value="CN=(.*?)(?:,|$)"/>
</beans:bean>
<beans:bean id="timelyUserDetailsService" class="timely.auth.UserDetailsService">
<beans:property name="users">
<util:list>
<beans:bean class="timely.auth.TimelyUser">
<beans:constructor-arg name="subjectDn">
<beans:value>CN=example.com</beans:value>
</beans:constructor-arg>
<beans:constructor-arg name="auths">
<util:list>
<beans:value>D</beans:value>
<beans:value>E</beans:value>
<beans:value>F</beans:value>
</util:list>
</beans:constructor-arg>
<beans:constructor-arg name="roles">
<util:list>
<beans:value>G</beans:value>
<beans:value>H</beans:value>
<beans:value>I</beans:value>
</util:list>
</beans:constructor-arg>
</beans:bean>
</util:list>
</beans:property>
</beans:bean>
<beans:bean id="x509AuthorizationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="timelyUserDetailsService" />
</beans:bean>
<user-service id="usernamePasswordService">
<user name="test" password="test1" authorities="A,B,C" />
</user-service>
<beans:bean id="noOpPasswordEncoder" class="org.springframework.security.crypto.password.NoOpPasswordEncoder"/>
<beans:bean id="UserNamePasswordAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="usernamePasswordService"/>
<beans:property name="passwordEncoder" ref="noOpPasswordEncoder"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<!-- X509 PreAuthenticated authorization provider -->
<authentication-provider ref="x509AuthorizationProvider"/>
<!-- Basic authorization provider, validates provided username and password -->
<authentication-provider ref="UserNamePasswordAuthenticationProvider" />
</authentication-manager>
<util:list id="requiredRoles" value-type="java.lang.String">
<beans:value></beans:value>
</util:list>
<util:list id="requiredAuths" value-type="java.lang.String">
<beans:value></beans:value>
</util:list>
</beans:beans>
-295
View File
@@ -1,295 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
</parent>
<artifactId>grafana-auth</artifactId>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
<dependency>
<groupId>io.github.lukehutch</groupId>
<artifactId>fast-classpath-scanner</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
</dependency>
<dependency>
<groupId>org.apache.accumulo</groupId>
<artifactId>accumulo-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.accumulo</groupId>
<artifactId>accumulo-minicluster</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-x-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<exclusions>
<exclusion>
<groupId>jdk.tools</groupId>
<artifactId>jdk.tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-minicluster</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-balancer</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-client</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-server</artifactId>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/dist/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<goals>
<goal>copy-dependencies</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<excludeArtifactIds>junit</excludeArtifactIds>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
<execution>
<id>unpack-native</id>
<goals>
<goal>unpack</goal>
</goals>
<phase>process-test-classes</phase>
<configuration>
<artifactItems>
<artifactItem>
<groupId>io.netty</groupId>
<artifactId>netty-tcnative-boringssl-static</artifactId>
<version>${version.netty-tcnative}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/native</outputDirectory>
<includes>**/*.so</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<goals>
<goal>add-source</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<sources>
<source>src/main/generated-java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<extensions>
<!-- Use os-maven-plugin to initialize the "os.detected" properties -->
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
</extension>
</extensions>
</build>
</project>
-55
View File
@@ -1,55 +0,0 @@
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>dist</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<outputDirectory></outputDirectory>
<includes>
<include>README*</include>
<include>LICENSE*</include>
<include>NOTICE*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>timely*.jar</include>
<include>grafana*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/lib</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/bin</directory>
<outputDirectory>bin</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/conf</directory>
<outputDirectory>conf</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.basedir}/src/main/resources/webapp</directory>
<outputDirectory>bin/webapp</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
@@ -1,322 +0,0 @@
package timely.grafana.auth;
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpContentCompressor;
import io.netty.handler.codec.http.HttpContentDecompressor;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.OpenSslServerContext;
import io.netty.handler.ssl.OpenSslServerSessionContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.internal.SystemPropertyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import timely.auth.AuthCache;
import timely.balancer.configuration.ClientSsl;
import timely.balancer.connection.http.HttpClientPool;
import timely.client.http.HttpClient;
import timely.configuration.ServerSsl;
import timely.grafana.auth.configuration.GrafanaAuthConfiguration;
import timely.grafana.auth.configuration.SpringBootstrap;
import timely.grafana.auth.netty.http.GrafanaRelayHandler;
import timely.grafana.auth.netty.http.GrafanaRequestDecoder;
import timely.netty.http.HttpStaticFileServerHandler;
import timely.netty.http.NonSslRedirectHandler;
import timely.netty.http.TimelyExceptionHandler;
import timely.netty.http.auth.X509LoginRequestHandler;
public class GrafanaAuth {
private static final Logger LOG = LoggerFactory.getLogger(GrafanaAuth.class);
private static final int EPOLL_MIN_MAJOR_VERSION = 2;
private static final int EPOLL_MIN_MINOR_VERSION = 6;
private static final int EPOLL_MIN_PATCH_VERSION = 32;
private static final String OS_NAME = "os.name";
private static final String OS_VERSION = "os.version";
protected static final CountDownLatch LATCH = new CountDownLatch(1);
static ConfigurableApplicationContext applicationContext;
private final GrafanaAuthConfiguration grafanaAuthConfig;
private EventLoopGroup httpWorkerGroup = null;
private EventLoopGroup httpBossGroup = null;
protected Channel httpChannelHandle = null;
protected volatile boolean shutdown = false;
public GrafanaAuth(GrafanaAuthConfiguration grafanaAuthConfig) throws Exception {
this.grafanaAuthConfig = grafanaAuthConfig;
}
protected static ConfigurableApplicationContext initializeContext(String[] args) {
SpringApplicationBuilder builder = new SpringApplicationBuilder(SpringBootstrap.class);
builder.web(WebApplicationType.NONE);
builder.registerShutdownHook(false);
return builder.run(args);
}
private void shutdownHook() {
final Runnable shutdownRunner = () -> {
if (!shutdown) {
shutdown();
}
};
final Thread hook = new Thread(shutdownRunner, "shutdown-hook-thread");
Runtime.getRuntime().addShutdownHook(hook);
}
public void shutdown() {
List<ChannelFuture> channelFutures = new ArrayList<>();
if (httpChannelHandle != null) {
LOG.info("Closing httpChannelHandle");
channelFutures.add(httpChannelHandle.close());
}
// wait for the channels to shutdown
channelFutures.forEach(f -> {
try {
f.get();
} catch (final Exception e) {
LOG.error("Channel:" + f.channel().config() + " -> " + e.getMessage(), e);
}
});
int quietPeriod = grafanaAuthConfig.getShutdownQuietPeriod();
List<Future<?>> groupFutures = new ArrayList<>();
if (httpBossGroup != null) {
LOG.info("Shutting down httpBossGroup");
groupFutures.add(httpBossGroup.shutdownGracefully(quietPeriod, 10, TimeUnit.SECONDS));
}
if (httpWorkerGroup != null) {
LOG.info("Shutting down httpWorkerGroup");
groupFutures.add(httpWorkerGroup.shutdownGracefully(quietPeriod, 10, TimeUnit.SECONDS));
}
groupFutures.parallelStream().forEach(f -> {
try {
f.get();
} catch (final Exception e) {
LOG.error("Group:" + f.toString() + " -> " + e.getMessage(), e);
}
});
if (applicationContext != null) {
LOG.info("Closing applicationContext");
applicationContext.close();
}
this.shutdown = true;
LOG.info("Server shut down.");
}
private static boolean useEpoll() {
// Should we just return true if this is Linux and if we get an error
// during Epoll
// setup handle it there?
final String os = SystemPropertyUtil.get(OS_NAME).toLowerCase().trim();
final String[] version = SystemPropertyUtil.get(OS_VERSION).toLowerCase().trim().split("\\.");
if (os.startsWith("linux") && version.length >= 3) {
final int major = Integer.parseInt(version[0]);
if (major > EPOLL_MIN_MAJOR_VERSION) {
return true;
} else if (major == EPOLL_MIN_MAJOR_VERSION) {
final int minor = Integer.parseInt(version[1]);
if (minor > EPOLL_MIN_MINOR_VERSION) {
return true;
} else if (minor == EPOLL_MIN_MINOR_VERSION) {
final int patch = Integer.parseInt(version[2].substring(0, 2));
return patch >= EPOLL_MIN_PATCH_VERSION;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
protected SslContext createSSLContext(GrafanaAuthConfiguration config) throws Exception {
ServerSsl sslCfg = config.getSecurity().getServerSsl();
Boolean generate = sslCfg.isUseGeneratedKeypair();
SslContextBuilder ssl;
if (generate) {
LOG.warn("Using generated self signed server certificate");
Date begin = new Date();
Date end = new Date(begin.getTime() + 86400000);
SelfSignedCertificate ssc = new SelfSignedCertificate("localhost", begin, end);
ssl = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey());
} else {
String cert = sslCfg.getCertificateFile();
String key = sslCfg.getKeyFile();
String keyPass = sslCfg.getKeyPassword();
if (null == cert || null == key) {
throw new IllegalArgumentException("Check your SSL properties, something is wrong.");
}
ssl = SslContextBuilder.forServer(new File(cert), new File(key), keyPass);
}
ssl.ciphers(sslCfg.getUseCiphers());
// Can't set to REQUIRE because the CORS pre-flight requests will fail.
ssl.clientAuth(ClientAuth.OPTIONAL);
Boolean useOpenSSL = sslCfg.isUseOpenssl();
if (useOpenSSL) {
ssl.sslProvider(SslProvider.OPENSSL);
} else {
ssl.sslProvider(SslProvider.JDK);
}
String trustStore = sslCfg.getTrustStoreFile();
if (null != trustStore) {
if (!trustStore.isEmpty()) {
ssl.trustManager(new File(trustStore));
}
}
return ssl.build();
}
protected SSLContext createSSLClientContext(GrafanaAuthConfiguration config) throws Exception {
ClientSsl ssl = config.getSecurity().getClientSsl();
return HttpClient.getSSLContext(ssl.getTrustStoreFile(), ssl.getTrustStoreType(), ssl.getTrustStorePassword(),
ssl.getKeyFile(), ssl.getKeyType(), ssl.getKeyPassword());
}
public void run() throws Exception {
AuthCache.configure(grafanaAuthConfig.getSecurity());
final boolean useEpoll = useEpoll();
Class<? extends ServerSocketChannel> channelClass;
if (useEpoll) {
httpWorkerGroup = new EpollEventLoopGroup();
httpBossGroup = new EpollEventLoopGroup();
channelClass = EpollServerSocketChannel.class;
} else {
httpWorkerGroup = new NioEventLoopGroup();
httpBossGroup = new NioEventLoopGroup();
channelClass = NioServerSocketChannel.class;
}
LOG.info("Using channel class {}", channelClass.getSimpleName());
final int httpPort = grafanaAuthConfig.getHttp().getPort();
final String httpIp = grafanaAuthConfig.getHttp().getIp();
SslContext sslCtx = createSSLContext(grafanaAuthConfig);
if (sslCtx instanceof OpenSslServerContext) {
OpenSslServerContext openssl = (OpenSslServerContext) sslCtx;
String application = "GrafanaAuth_" + httpPort;
OpenSslServerSessionContext opensslCtx = openssl.sessionContext();
opensslCtx.setSessionCacheEnabled(true);
opensslCtx.setSessionCacheSize(128);
opensslCtx.setSessionIdContext(application.getBytes(StandardCharsets.UTF_8));
opensslCtx.setSessionTimeout(grafanaAuthConfig.getSecurity().getSessionMaxAge());
}
SSLContext clientSSLContext = createSSLClientContext(grafanaAuthConfig);
final ServerBootstrap httpServer = new ServerBootstrap();
httpServer.group(httpBossGroup, httpWorkerGroup);
httpServer.channel(channelClass);
httpServer.handler(new LoggingHandler());
HttpClientPool httpClientPool = new HttpClientPool(grafanaAuthConfig.getSecurity(), grafanaAuthConfig.getHttp(),
clientSSLContext);
httpServer.childHandler(setupHttpChannel(grafanaAuthConfig, sslCtx, httpClientPool));
httpServer.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
httpServer.option(ChannelOption.SO_BACKLOG, 128);
httpServer.option(ChannelOption.SO_KEEPALIVE, true);
httpChannelHandle = httpServer.bind(httpIp, httpPort).sync().channel();
final String httpAddress = ((InetSocketAddress) httpChannelHandle.localAddress()).getAddress().getHostAddress();
shutdownHook();
LOG.info("Server started. Listening on {}:{} for HTTP traffic", httpAddress, httpPort);
}
public static void main(String[] args) throws Exception {
GrafanaAuth.applicationContext = GrafanaAuth.initializeContext(args);
GrafanaAuthConfiguration grafanaAuthConf = GrafanaAuth.applicationContext
.getBean(GrafanaAuthConfiguration.class);
GrafanaAuth grafanaAuth = new GrafanaAuth(grafanaAuthConf);
try {
grafanaAuth.run();
LATCH.await();
} catch (final InterruptedException e) {
LOG.info("Server shutting down.");
} catch (Exception e) {
LOG.error("Error running server.", e);
} finally {
try {
grafanaAuth.shutdown();
} catch (Exception e) {
System.exit(1);
}
}
}
protected ChannelHandler setupHttpChannel(GrafanaAuthConfiguration config, SslContext sslCtx,
HttpClientPool httpClientPool) {
return new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("ssl", new NonSslRedirectHandler(config.getHttp(), sslCtx));
ch.pipeline().addLast("encoder", new HttpResponseEncoder());
ch.pipeline().addLast("decoder", new HttpRequestDecoder());
ch.pipeline().addLast("compressor", new HttpContentCompressor());
ch.pipeline().addLast("decompressor", new HttpContentDecompressor());
// high maximum contentLength so that grafana snapshots can be delivered
// might not be necessary if inbound chunking (while proxying) is handled
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(2097152));
ch.pipeline().addLast("chunker", new ChunkedWriteHandler());
ch.pipeline().addLast("grafanaDecoder",
new GrafanaRequestDecoder(config.getSecurity(), config.getHttp()));
ch.pipeline().addLast("fileServer", new HttpStaticFileServerHandler());
ch.pipeline().addLast("login", new X509LoginRequestHandler(config.getSecurity(), config.getHttp()));
ch.pipeline().addLast("httpRelay", new GrafanaRelayHandler(config, httpClientPool));
ch.pipeline().addLast("error", new TimelyExceptionHandler()
.setIgnoreSslHandshakeErrors(config.getSecurity().getServerSsl().isUseGeneratedKeypair()));
}
};
}
}
@@ -1,32 +0,0 @@
package timely.grafana.auth.configuration;
public class Grafana {
private String host = "localhost";
private Integer port = 3000;
private String protocol = "http";
public void setHost(String host) {
this.host = host;
}
public String getHost() {
return host;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getPort() {
return port;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getProtocol() {
return protocol;
}
}
@@ -1,54 +0,0 @@
package timely.grafana.auth.configuration;
import javax.validation.Valid;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import timely.balancer.configuration.BalancerHttp;
import timely.balancer.configuration.BalancerSecurity;
@Validated
@Component
@ConfigurationProperties(prefix = "grafana-auth")
public class GrafanaAuthConfiguration {
@Valid
@NestedConfigurationProperty
private BalancerHttp http = new BalancerHttp();
@Valid
@NestedConfigurationProperty
private BalancerSecurity security = new BalancerSecurity();
@Valid
@NestedConfigurationProperty
private Grafana grafana = new Grafana();
private Integer shutdownQuietPeriod = 5;
public BalancerSecurity getSecurity() {
return security;
}
public BalancerHttp getHttp() {
return http;
}
public Grafana getGrafana() {
return grafana;
}
/**
* Time to wait (in seconds) for connections to finish and to make sure no new
* connections happen before shutting down Netty event loop groups.
*/
public int getShutdownQuietPeriod() {
return this.shutdownQuietPeriod;
}
public void setShutdownQuietPeriod(Integer quietPeriod) {
this.shutdownQuietPeriod = quietPeriod;
}
}
@@ -1,7 +0,0 @@
package timely.grafana.auth.configuration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackageClasses = { SpringBootstrap.class })
public class SpringBootstrap {
}
@@ -1,234 +0,0 @@
package timely.grafana.auth.netty.http;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Multimap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.ReferenceCountUtil;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
import timely.api.request.timeseries.HttpRequest;
import timely.api.response.TimelyException;
import timely.auth.TimelyPrincipal;
import timely.auth.TimelyUser;
import timely.auth.util.DnUtils;
import timely.auth.util.HttpHeaderUtils;
import timely.balancer.connection.TimelyBalancedHost;
import timely.balancer.connection.http.HttpClientPool;
import timely.grafana.auth.configuration.GrafanaAuthConfiguration;
import timely.grafana.request.GrafanaRequest;
import timely.netty.http.TimelyHttpHandler;
import timely.netty.http.auth.TimelyAuthenticationToken;
public class GrafanaRelayHandler extends SimpleChannelInboundHandler<HttpRequest> implements TimelyHttpHandler {
private static final Logger LOG = LoggerFactory.getLogger(GrafanaRelayHandler.class);
private final HttpClientPool httpClientPool;
private GrafanaAuthConfiguration config;
public GrafanaRelayHandler(GrafanaAuthConfiguration config, HttpClientPool httpClientPool) {
this.config = config;
this.httpClientPool = httpClientPool;
}
@Override
public void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception {
CloseableHttpClient client = null;
CloseableHttpResponse relayedResponse = null;
FullHttpRequest request = null;
GrafanaRequest grafanaRequest;
TimelyBalancedHost k = null;
String relayURI = null;
try {
try {
request = msg.getHttpRequest();
String originalURI = request.uri();
originalURI = encodeURI(originalURI);
if (msg instanceof GrafanaRequest) {
grafanaRequest = (GrafanaRequest) msg;
} else {
throw new UnsupportedOperationException("Request not supported");
}
TimelyAuthenticationToken token = grafanaRequest.getToken();
if (token == null) {
throw new IllegalStateException("No token on grafana request");
}
String protocol = config.getGrafana().getProtocol();
String host = config.getGrafana().getHost();
Integer port = config.getGrafana().getPort();
k = TimelyBalancedHost.of(host, -1, port, -1, -1, null);
client = httpClientPool.borrowObject(k);
Multimap<String, String> headers = HttpHeaderUtils.toMultimap(request.headers());
// If incoming user sets these headers, do not relay them
headers.removeAll("x-webauth-user");
headers.removeAll("x-webauth-name");
TimelyPrincipal principal = token.getTimelyPrincipal();
TimelyUser user = principal.getPrimaryUser();
String subjectDn = user.getDn().subjectDN();
String userName = DnUtils.getCommonName(subjectDn);
String loginName = DnUtils.getShortName(subjectDn);
headers.put("x-webauth-user", loginName);
headers.put("x-webauth-name", userName);
List<Header> relayedHeaderList = new ArrayList<>();
for (Map.Entry<String, String> h : headers.entries()) {
if (!h.getKey().equals(CONTENT_LENGTH.toString())) {
relayedHeaderList.add(new BasicHeader(h.getKey(), h.getValue()));
}
}
Header[] headerArray = new Header[relayedHeaderList.size()];
relayedHeaderList.toArray(headerArray);
relayURI = protocol + "://" + host + ":" + port + originalURI;
if (request.method().equals(HttpMethod.HEAD)) {
HttpHead relayedRequest = new HttpHead(relayURI);
if (headerArray.length > 0) {
relayedRequest.setHeaders(headerArray);
}
relayedResponse = client.execute(relayedRequest);
} else if (request.method().equals(HttpMethod.GET)) {
HttpGet relayedRequest = new HttpGet(relayURI);
if (headerArray.length > 0) {
relayedRequest.setHeaders(headerArray);
}
relayedResponse = client.execute(relayedRequest);
} else if (request.method().equals(HttpMethod.POST)) {
HttpPost relayedRequest = new HttpPost(relayURI);
String content = request.content().toString(StandardCharsets.UTF_8);
StringEntity entity = new StringEntity(content);
relayedRequest.setEntity(entity);
if (headerArray.length > 0) {
relayedRequest.setHeaders(headerArray);
}
relayedResponse = client.execute(relayedRequest);
} else if (request.method().equals(HttpMethod.PUT)) {
HttpPut relayedRequest = new HttpPut(relayURI);
String content = request.content().toString(StandardCharsets.UTF_8);
StringEntity entity = new StringEntity(content);
relayedRequest.setEntity(entity);
if (headerArray.length > 0) {
relayedRequest.setHeaders(headerArray);
}
relayedResponse = client.execute(relayedRequest);
} else if (request.method().equals(HttpMethod.DELETE)) {
HttpDelete relayedRequest = new HttpDelete(relayURI);
if (headerArray.length > 0) {
relayedRequest.setHeaders(headerArray);
}
relayedResponse = client.execute(relayedRequest);
} else if (request.method().equals(HttpMethod.OPTIONS)) {
HttpOptions relayedRequest = new HttpOptions(relayURI);
if (headerArray.length > 0) {
relayedRequest.setHeaders(headerArray);
}
relayedResponse = client.execute(relayedRequest);
}
} catch (Exception e) {
String message = e.getMessage();
if (message == null) {
LOG.error("", e);
} else {
LOG.error(message, e);
}
this.sendHttpError(ctx, new TimelyException(HttpResponseStatus.INTERNAL_SERVER_ERROR.code(),
e.getMessage(), e.getLocalizedMessage(), e));
return;
} finally {
if (request != null && request instanceof AutoCloseable) {
ReferenceCountUtil.release(request);
}
}
FullHttpResponse response = null;
if (relayedResponse == null) {
this.sendHttpError(ctx, new TimelyException(HttpResponseStatus.METHOD_NOT_ALLOWED.code(),
"Method not allowed", "Method not allowed"));
} else {
LOG.debug("RequestURL:{} ResponseCode:{}", relayURI, relayedResponse.getStatusLine().getStatusCode());
HttpEntity httpEntity = relayedResponse.getEntity();
if (httpEntity == null) {
response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.valueOf(relayedResponse.getStatusLine().getStatusCode()));
} else {
ByteArrayOutputStream baos = new MyByteArrayOutputStream();
StreamUtils.copy(httpEntity.getContent(), baos);
response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.valueOf(relayedResponse.getStatusLine().getStatusCode()),
Unpooled.copiedBuffer(baos.toByteArray()));
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
}
for (Header h : relayedResponse.getAllHeaders()) {
response.headers().add(h.getName(), h.getValue());
}
sendResponse(ctx, response);
}
} finally {
if (relayedResponse != null) {
relayedResponse.close();
}
if (client != null && k != null) {
httpClientPool.returnObject(k, client);
} else {
LOG.error("NOT RETURNING CONNECTION! " + msg.getHttpRequest().uri());
}
}
}
static public class MyByteArrayOutputStream extends ByteArrayOutputStream {
public MyByteArrayOutputStream() {
}
public MyByteArrayOutputStream(int size) {
super(size);
}
public int getCount() {
return count;
}
public byte[] getBuf() {
return buf;
}
}
static public String encodeURI(String s) {
try {
s = s.replaceAll("\\{", URLEncoder.encode("{", "UTF-8"));
s = s.replaceAll("\\}", URLEncoder.encode("}", "UTF-8"));
} catch (Exception e) {
}
return s;
}
}
@@ -1,133 +0,0 @@
package timely.grafana.auth.netty.http;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Multimap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import timely.api.request.AuthenticatedRequest;
import timely.api.request.timeseries.HttpRequest;
import timely.api.response.StrictTransportResponse;
import timely.api.response.TimelyException;
import timely.auth.AuthCache;
import timely.auth.AuthenticationService;
import timely.auth.SubjectIssuerDNPair;
import timely.auth.TimelyPrincipal;
import timely.auth.util.HttpHeaderUtils;
import timely.configuration.Http;
import timely.configuration.Security;
import timely.grafana.request.GrafanaRequest;
import timely.netty.Constants;
import timely.netty.http.TimelyHttpHandler;
import timely.netty.http.auth.TimelyAuthenticationToken;
public class GrafanaRequestDecoder extends MessageToMessageDecoder<FullHttpRequest> implements TimelyHttpHandler {
private static final Logger LOG = LoggerFactory.getLogger(GrafanaRequestDecoder.class);
private static final String LOG_RECEIVED_REQUEST = "Received HTTP request {}";
private static final String LOG_PARSED_REQUEST = "Parsed request {}";
private final Security security;
private final String nonSecureRedirectAddress;
public GrafanaRequestDecoder(Security security, Http http) {
this.security = security;
this.nonSecureRedirectAddress = http.getRedirectPath();
}
public static String getSessionId(FullHttpRequest msg) {
Multimap<String, String> headers = HttpHeaderUtils.toMultimap(msg.headers());
Collection<String> cookies = headers.get(HttpHeaderNames.COOKIE.toString());
final StringBuilder buf = new StringBuilder();
cookies.forEach(h -> {
ServerCookieDecoder.STRICT.decode(h).forEach(c -> {
if (c.name().equals(Constants.COOKIE_NAME)) {
if (buf.length() == 0) {
buf.append(c.value());
}
}
});
});
if (buf.length() == 0) {
return null;
} else {
return buf.toString();
}
}
@Override
protected void decode(ChannelHandlerContext ctx, FullHttpRequest msg, List<Object> out) throws Exception {
LOG.trace(LOG_RECEIVED_REQUEST, msg);
final String uri = msg.uri();
final QueryStringDecoder decoder = new QueryStringDecoder(uri);
if (decoder.path().equals(nonSecureRedirectAddress)) {
out.add(new StrictTransportResponse());
return;
}
final String sessionId = getSessionId(msg);
LOG.trace("SessionID: " + sessionId);
HttpRequest request;
try {
request = new GrafanaRequest();
Multimap<String, String> headers = HttpHeaderUtils.toMultimap(msg.headers());
((AuthenticatedRequest) request).addHeaders(headers);
X509Certificate clientCert = AuthenticationService.getClientCertificate(ctx);
TimelyAuthenticationToken token;
if (StringUtils.isNotBlank(sessionId)) {
TimelyPrincipal principal;
((AuthenticatedRequest) request).setSessionId(sessionId);
if (AuthCache.containsKey(sessionId)) {
principal = AuthCache.get(sessionId);
} else {
principal = TimelyPrincipal.anonymousPrincipal();
}
SubjectIssuerDNPair dn = principal.getPrimaryUser().getDn();
token = AuthenticationService.getAuthenticationToken(null, dn.subjectDN(), dn.issuerDN());
} else if (clientCert != null) {
token = AuthenticationService.getAuthenticationToken(clientCert, headers);
} else {
SubjectIssuerDNPair dn = TimelyPrincipal.anonymousPrincipal().getPrimaryUser().getDn();
token = AuthenticationService.getAuthenticationToken(null, dn.subjectDN(), dn.issuerDN());
}
((AuthenticatedRequest) request).setToken(token);
request.setHttpRequest(msg.copy());
LOG.trace(LOG_PARSED_REQUEST, request);
request.validate();
out.add(request);
} catch (UnsupportedOperationException | NullPointerException e) {
// Return the original http request to route to the static file
// server
msg.retain();
out.add(msg);
return;
}
try {
try {
AuthenticationService.enforceAccess((AuthenticatedRequest) request);
} catch (TimelyException e) {
if (!security.isAllowAnonymousHttpAccess()) {
throw e;
}
}
} catch (Exception e) {
out.clear();
throw e;
}
}
}
@@ -1,32 +0,0 @@
package timely.grafana.request;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.QueryStringDecoder;
import timely.api.annotation.Http;
import timely.api.request.AuthenticatedRequest;
import timely.api.request.HttpGetRequest;
import timely.api.request.HttpPostRequest;
@Http(path = "/")
public class GrafanaRequest extends AuthenticatedRequest implements HttpGetRequest, HttpPostRequest {
private FullHttpRequest httpRequest = null;
@Override
public HttpGetRequest parseQueryParameters(QueryStringDecoder decoder) throws Exception {
return new GrafanaRequest();
}
@Override
public HttpPostRequest parseBody(String content) throws Exception {
return new GrafanaRequest();
}
public void setHttpRequest(FullHttpRequest httpRequest) {
this.httpRequest = httpRequest;
}
public FullHttpRequest getHttpRequest() {
return httpRequest;
}
}
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter>
<Match>
<Class name="timely.grafana.auth.netty.http.GrafanaRelayHandler$MyByteArrayOutputStream" />
<Method name="getBuf" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
</FindBugsFilter>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>timely</groupId>
<artifactId>timely</artifactId>
<version>1.3.0</version>
<version>2.0.0</version>
</parent>
<artifactId>timely-app</artifactId>
<packaging>pom</packaging>
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
...require('@grafana/toolkit/src/config/prettier.plugin.config.json'),
};
+3 -3
View File
@@ -1,6 +1,6 @@
# Timely Data Source Plugin
Timely is a time series database application that provides secure access to time
series data. Timely is written in Java, uses
[Apache Accumulo](https://accumulo.apache.org/) for backend storage, and has
Timely is a time series database application that provides secure access to time
series data. Timely is written in Java, uses
[Apache Accumulo](https://accumulo.apache.org/) for backend storage, and has
a configurable length memory cache.
+2 -2
View File
@@ -1,6 +1,6 @@
# Test against the latest version of this Node.js version
environment:
nodejs_version: "10"
nodejs_version: '10'
# Local NPM Modules
cache:
@@ -22,5 +22,5 @@ test_script:
# Run the build
build_script:
- yarn dev # This will also run prettier!
- yarn dev # This will also run prettier!
- yarn build # make sure both scripts work
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="jest tests" tests="1" failures="0" time="1.179">
<testsuite name="placeholder test" errors="0" failures="0" skipped="0" timestamp="2021-10-22T20:15:17" time="0.552" tests="1">
<testcase classname="placeholder test should return true" name="placeholder test should return true" time="0.003">
</testcase>
</testsuite>
</testsuites>
+3 -3
View File
@@ -1,6 +1,6 @@
# Timely Data Source Plugin
Timely is a time series database application that provides secure access to time
series data. Timely is written in Java, uses
[Apache Accumulo](https://accumulo.apache.org/) for backend storage, and has
Timely is a time series database application that provides secure access to time
series data. Timely is written in Java, uses
[Apache Accumulo](https://accumulo.apache.org/) for backend storage, and has
a configurable length memory cache.
+1 -100
View File
@@ -1,101 +1,2 @@
define(function() { return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./styles/dark.css");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./styles/dark.css":
/*!*************************!*\
!*** ./styles/dark.css ***!
\*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ })
/******/ })});;
define((function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=71)}({71:function(e,t,n){}})}));
//# sourceMappingURL=dark.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./styles/dark.css"],"names":[],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,uC","file":"dark.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./styles/dark.css\");\n","// extracted by mini-css-extract-plugin"],"sourceRoot":""}
{"version":3,"sources":["webpack:///webpack/bootstrap"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s"],"mappings":"sCACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,IAIjBlC,EAAoBA,EAAoBmC,EAAI,I","file":"dark.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 71);\n"],"sourceRoot":""}
+1 -100
View File
@@ -1,101 +1,2 @@
define(function() { return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./styles/light.css");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./styles/light.css":
/*!**************************!*\
!*** ./styles/light.css ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ })
/******/ })});;
define((function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=70)}({70:function(e,t,n){}})}));
//# sourceMappingURL=light.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./styles/light.css"],"names":[],"mappings":";QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA,uC","file":"light.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./styles/light.css\");\n","// extracted by mini-css-extract-plugin"],"sourceRoot":""}
{"version":3,"sources":["webpack:///webpack/bootstrap"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s"],"mappings":"sCACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,IAIjBlC,EAAoBA,EAAoBmC,EAAI,I","file":"light.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 70);\n"],"sourceRoot":""}
+2 -74841
View File
File diff suppressed because it is too large. Load diff
+87
View File
@@ -0,0 +1,87 @@
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.16.1
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.16.1-lts
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///../node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack:///../node_modules/@babel/runtime/helpers/defineProperty.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js","webpack:///../node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js","webpack:///../node_modules/@babel/runtime/helpers/esm/classCallCheck.js","webpack:///../node_modules/@babel/runtime/helpers/esm/createClass.js","webpack:///../node_modules/@babel/runtime/helpers/esm/defineProperty.js","webpack:///../node_modules/@babel/runtime/helpers/esm/extends.js","webpack:///../node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js","webpack:///../node_modules/@babel/runtime/helpers/esm/inherits.js","webpack:///../node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack:///../node_modules/@babel/runtime/helpers/esm/iterableToArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js","webpack:///../node_modules/@babel/runtime/helpers/esm/nonIterableRest.js","webpack:///../node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js","webpack:///../node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js","webpack:///../node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js","webpack:///../node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js","webpack:///../node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack:///../node_modules/@babel/runtime/helpers/esm/slicedToArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/toArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/toConsumableArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/typeof.js","webpack:///../node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js","webpack:///../node_modules/@babel/runtime/helpers/extends.js","webpack:///../node_modules/@babel/runtime/helpers/inheritsLoose.js","webpack:///../node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js","webpack:///../node_modules/@material-ui/core/esm/Accordion/Accordion.js","webpack:///../node_modules/@material-ui/core/esm/Accordion/AccordionContext.js","webpack:///../node_modules/@material-ui/core/esm/Accordion/index.js","webpack:///../node_modules/@material-ui/core/esm/AccordionActions/AccordionActions.js","webpack:///../node_modules/@material-ui/core/esm/AccordionActions/index.js","webpack:///../node_modules/@material-ui/core/esm/AccordionDetails/AccordionDetails.js","webpack:///../node_modules/@material-ui/core/esm/AccordionDetails/index.js","webpack:///../node_modules/@material-ui/core/esm/AccordionSummary/AccordionSummary.js","webpack:///../node_modules/@material-ui/core/esm/AccordionSummary/index.js","webpack:///../node_modules/@material-ui/core/esm/AppBar/AppBar.js","webpack:///../node_modules/@material-ui/core/esm/AppBar/index.js","webpack:///../node_modules/@material-ui/core/esm/Avatar/Avatar.js","webpack:///../node_modules/@material-ui/core/esm/Avatar/index.js","webpack:///../node_modules/@material-ui/core/esm/Backdrop/Backdrop.js","webpack:///../node_modules/@material-ui/core/esm/Backdrop/index.js","webpack:///../node_modules/@material-ui/core/esm/Badge/Badge.js","webpack:///../node_modules/@material-ui/core/esm/Badge/index.js","webpack:///../node_modules/@material-ui/core/esm/BottomNavigation/BottomNavigation.js","webpack:///../node_modules/@material-ui/core/esm/BottomNavigation/index.js","webpack:///../node_modules/@material-ui/core/esm/BottomNavigationAction/BottomNavigationAction.js","webpack:///../node_modules/@material-ui/core/esm/BottomNavigationAction/index.js","webpack:///../node_modules/@material-ui/core/esm/Box/Box.js","webpack:///../node_modules/@material-ui/core/esm/Box/index.js","webpack:///../node_modules/@material-ui/core/esm/Breadcrumbs/BreadcrumbCollapsed.js","webpack:///../node_modules/@material-ui/core/esm/Breadcrumbs/Breadcrumbs.js","webpack:///../node_modules/@material-ui/core/esm/Breadcrumbs/index.js","webpack:///../node_modules/@material-ui/core/esm/Button/Button.js","webpack:///../node_modules/@material-ui/core/esm/Button/index.js","webpack:///../node_modules/@material-ui/core/esm/ButtonBase/ButtonBase.js","webpack:///../node_modules/@material-ui/core/esm/ButtonBase/Ripple.js","webpack:///../node_modules/@material-ui/core/esm/ButtonBase/TouchRipple.js","webpack:///../node_modules/@material-ui/core/esm/ButtonBase/index.js","webpack:///../node_modules/@material-ui/core/esm/ButtonGroup/ButtonGroup.js","webpack:///../node_modules/@material-ui/core/esm/ButtonGroup/index.js","webpack:///../node_modules/@material-ui/core/esm/Card/Card.js","webpack:///../node_modules/@material-ui/core/esm/Card/index.js","webpack:///../node_modules/@material-ui/core/esm/CardActionArea/CardActionArea.js"Line truncated
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///external \"react\"","webpack:///../node_modules/prop-types/index.js","webpack:///../node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack:///../node_modules/@babel/runtime/helpers/defineProperty.js","webpack:///../node_modules/@babel/runtime/helpers/extends.js","webpack:///../node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js","webpack:///../node_modules/classnames/index.js","webpack:///external \"@grafana/ui\"","webpack:///../node_modules/@babel/runtime/helpers/inheritsLoose.js","webpack:///external \"react-dom\"","webpack:///external \"lodash\"","webpack:///external \"@grafana/runtime\"","webpack:///../node_modules/fast-deep-equal/index.js","webpack:///../node_modules/invariant/browser.js","webpack:///../node_modules/define-properties/index.js","webpack:///../node_modules/warning/warning.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js","webpack:///../node_modules/webpack/buildin/global.js","webpack:///../node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js","webpack:///../node_modules/function-bind/index.js","webpack:///../node_modules/call-bind/index.js","webpack:///../node_modules/popper.js/dist/esm/popper.js","webpack:///../node_modules/@hypnosphi/create-react-context/lib/index.js","webpack:///../node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js","webpack:///../node_modules/object-keys/index.js","webpack:///../node_modules/object-keys/isArguments.js","webpack:///../node_modules/call-bind/callBound.js","webpack:///../node_modules/get-intrinsic/index.js","webpack:///../node_modules/has-symbols/shams.js","webpack:///../node_modules/object-is/implementation.js","webpack:///../node_modules/object-is/polyfill.js","webpack:///../node_modules/regexp.prototype.flags/implementation.js","webpack:///../node_modules/regexp.prototype.flags/polyfill.js","webpack:///../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js","webpack:///../node_modules/css-loader/dist/runtime/api.js","webpack:///external \"@grafana/data\"","webpack:///../node_modules/dayjs/dayjs.min.js","webpack:///../node_modules/lodash.debounce/index.js","webpack:///../node_modules/deep-equal/index.js","webpack:///../node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js","webpack:///../node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack:///../node_modules/@babel/runtime/helpers/esm/iterableToArray.js","webpack:///../node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js","webpack:///../node_modules/@babel/runtime/helpers/esm/nonIterableRest.js","webpack:///../node_modules/@material-ui/core/node_modules/popper.js/dist/esm/popper.js","webpack:///../node_modules/prop-types/factoryWithThrowingShims.js","webpack:///../node_modules/prop-types/lib/ReactPropTypesSecret.js","webpack:///../node_modules/@babel/runtime/helpers/setPrototypeOf.js","webpack:///../node_modules/object-keys/implementation.js","webpack:///../node_modules/is-arguments/index.js","webpack:///../node_modules/has-symbols/index.js","webpack:///../node_modules/function-bind/implementation.js","webpack:///../node_modules/has/src/index.js","webpack:///../node_modules/object-is/index.js","webpack:///../node_modules/object-is/shim.js","webpack:///../node_modules/is-regex/index.js","webpack:///../node_modules/regexp.prototype.flags/index.js","webpack:///../node_modules/regexp.prototype.flags/shim.js","webpack:///../node_modules/is-date-object/index.js","webpack:///../node_modules/@hypnosphi/create-react-context/lib/implementation.js","webpack:///../node_modules/gud/index.js","webpack:///../node_modules/react-is/index.js","webpack:///../node_modules/react-is/cjs/react-is.production.min.js","webpack:///./static/css/timely-bootstrap.css?617f","webpack:///./static/css/timely-bootstrap.css","webpack:///./static/css/timely.css?f98e","webpack:///./static/css/timely.css","webpack:///../node_modules/tslib/tslib.es6.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/isFunction.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/lift.js","webpack:///../node_modules/rxjs/node_modules/tslib/tslib.es6.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/arrRemove.js","webpack:///../node_modules/rxjs/dist/esm5/internal/Subscription.js","webpack:///../node_modules/rxjs/dist/esm5/internal/config.js","webpack:///../node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/noop.js","webpack:///../node_modules/rxjs/dist/esm5/internal/NotificationFactories.js","webpack:///../node_modules/rxjs/dist/esm5/internal/util/errorContext.js","webpack:///../node_modules/rxjs/dist/esm5/inteLine truncated
+3 -5
View File
@@ -12,9 +12,7 @@
"author": {
"name": "National Security Agency"
},
"keywords": [
"Simple"
],
"keywords": ["Simple"],
"logos": {
"small": "static/img/timely_square_small.png",
"large": "static/img/timely_square_large.png"
@@ -30,8 +28,8 @@
}
],
"screenshots": [],
"version": "1.3.0",
"updated": "2020-09-25"
"version": "2.0.0",
"updated": "2024-01-17"
},
"dependencies": {
"classnames": "2.2.6",
-54
View File
@@ -1,54 +0,0 @@
$box-shadow-dimensions: 0 0 0 0.2rem;
$placeholder-color: #6c757d;
.rbt {
&-input-multi {
// Bootstrap 4 focus style
&.focus {
background-color: #fff;
border-color: #80bdff;
box-shadow: $box-shadow-dimensions rgba(0, 123, 255, 0.25);
color: #495057;
outline: 0;
}
&.is-invalid.focus {
border-color: #dc3545;
box-shadow: $box-shadow-dimensions rgba(220, 53, 69, 0.25);
}
&.is-valid.focus {
border-color: #28a745;
box-shadow: $box-shadow-dimensions rgba(40, 167, 69, 0.25);
}
input {
// Firefox
&::-moz-placeholder {
color: $placeholder-color;
opacity: 1;
}
// Internet Explorer 10+
&:-ms-input-placeholder {
color: $placeholder-color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
color: $placeholder-color;
}
}
// Override height in main CSS file :/
& .rbt-input-main,
&.form-control-lg .rbt-input-main,
&.form-control-sm .rbt-input-main {
height: auto;
}
}
&-token {
margin: 1px 3px 2px 0;
}
}
-201
View File
@@ -1,201 +0,0 @@
.rbt .rbt-input-main::-ms-clear {
display: none !important;
}
/**
* Menu
*/
.rbt-menu {
margin-bottom: 2px !important;
}
.rbt-menu > .dropdown-item {
overflow: hidden !important;
text-overflow: ellipsis !important;
}
.rbt-menu > .dropdown-item:focus {
outline: none !important;
}
.rbt-menu-pagination-option {
text-align: center !important;
}
/**
* Multi-select Input
*/
.rbt-input-multi {
cursor: text !important;
overflow: hidden !important;
position: relative !important;
}
.rbt-input-multi.focus {
border-color: #80bdff !important;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
color: #495057 !important;
outline: 0 !important;
}
.rbt-input-multi.form-control {
height: auto !important;
}
.rbt-input-multi.form-control[disabled] {
background-color: #e9ecef !important;
opacity: 1 !important;
}
.rbt-input-multi.is-invalid.focus {
border-color: #dc3545 !important;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
}
.rbt-input-multi.is-valid.focus {
border-color: #28a745 !important;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
}
.rbt-input-multi input::-moz-placeholder {
color: #6c757d !important;
opacity: 1 !important;
}
.rbt-input-multi input:-ms-input-placeholder {
color: #6c757d !important;
}
.rbt-input-multi input::-webkit-input-placeholder {
color: #6c757d !important;
}
.rbt-input-multi .rbt-input-wrapper {
align-items: flex-start !important;
display: flex !important;
flex-wrap: wrap !important;
margin-bottom: -4px !important;
margin-top: -1px !important;
overflow: hidden !important;
}
.rbt-input-multi .rbt-input-main {
margin: 1px 0 4px !important;
}
/**
* Close Button
*/
.rbt-close {
z-index: 1 !important;
}
.rbt-close-lg {
font-size: 24px !important;
}
/**
* Token
*/
.rbt-token {
background-color: #e7f4ff !important;
border: 0 !important;
border-radius: .25rem !important;
color: #007bff !important;
display: inline-block !important;
line-height: 1em !important;
margin: 1px 3px 2px 0 !important;
padding: 4px 7px !important;
position: relative !important;
}
.rbt-token-disabled {
background-color: rgba(0, 0, 0, 0.1) !important;
color: #495057 !important;
pointer-events: none !important;
}
.rbt-token-removeable {
cursor: pointer !important;
padding-right: 21px !important;
}
.rbt-token-active {
background-color: #007bff !important;
color: #fff !important;
outline: none !important;
text-decoration: none !important;
}
.rbt-token .rbt-token-remove-button {
bottom: 0 !important;
color: inherit !important;
font-size: inherit !important;
font-weight: normal !important;
opacity: 1 !important;
outline: none !important;
padding: 3px 7px !important;
position: absolute !important;
right: 0 !important;
text-shadow: none !important;
top: -2px !important;
}
/**
* Loader + CloseButton container
*/
.rbt-aux {
align-items: center !important;
display: flex !important;
bottom: 0 !important;
justify-content: center !important;
pointer-events: none !important;
/* Don't block clicks on the input */
position: absolute !important;
right: 0 !important;
top: 0 !important;
width: 34px !important;
}
.rbt-aux-lg {
width: 46px !important;
}
.rbt-aux .rbt-close {
margin-top: -4px !important;
pointer-events: auto !important;
/* Override pointer-events: none; above */
}
.has-aux .rbt-input {
padding-right: 34px !important;
}
.rbt-highlight-text {
background-color: inherit !important;
color: inherit !important;
font-weight: bold !important;
padding: 0 !important;
}
/**
* Input Groups
*/
.input-group > .rbt {
flex: 1 !important;
}
.input-group > .rbt .rbt-input-hint,
.input-group > .rbt .rbt-aux {
z-index: 5 !important;
}
.input-group > .rbt:not(:first-child) .form-control {
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
}
.input-group > .rbt:not(:last-child) .form-control {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
-240
View File
@@ -1,240 +0,0 @@
$animation: loader-animation 600ms infinite linear;
$inset: inset 0 1px 1px rgba(0, 0, 0, 0.075);
$placeholder-color: #999;
.rbt {
&-menu {
margin-bottom: 2px; // Spacing for dropup
& > li a {
overflow: hidden;
text-overflow: ellipsis;
&:focus {
outline: none;
}
}
&-pagination-option {
text-align: center;
}
}
// Hide IE's native "clear" button
& .rbt-input-main::-ms-clear {
display: none;
}
&-input-multi {
cursor: text;
overflow: hidden;
position: relative;
height: auto;
// Apply Bootstrap focus styles
&.focus {
box-shadow: $inset, 0 0 8px rgba(102, 175, 233, 0.6);
border-color: #66afe9;
outline: 0;
}
// BS4 uses the :disabled pseudo-class, which doesn't work with non-inputs.
&.form-control[disabled] {
background-color: #e9ecef;
opacity: 1;
}
// Apply Bootstrap placeholder styles
input {
// Firefox
&::-moz-placeholder {
color: $placeholder-color;
opacity: 1;
}
// Internet Explorer 10+
&:-ms-input-placeholder {
color: $placeholder-color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
color: $placeholder-color;
}
}
.rbt-input-wrapper {
align-items: flex-start;
display: flex;
flex-wrap: wrap;
margin-bottom: -4px;
margin-top: -1px;
overflow: hidden;
}
.rbt-input-main {
// Set input height for cross-browser consistency
height: 20px;
margin: 1px 0 4px;
}
&.input,
&.form-control {
&-lg {
.rbt-input-main {
height: 24px;
}
}
&-sm {
.rbt-input-main {
height: 18px;
}
}
}
}
&-close {
z-index: 1;
&-lg {
font-size: 24px;
}
}
&-token {
background-color: #e7f4ff;
border: 0;
border-radius: 2px;
color: #1f8dd6;
display: inline-block;
line-height: 1em;
margin: 0 3px 3px 0;
padding: 4px 7px;
position: relative;
&-disabled {
background-color: #ddd;
color: #888;
pointer-events: none;
}
&-removeable {
cursor: pointer;
padding-right: 21px;
}
&-active {
background-color: #1f8dd6;
color: #fff;
outline: none;
text-decoration: none;
}
& &-remove-button {
bottom: 0;
color: inherit;
font-size: inherit;
font-weight: normal;
opacity: 1;
outline: none;
padding: 3px 7px;
position: absolute;
right: 0;
text-shadow: none;
top: -2px;
}
}
&-loader {
-moz-animation: $animation;
-webkit-animation: $animation;
animation: $animation;
border: 1px solid #d5d5d5;
border-radius: 50%;
border-top-color: #1f8dd6;
display: block;
height: 16px;
width: 16px;
&-lg {
height: 20px;
width: 20px;
}
}
&-aux {
align-items: center;
display: flex;
bottom: 0;
justify-content: center;
pointer-events: none; /* Don't block clicks on the input */
position: absolute;
right: 0;
top: 0;
width: 34px;
&-lg {
width: 46px;
}
& .rbt-close {
margin-top: -4px;
pointer-events: auto; /* Override pointer-events: none; above */
}
}
.has-aux &-input {
padding-right: 34px;
}
&-highlight-text {
background-color: inherit;
color: inherit;
font-weight: bold;
padding: 0;
}
}
/* Input Groups */
.input-group > .rbt {
flex: 1;
// Form-controls within input-groups have a higher z-index.
& .rbt-input-hint,
& .rbt-aux {
z-index: 5;
}
&:not(:first-child) .form-control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
&:not(:last-child) .form-control {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
/* Validation States */
.has-error .rbt-input-multi.focus {
border-color: #843534;
box-shadow: $inset, 0 0 6px #ce8483;
}
.has-warning .rbt-input-multi.focus {
border-color: #66512c;
box-shadow: $inset, 0 0 6px #c0a16b;
}
.has-success .rbt-input-multi.focus {
border-color: #2b542c;
box-shadow: $inset, 0 0 6px #67b168;
}
@keyframes loader-animation {
to {
transform: rotate(1turn);
}
}
-408
View File
@@ -1,408 +0,0 @@
div.timely .form-control {
display: block;
width: 100%;
height: calc(1.5em + 0.75rem + 2px);
padding: 0.375rem 0.75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
/*@media (prefers-reduced-motion: reduce) {*/
/* .form-control {*/
/* transition: none;*/
/* }*/
/*}*/
div.timely .form-control::-ms-expand {
background-color: transparent;
border: 0;
}
div.timely .form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #495057;
}
div.timely .form-control:focus {
color: #495057;
/*background-color: #fff;*/
border-color: #80bdff;
outline: 0;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
/*box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);*/
}
div.timely .form-control::-webkit-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-moz-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:disabled, div.timely .form-control[readonly] {
background-color: #e9ecef;
opacity: 1;
}
div.timely select.form-control:focus::-ms-value {
color: #495057;
background-color: #fff;
}
div.timely .form-control-file,
div.timely .form-control-range {
display: block;
width: 100%;
}
div.timely .form-control-plaintext {
display: block;
width: 100%;
padding: 0.375rem 0;
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
border: solid transparent;
border-width: 1px 0;
}
div.timely .form-control-plaintext.form-control-sm, div.timely .form-control-plaintext.form-control-lg {
padding-right: 0;
padding-left: 0;
}
div.timely .form-control-sm {
height: calc(1.5em + 0.5rem + 2px);
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
}
div.timely .form-control-lg {
height: calc(1.5em + 1rem + 2px);
padding: 0.5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: 0.3rem;
}
div.timely select.form-control[size], div.timely select.form-control[multiple] {
height: auto;
}
div.timely textarea.form-control {
height: auto;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
div.timely .dropup,
div.timely .dropright,
div.timely .dropdown,
div.timely .dropleft {
position: relative;
}
div.timely .dropdown-toggle {
white-space: nowrap;
}
div.timely .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
}
div.timely .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
}
div.timely .dropdown-menu-left {
right: auto;
left: 0;
}
div.timely .dropdown-menu-right {
right: 0;
left: auto;
}
/*@media (min-width: 576px) {*/
/* .dropdown-menu-sm-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-sm-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
/*@media (min-width: 768px) {*/
/* .dropdown-menu-md-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-md-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
/*@media (min-width: 992px) {*/
/* .dropdown-menu-lg-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-lg-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
/*@media (min-width: 1200px) {*/
/* .dropdown-menu-xl-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-xl-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
div.timely .dropup .dropdown-menu {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 0.125rem;
}
div.timely .dropup .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0;
border-right: 0.3em solid transparent;
border-bottom: 0.3em solid;
border-left: 0.3em solid transparent;
}
div.timely .dropup .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropright .dropdown-menu {
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: 0.125rem;
}
div.timely .dropright .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
}
div.timely .dropright .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropright .dropdown-toggle::after {
vertical-align: 0;
}
div.timely .dropleft .dropdown-menu {
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: 0.125rem;
}
div.timely .dropleft .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
}
div.timely .dropleft .dropdown-toggle::after {
display: none;
}
div.timely .dropleft .dropdown-toggle::before {
display: inline-block;
margin-right: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0.3em solid;
border-bottom: 0.3em solid transparent;
}
div.timely .dropleft .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropleft .dropdown-toggle::before {
vertical-align: 0;
}
div.timely .dropdown-menu[x-placement^="top"], div.timely .dropdown-menu[x-placement^="right"], div.timely .dropdown-menu[x-placement^="bottom"], div.timely .dropdown-menu[x-placement^="left"] {
right: auto;
bottom: auto;
}
div.timely .dropdown-divider {
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid #e9ecef;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-menu.show {
display: block;
}
div.timely .dropdown-header {
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
color: #6c757d;
white-space: nowrap;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
File diff suppressed because it is too large. Load diff
+196 -232
View File
@@ -1,359 +1,323 @@
div.timely .form-control {
display: block;
width: 100%;
/*height: calc(1.5em + 0.75rem + 2px);*/
height: 32px;
/*padding: 0.375rem 0.75rem;*/
padding: 0px 8px;
/*font-size: 1rem;*/
font-size: 14px;
font-weight: 400;
line-height: 1.5;
border: 1px solid #ced4da;
/*border-radius: 0.25rem;*/
border-radius: 2px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
color: #495057;
background-color: #fff;
background-clip: padding-box;
display: block;
width: 100%;
height: 32px;
padding: 0px 8px;
font-size: 14px;
font-weight: 400;
line-height: 1.5;
border: 1px solid #ced4da;
border-radius: 2px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
background-clip: padding-box;
}
div.timely .form-control::-ms-expand {
background-color: transparent;
border: 0;
background-color: transparent;
border: 0;
}
div.timely .form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #495057;
color: transparent;
text-shadow: 0 0 0 #495057;
}
div.timely .form-control:focus, div.timely input:focus {
border-color: #80bdff;
outline: 0;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
div.timely .form-control::-webkit-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-moz-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:disabled, div.timely .form-control[readonly] {
background-color: #e9ecef;
opacity: 1;
}
div.timely select.form-control:focus::-ms-value {
color: #495057;
background-color: #fff;
div.timely .form-control:focus,
div.timely input:focus {
border-color: #80bdff;
outline: 0;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
div.timely .form-control-file,
div.timely .form-control-range {
display: block;
width: 100%;
display: block;
width: 100%;
}
div.timely .form-control-plaintext {
display: block;
width: 100%;
padding: 0.375rem 0;
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
border: solid transparent;
border-width: 1px 0;
display: block;
width: 100%;
padding: 0.375rem 0;
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
border: solid transparent;
border-width: 1px 0;
}
div.timely .form-control-plaintext.form-control-sm, div.timely .form-control-plaintext.form-control-lg {
padding-right: 0;
padding-left: 0;
div.timely .form-control-plaintext.form-control-sm,
div.timely .form-control-plaintext.form-control-lg {
padding-right: 0;
padding-left: 0;
}
div.timely .form-control-sm {
height: calc(1.5em + 0.5rem + 2px);
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
height: calc(1.5em + 0.5rem + 2px);
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
}
div.timely .form-control-lg {
height: calc(1.5em + 1rem + 2px);
padding: 0.5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: 0.3rem;
height: calc(1.5em + 1rem + 2px);
padding: 0.5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: 0.3rem;
}
div.timely select.form-control[size], div.timely select.form-control[multiple] {
height: auto;
div.timely select.form-control[size],
div.timely select.form-control[multiple] {
height: auto;
}
div.timely textarea.form-control {
height: auto;
height: auto;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
div.timely .dropdown-item:hover,
div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
div.timely .dropdown-item.active,
div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
div.timely .dropdown-item.disabled,
div.timely .dropdown-item:disabled {
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
div.timely .dropup,
div.timely .dropright,
div.timely .dropdown,
div.timely .dropleft {
position: relative;
position: relative;
}
div.timely .dropdown-toggle {
white-space: nowrap;
white-space: nowrap;
}
div.timely .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
}
div.timely .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
}
div.timely .dropdown-menu-left {
right: auto;
left: 0;
right: auto;
left: 0;
}
div.timely .dropdown-menu-right {
right: 0;
left: auto;
right: 0;
left: auto;
}
div.timely .dropup .dropdown-menu {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 0.125rem;
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 0.125rem;
}
div.timely .dropup .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0;
border-right: 0.3em solid transparent;
border-bottom: 0.3em solid;
border-left: 0.3em solid transparent;
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0;
border-right: 0.3em solid transparent;
border-bottom: 0.3em solid;
border-left: 0.3em solid transparent;
}
div.timely .dropup .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropright .dropdown-menu {
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: 0.125rem;
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: 0.125rem;
}
div.timely .dropright .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
}
div.timely .dropright .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropright .dropdown-toggle::after {
vertical-align: 0;
vertical-align: 0;
}
div.timely .dropleft .dropdown-menu {
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: 0.125rem;
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: 0.125rem;
}
div.timely .dropleft .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
}
div.timely .dropleft .dropdown-toggle::after {
display: none;
display: none;
}
div.timely .dropleft .dropdown-toggle::before {
display: inline-block;
margin-right: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0.3em solid;
border-bottom: 0.3em solid transparent;
display: inline-block;
margin-right: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid transparent;
border-right: 0.3em solid;
border-bottom: 0.3em solid transparent;
}
div.timely .dropleft .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropleft .dropdown-toggle::before {
vertical-align: 0;
vertical-align: 0;
}
div.timely .dropdown-menu[x-placement^="top"], div.timely .dropdown-menu[x-placement^="right"], div.timely .dropdown-menu[x-placement^="bottom"], div.timely .dropdown-menu[x-placement^="left"] {
right: auto;
bottom: auto;
div.timely .dropdown-menu[x-placement^='top'],
div.timely .dropdown-menu[x-placement^='right'],
div.timely .dropdown-menu[x-placement^='bottom'],
div.timely .dropdown-menu[x-placement^='left'] {
right: auto;
bottom: auto;
}
div.timely .dropdown-divider {
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid #e9ecef;
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid #e9ecef;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
div.timely .dropdown-item:hover,
div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
div.timely .dropdown-item.active,
div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
div.timely .dropdown-item.disabled,
div.timely .dropdown-item:disabled {
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-menu.show {
display: block;
display: block;
}
div.timely .dropdown-header {
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
color: #6c757d;
white-space: nowrap;
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
white-space: nowrap;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
display: block;
padding: 0.25rem 1.5rem;
}
+29 -33
View File
@@ -1,81 +1,77 @@
div.timely input:focus {
z-index: 1;
z-index: 1;
}
div.timely-edior-row div.gf-form-inline {
height: 40px !important;
height: 40px !important;
}
div.timely input.form-control {
border-color: rgb(44, 50, 53);
border-top-color: rgb(44, 50, 53);
border-right-color: rgb(44, 50, 53);
border-bottom-color: rgb(44, 50, 53);
border-left-color: rgb(44, 50, 53);
border-color: rgb(44, 50, 53);
border-top-color: rgb(44, 50, 53);
border-right-color: rgb(44, 50, 53);
border-bottom-color: rgb(44, 50, 53);
border-left-color: rgb(44, 50, 53);
}
div.timely.tag {
min-width: 16px !important;
padding-left: 2px;
padding-right: 2px;
min-width: 16px !important;
padding-left: 2px;
padding-right: 2px;
}
div.timely-edior-row div.gf-form {
margin-right: 4px !important;
margin-right: 4px !important;
}
div.timely.tag.error {
margin-left: 4px;
margin-left: 4px;
}
div.timely.tag.error svg {
color: #f19d06;
color: #f19d06;
}
div.timely.tag.edit {
margin-left: 6px;
margin-left: 6px;
}
div.timely.tag.edit svg {
color: #62A562;
color: #62a562;
}
div.timely.tag.save {
margin-left: 6px;
margin-left: 6px;
}
div.timely.tag.save svg {
color: #62A562;
color: #62a562;
}
div.timely.tag.delete svg {
color: #D9162D;
color: #d9162d;
}
div.timely.tag.addtag svg {
color: #62A562;
color: #62a562;
}
button[title="Move query down"] div svg {
color: #B3BFBD;
button[title='Move query down'] div svg {
color: #b3bfbd;
}
button[title="Move query up"] div svg {
color: #B3BFBD;
button[title='Move query up'] div svg {
color: #b3bfbd;
}
button[title="Duplicate query"] div svg {
color: #62A562;
button[title='Duplicate query'] div svg {
color: #62a562;
}
button[title="Disable/enable query"] div svg {
color: #2AB4F5;
button[title='Disable/enable query'] div svg {
color: #2ab4f5;
}
button[title="Remove query"] div svg {
color: #D9162D;
button[title='Remove query'] div svg {
color: #d9162d;
}
+2 -2
View File
@@ -35,7 +35,7 @@ $placeholder-color: #6c757d;
}
// Safari and Chrome
&::-webkit-input-placeholder {
&::-webkit-input-placeholder {
color: $placeholder-color;
}
}
@@ -51,4 +51,4 @@ $placeholder-color: #6c757d;
&-token {
margin: 1px 3px 2px 0;
}
}
}
+87 -87
View File
@@ -1,201 +1,201 @@
.rbt .rbt-input-main::-ms-clear {
display: none !important;
display: none !important;
}
/**
* Menu
*/
.rbt-menu {
margin-bottom: 2px !important;
margin-bottom: 2px !important;
}
.rbt-menu > .dropdown-item {
overflow: hidden !important;
text-overflow: ellipsis !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
.rbt-menu > .dropdown-item:focus {
outline: none !important;
outline: none !important;
}
.rbt-menu-pagination-option {
text-align: center !important;
text-align: center !important;
}
/**
* Multi-select Input
*/
.rbt-input-multi {
cursor: text !important;
overflow: hidden !important;
position: relative !important;
cursor: text !important;
overflow: hidden !important;
position: relative !important;
}
.rbt-input-multi.focus {
border-color: #80bdff !important;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
color: #495057 !important;
outline: 0 !important;
border-color: #80bdff !important;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
color: #495057 !important;
outline: 0 !important;
}
.rbt-input-multi.form-control {
height: auto !important;
height: auto !important;
}
.rbt-input-multi.form-control[disabled] {
background-color: #e9ecef !important;
opacity: 1 !important;
background-color: #e9ecef !important;
opacity: 1 !important;
}
.rbt-input-multi.is-invalid.focus {
border-color: #dc3545 !important;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
border-color: #dc3545 !important;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
}
.rbt-input-multi.is-valid.focus {
border-color: #28a745 !important;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
border-color: #28a745 !important;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
}
.rbt-input-multi input::-moz-placeholder {
color: #6c757d !important;
opacity: 1 !important;
color: #6c757d !important;
opacity: 1 !important;
}
.rbt-input-multi input:-ms-input-placeholder {
color: #6c757d !important;
color: #6c757d !important;
}
.rbt-input-multi input::-webkit-input-placeholder {
color: #6c757d !important;
color: #6c757d !important;
}
.rbt-input-multi .rbt-input-wrapper {
align-items: flex-start !important;
display: flex !important;
flex-wrap: wrap !important;
margin-bottom: -4px !important;
margin-top: -1px !important;
overflow: hidden !important;
align-items: flex-start !important;
display: flex !important;
flex-wrap: wrap !important;
margin-bottom: -4px !important;
margin-top: -1px !important;
overflow: hidden !important;
}
.rbt-input-multi .rbt-input-main {
margin: 1px 0 4px !important;
margin: 1px 0 4px !important;
}
/**
* Close Button
*/
.rbt-close {
z-index: 1 !important;
z-index: 1 !important;
}
.rbt-close-lg {
font-size: 24px !important;
font-size: 24px !important;
}
/**
* Token
*/
.rbt-token {
background-color: #e7f4ff !important;
border: 0 !important;
border-radius: .25rem !important;
color: #007bff !important;
display: inline-block !important;
line-height: 1em !important;
margin: 1px 3px 2px 0 !important;
padding: 4px 7px !important;
position: relative !important;
background-color: #e7f4ff !important;
border: 0 !important;
border-radius: 0.25rem !important;
color: #007bff !important;
display: inline-block !important;
line-height: 1em !important;
margin: 1px 3px 2px 0 !important;
padding: 4px 7px !important;
position: relative !important;
}
.rbt-token-disabled {
background-color: rgba(0, 0, 0, 0.1) !important;
color: #495057 !important;
pointer-events: none !important;
background-color: rgba(0, 0, 0, 0.1) !important;
color: #495057 !important;
pointer-events: none !important;
}
.rbt-token-removeable {
cursor: pointer !important;
padding-right: 21px !important;
cursor: pointer !important;
padding-right: 21px !important;
}
.rbt-token-active {
background-color: #007bff !important;
color: #fff !important;
outline: none !important;
text-decoration: none !important;
background-color: #007bff !important;
color: #fff !important;
outline: none !important;
text-decoration: none !important;
}
.rbt-token .rbt-token-remove-button {
bottom: 0 !important;
color: inherit !important;
font-size: inherit !important;
font-weight: normal !important;
opacity: 1 !important;
outline: none !important;
padding: 3px 7px !important;
position: absolute !important;
right: 0 !important;
text-shadow: none !important;
top: -2px !important;
bottom: 0 !important;
color: inherit !important;
font-size: inherit !important;
font-weight: normal !important;
opacity: 1 !important;
outline: none !important;
padding: 3px 7px !important;
position: absolute !important;
right: 0 !important;
text-shadow: none !important;
top: -2px !important;
}
/**
* Loader + CloseButton container
*/
.rbt-aux {
align-items: center !important;
display: flex !important;
bottom: 0 !important;
justify-content: center !important;
pointer-events: none !important;
/* Don't block clicks on the input */
position: absolute !important;
right: 0 !important;
top: 0 !important;
width: 34px !important;
align-items: center !important;
display: flex !important;
bottom: 0 !important;
justify-content: center !important;
pointer-events: none !important;
/* Don't block clicks on the input */
position: absolute !important;
right: 0 !important;
top: 0 !important;
width: 34px !important;
}
.rbt-aux-lg {
width: 46px !important;
width: 46px !important;
}
.rbt-aux .rbt-close {
margin-top: -4px !important;
pointer-events: auto !important;
/* Override pointer-events: none; above */
margin-top: -4px !important;
pointer-events: auto !important;
/* Override pointer-events: none; above */
}
.has-aux .rbt-input {
padding-right: 34px !important;
padding-right: 34px !important;
}
.rbt-highlight-text {
background-color: inherit !important;
color: inherit !important;
font-weight: bold !important;
padding: 0 !important;
background-color: inherit !important;
color: inherit !important;
font-weight: bold !important;
padding: 0 !important;
}
/**
* Input Groups
*/
.input-group > .rbt {
flex: 1 !important;
flex: 1 !important;
}
.input-group > .rbt .rbt-input-hint,
.input-group > .rbt .rbt-aux {
z-index: 5 !important;
z-index: 5 !important;
}
.input-group > .rbt:not(:first-child) .form-control {
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
}
.input-group > .rbt:not(:last-child) .form-control {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
+2 -2
View File
@@ -58,7 +58,7 @@ $placeholder-color: #999;
}
// Safari and Chrome
&::-webkit-input-placeholder {
&::-webkit-input-placeholder {
color: $placeholder-color;
}
}
@@ -237,4 +237,4 @@ $placeholder-color: #999;
to {
transform: rotate(1turn);
}
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+1 -51
View File
@@ -1,51 +1 @@
/* color of input fields */
div.timely input.form-control {
color: #c7d0d9;
background-color: #0b0c0e;
}
div.timely .dropdown-item {
color: #C7D0D9;
background-color: #0B0C0E;
}
div.timely .dropdown-item-text {
color: #C7D0D9;
background-color: #0B0C0E;
}
div.timely .dropdown-item:hover, .dropdown-item:focus {
background-color: #4F5255;
}
div.timely .dropdown-item.active, .dropdown-item:active {
background-color: #4F5255;
}
div.timely .dropdown-item.disabled, .dropdown-item:disabled {
color: #0B0C0E;
}
div.timely .dropdown-header {
color: #0B0C0E;
}
div.timely .dropdown-menu {
background-color: #0B0C0E;
box-shadow: 0px 2px 2px 2px #31343b;
}
div.timely input.form-control:focus {
outline: 0;
box-shadow: 0px 0px 0px 2px #141619, 0px 0px 0px 4px #1F60C4;
outline-offset: 2px;
transition: all 0.2s cubic-bezier(0.19, 1, 0.22, 1) 0s;
}
/* color of highlighted text in autocomplete */
div.timely mark.rbt-highlight-text {
background: linear-gradient(90deg, #56585C, #4c5057);
color: #ff0;
}
/*# sourceMappingURL=dark.css.map*/
div.timely .dropdown-item,div.timely .dropdown-item-text,div.timely input.form-control{color:#c7d0d9;background-color:#0b0c0e}.dropdown-item:active,.dropdown-item:focus,div.timely .dropdown-item.active,div.timely .dropdown-item:hover{background-color:#4f5255}.dropdown-item:disabled,div.timely .dropdown-header,div.timely .dropdown-item.disabled{color:#0b0c0e}div.timely .dropdown-menu{background-color:#0b0c0e;box-shadow:0 2px 2px 2px #31343b}div.timely input.form-control:focus{color:#c7d0d9;outline:0;box-shadow:0 0 0 2px #141619,0 0 0 4px #1f60c4;outline-offset:2px;transition:all .2s cubic-bezier(.19,1,.22,1) 0s}div.timely mark.rbt-highlight-text{background:linear-gradient(90deg,#56585c,#4c5057);color:#ff0}
-1
View File
@@ -1 +0,0 @@
{"version":3,"sources":["webpack:///dark.css"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B;IACI,cAAc;IACd,yBAAyB;AAC7B;;AAEA;IACI,cAAc;IACd,yBAAyB;AAC7B;;AAEA;IACI,cAAc;IACd,yBAAyB;AAC7B;;AAEA;IACI,yBAAyB;AAC7B;;AAEA;IACI,yBAAyB;AAC7B;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,yBAAyB;IACzB,mCAAmC;AACvC;;AAEA;IACI,UAAU;IACV,4DAA4D;IAC5D,mBAAmB;IACnB,sDAAsD;AAC1D;;AAEA,8CAA8C;AAC9C;IACI,oDAAoD;IACpD,WAAW;AACf,C","file":"styles/dark.css","sourcesContent":["/* color of input fields */\ndiv.timely input.form-control {\n color: #c7d0d9;\n background-color: #0b0c0e;\n}\n\ndiv.timely .dropdown-item {\n color: #C7D0D9;\n background-color: #0B0C0E;\n}\n\ndiv.timely .dropdown-item-text {\n color: #C7D0D9;\n background-color: #0B0C0E;\n}\n\ndiv.timely .dropdown-item:hover, .dropdown-item:focus {\n background-color: #4F5255;\n}\n\ndiv.timely .dropdown-item.active, .dropdown-item:active {\n background-color: #4F5255;\n}\n\ndiv.timely .dropdown-item.disabled, .dropdown-item:disabled {\n color: #0B0C0E;\n}\n\ndiv.timely .dropdown-header {\n color: #0B0C0E;\n}\n\ndiv.timely .dropdown-menu {\n background-color: #0B0C0E;\n box-shadow: 0px 2px 2px 2px #31343b;\n}\n\ndiv.timely input.form-control:focus {\n outline: 0;\n box-shadow: 0px 0px 0px 2px #141619, 0px 0px 0px 4px #1F60C4;\n outline-offset: 2px;\n transition: all 0.2s cubic-bezier(0.19, 1, 0.22, 1) 0s;\n}\n\n/* color of highlighted text in autocomplete */\ndiv.timely mark.rbt-highlight-text {\n background: linear-gradient(90deg, #56585C, #4c5057);\n color: #ff0;\n}"],"sourceRoot":""}
+1 -50
View File
@@ -1,50 +1 @@
/* color of input fields */
div.timely input.form-control {
color: #464C54;
background-color: #FFFFFF;
}
div.timely .dropdown-item {
color: #464C54;
}
div.timely .dropdown-item-text {
color: #464C54;
}
div.timely .dropdown-item:hover, .dropdown-item:focus {
color: #464C54;
background-color: #E3E6E9;
}
div.timely .dropdown-item.active, .dropdown-item:active {
color: #464C54;
background-color: #E3E6E9;
}
div.timely .dropdown-item.disabled, .dropdown-item:disabled {
color: #abadaf;
}
div.timely .dropdown-header {
color: #464C54;
}
div.timely .dropdown-menu {
box-shadow: 0px 4px 2px 0px #cbcbcb;
}
div.timely input.form-control:focus {
outline: 0;
box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #5794f2;
outline-offset: 2px;
transition: all 0.2s cubic-bezier(0.19, 1, 0.22, 1) 0s;
}
/* color of highlighted text in autocomplete */
div.timely mark.rbt-highlight-text {
background: linear-gradient(90deg, #bfc0c1, #abadaf);
color: #ff0;
}
/*# sourceMappingURL=light.css.map*/
div.timely input.form-control{color:#464c54;background-color:#fff}div.timely .dropdown-item,div.timely .dropdown-item-text{color:#464c54}.dropdown-item:active,.dropdown-item:focus,div.timely .dropdown-item.active,div.timely .dropdown-item:hover{color:#464c54;background-color:#e3e6e9}.dropdown-item:disabled,div.timely .dropdown-item.disabled{color:#abadaf}div.timely .dropdown-header{color:#464c54}div.timely .dropdown-menu{box-shadow:0 4px 2px 0 #cbcbcb}div.timely input.form-control:focus{color:#464c54;outline:0;box-shadow:0 0 0 2px #fff,0 0 0 4px #5794f2;outline-offset:2px;transition:all .2s cubic-bezier(.19,1,.22,1) 0s}div.timely mark.rbt-highlight-text{background:linear-gradient(90deg,#bfc0c1,#abadaf);color:#ff0}
-1
View File
@@ -1 +0,0 @@
{"version":3,"sources":["webpack:///light.css"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B;IACI,cAAc;IACd,yBAAyB;AAC7B;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;IACd,yBAAyB;AAC7B;;AAEA;IACI,cAAc;IACd,yBAAyB;AAC7B;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,mCAAmC;AACvC;;AAEA;IACI,UAAU;IACV,4DAA4D;IAC5D,mBAAmB;IACnB,sDAAsD;AAC1D;;AAEA,8CAA8C;AAC9C;IACI,oDAAoD;IACpD,WAAW;AACf,C","file":"styles/light.css","sourcesContent":["/* color of input fields */\ndiv.timely input.form-control {\n color: #464C54;\n background-color: #FFFFFF;\n}\n\ndiv.timely .dropdown-item {\n color: #464C54;\n}\n\ndiv.timely .dropdown-item-text {\n color: #464C54;\n}\n\ndiv.timely .dropdown-item:hover, .dropdown-item:focus {\n color: #464C54;\n background-color: #E3E6E9;\n}\n\ndiv.timely .dropdown-item.active, .dropdown-item:active {\n color: #464C54;\n background-color: #E3E6E9;\n}\n\ndiv.timely .dropdown-item.disabled, .dropdown-item:disabled {\n color: #abadaf;\n}\n\ndiv.timely .dropdown-header {\n color: #464C54;\n}\n\ndiv.timely .dropdown-menu {\n box-shadow: 0px 4px 2px 0px #cbcbcb;\n}\n\ndiv.timely input.form-control:focus {\n outline: 0;\n box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #5794f2;\n outline-offset: 2px;\n transition: all 0.2s cubic-bezier(0.19, 1, 0.22, 1) 0s;\n}\n\n/* color of highlighted text in autocomplete */\ndiv.timely mark.rbt-highlight-text {\n background: linear-gradient(90deg, #bfc0c1, #abadaf);\n color: #ff0;\n}"],"sourceRoot":""}
Binary file not shown.
Binary file not shown.
+5 -7
View File
@@ -3,11 +3,9 @@ module github.com/NationalSecurityAgency/timely-datasource
go 1.14
require (
github.com/ericgio/react-bootstrap-typeahead v4.2.3+incompatible // indirect
github.com/grafana/grafana v1.9.2-0.20200515143030-aee1438ff2f7
github.com/grafana/grafana-plugin-sdk-go v0.65.0
github.com/hashicorp/go-hclog v0.14.1
github.com/prometheus/common v0.7.0
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
golang.org/x/net v0.0.0-20200202094626-16171245cfb2
github.com/grafana/grafana-plugin-sdk-go v0.111.0
github.com/hashicorp/go-hclog v0.16.1
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/prometheus/common v0.29.0 // indirect
golang.org/x/net v0.17.0 // indirect
)
+530 -184
View File
@@ -1,434 +1,780 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
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=
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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/mysqlerr v0.0.0-20170204212430-6c6b55f8796f/go.mod h1:f3HiCrHjHBdcm6E83vGaXh1KomZMA2P6aeo3hKx/wg0=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
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 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/arrow/go/arrow v0.0.0-20200403134915-89ce1cadb678 h1:R72+9UXiP7TnpTAdznM1okjzyqb3bzopSA7HCP7p3gM=
github.com/apache/arrow/go/arrow v0.0.0-20200403134915-89ce1cadb678/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/apache/arrow/go/arrow v0.0.0-20210223225224-5bea62493d91 h1:rbe942bXzd2vnds4y9fYQL8X4yFltXoZsKW7KtG+TFM=
github.com/apache/arrow/go/arrow v0.0.0-20210223225224-5bea62493d91/go.mod h1:c9sxoIT3YgLxH4UhLOCKaBlEojuMhVYpk4Ntv3opUTQ=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/aws/aws-sdk-go v1.29.20/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
github.com/beevik/etree v1.0.1/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/benbjohnson/clock v0.0.0-20161215174838-7dc76406b6d3/go.mod h1:UMqtWQTnOe4byzwe7Zhwh8f8s+36uszN51sJrSIZlTE=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
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/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/crewjam/saml v0.0.0-20191031171751-c42136edf9b1/go.mod h1:pzACCdpqjQKTvpPZs5P3FzFNQ+RSOJX5StwHwh7ZUgw=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
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/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
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.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ericgio/react-bootstrap-typeahead v1.4.2 h1:o5xc7QpIIau6rMF3bLCpjvqrKZMOShMq0Gv3O12cNSg=
github.com/ericgio/react-bootstrap-typeahead v4.2.3+incompatible h1:a+CttlKZj5lC7wUv7xl+XVJdtkAHN+lkjWELxuKtKKU=
github.com/ericgio/react-bootstrap-typeahead v4.2.3+incompatible/go.mod h1:JprI4nOtRQjx4voESyHoru4vTBPWxLZb6TAFcFOaRKg=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/inject v0.0.0-20180706035515-f23751cae28b/go.mod h1:oO8UHw+fDHjDsk4CTy/E96WDzFUYozAtBAaGNoVL0+c=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/facebookgo/structtag v0.0.0-20150214074306-217e25fb9691/go.mod h1:sKLL1iua/0etWfo/nPCmyz+v2XDMXy+Ho53W7RAuZNY=
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
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/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
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-macaron/binding v0.0.0-20190806013118-0b4f37bab25b/go.mod h1:AG8Z6qkQM8s47aUDJOco/SNwJ8Czif2hMm7rc0abDog=
github.com/go-macaron/gzip v0.0.0-20160222043647-cad1c6580a07/go.mod h1://cJFfDp/70L0oTNAMB+M8Jd0rpuIx/55iARuJ6StwE=
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI=
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw=
github.com/go-macaron/session v0.0.0-20190805070824-1a3cdc6f5659 h1:YXDFNK98PgKeBd+xM2Babdd6gyABG8H+SSAh5+hr0os=
github.com/go-macaron/session v0.0.0-20190805070824-1a3cdc6f5659/go.mod h1:tLd0QEudXocQckwcpCq5pCuTCuYc24I0bRJDuRe9OuQ=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
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.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
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=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1 h1:jAbXjIeW2ZSW2AwFxlGTDoc2CjI2XujLkV3ArsZFCvc=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/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 v1.11.0 h1:O7CEyB8Cb3/DmtxODGtLHcEvpr81Jm5qLg/hsHnxA2A=
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/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-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gosimple/slug v1.4.2 h1:jDmprx3q/9Lfk4FkGZtvzDQ9Cj9eAmsjzeQGp24PeiQ=
github.com/gosimple/slug v1.4.2/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0=
github.com/grafana/grafana v1.9.2-0.20200515143030-aee1438ff2f7 h1:2cz906lNJc9lOMXxYWCs/64CYKM06TBxGTYsTav1w7k=
github.com/grafana/grafana v1.9.2-0.20200515143030-aee1438ff2f7/go.mod h1:cEzI5frGJaiLFg6b1vUEu3WTGQ3gv6C3cKjsHQlAW04=
github.com/grafana/grafana v6.1.6+incompatible/go.mod h1:U8QyUclJHj254BFcuw45p6sg7eeGYX44qn1ShYo5rGE=
github.com/grafana/grafana-plugin-model v0.0.0-20190930120109-1fc953a61fb4/go.mod h1:nc0XxBzjeGcrMltCDw269LoWF9S8ibhgxolCdA1R8To=
github.com/grafana/grafana-plugin-sdk-go v0.60.0 h1:9IhNRdoaRi2RQflmNQHv2VuqXRGigpLacoYHHXZ+XBU=
github.com/grafana/grafana-plugin-sdk-go v0.60.0/go.mod h1:V3mq3GjPrIOc4K9jOm3mP5scJQgx9NJaYQ3cUlxm8vE=
github.com/grafana/grafana-plugin-sdk-go v0.62.0 h1:b4n8bCKCUR3mbQLQcU5xSHkN/wRO+gOC/oiEo2ewur0=
github.com/grafana/grafana-plugin-sdk-go v0.62.0/go.mod h1:w855JyiC5PDP3naWUJP0h/vY8RlzlE4+4fodyoXph+4=
github.com/grafana/grafana-plugin-sdk-go v0.65.0 h1:l6cPKCFxf3AN3gd7Sprum2TuhcqsGI98Xa/1dDuin9E=
github.com/grafana/grafana-plugin-sdk-go v0.65.0/go.mod h1:w855JyiC5PDP3naWUJP0h/vY8RlzlE4+4fodyoXph+4=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grafana/grafana-plugin-sdk-go v0.111.0 h1:7eqLgAdDYeELVokRCeDEobYQJy5/E5C43tZkb/xH66Q=
github.com/grafana/grafana-plugin-sdk-go v0.111.0/go.mod h1:D7x3ah+1d4phNXpbnOaxa/osSaZlwh9/ZUnGGzegRbk=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
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/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd h1:rNuUHR+CvK1IS89MMtcF0EpcVMZtjKfPRp4MEmt/aTs=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
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-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-plugin v1.2.2 h1:mgDpq0PkoK5gck2w4ivaMpWRHv/matdOR4xmeScmf/w=
github.com/hashicorp/go-plugin v1.2.2/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
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/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec h1:CGkYB1Q7DSsH/ku+to+foV4agt2F2miquaLUgF6L178=
github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.10.1/go.mod h1:s/VXv+TdctEOx2wCEguezYaR7f0OwUAd6H9VGfRkcSs=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
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.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
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=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/linkedin/goavro/v2 v2.9.7/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
github.com/magefile/mage v1.9.0 h1:t3AU2wNwehMCW97vuqQLtw6puppWXHO+O2MHo5a50XE=
github.com/magefile/mage v1.9.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/mattetti/filebuffer v1.0.0 h1:ixTvQ0JjBTwWbdpDZ98lLrydo7KRi8xNRIi5RFszsbY=
github.com/mattetti/filebuffer v1.0.0/go.mod h1:X6nyAIge2JGVmuJt2MFCqmHrb/5IHiphfHtot0s5cnI=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls=
github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
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.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/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 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
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/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
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/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.23.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE=
github.com/prometheus/common v0.29.0/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.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/russellhaering/goxmldsig v0.0.0-20180430223755-7acd5e4a6ef7/go.mod h1:Oz4y6ImuOQZxynhbSXk7btjEfNBtGlj2dcaOvXl2FSM=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
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-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
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/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ75iPqWZc0HeJWFYNCvKsfpQwFpRNTA=
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0=
github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff h1:QCdUBuN+iKWAB9HqPTkBwyKPPUHDobJ2AuELSNZwd4o=
github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff/go.mod h1:m7kjsbCuO4QKP3KLfnxiUZWiOiFXmxj30HeexjL3lc0=
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329/go.mod h1:OBcG9bn7sHtXgarhUEb3OfCnNsgtGnkVf41ilSZ3K3E=
github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/xorcare/pointer v1.1.0 h1:sFwXOhRF8QZ0tyVZrtxWGIoVZNEmRzBCaFWdONPQIUM=
github.com/xorcare/pointer v1.1.0/go.mod h1:6KLhkOh6YbuvZkT4YbxIbR/wzLBjyMxOiNzZhJTor2Y=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
github.com/zenazn/goji v0.9.1-0.20160507202103-64eb34159fe5/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
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.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
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.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190325154230-a5d413f7728c/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-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+UgTgQZ4pMLzXxi1pSt+/Y=
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
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-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/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
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=
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/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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190125091013-d26f9f9a57f3/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-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/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-20200904194848-62affa334b73/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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
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 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/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-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/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-20190826190057-c7b8b68b1456/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-20191220142924-d4481acd189f h1:68K/z8GLUxV76xGSqwTWw2gyk/jwn79LUL43rES2g8o=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
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-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-20200909081042-eff7692f9009/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-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/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-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-20190328211700-ab21143f2384/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-20190802220118-1d1727260058/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
golang.org/x/tools v0.0.0-20190805222050-c5a2fd39b72a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
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-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/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-20191213221258-04c2e8eff935/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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-20200103221440-774c71fcf114/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.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
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=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
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.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
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-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
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-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
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-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-20200911024640-645f7a48b24f h1:Yv4xsIx7HZOoyUGSJ2ksDyWE2qIBXROsZKt2ny3hCGM=
google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
google.golang.org/grpc v1.23.1/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=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
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.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.37.1 h1:ARnQJNWxGyYJpdf/JXscNlQr/uv607ZPU9Z7ogHi+iI=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200910201057-6591123024b3/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfzYWe577fCe7Ceci+6qjO2Rdc0Z4=
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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag=
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
gopkg.in/macaron.v1 v1.3.4 h1:HvIscOwxhFhx3swWM/979wh2QMYyuXrNmrF9l+j3HZs=
gopkg.in/macaron.v1 v1.3.4/go.mod h1:/RoHTdC8ALpyJ3+QR36mKjwnT1F1dyYtsGM9Ate6ZFI=
gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/redis.v2 v2.3.2/go.mod h1:4wl9PJ/CqzeHk3LVq1hNLHH8krm3+AXEgut4jVc++LU=
gopkg.in/redis.v5 v5.2.9/go.mod h1:6gtv0/+A4iM08kdRfocWYB3bLX2tebpNtfKlFT6H4mY=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/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 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
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/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 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
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=
xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU=
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
xorm.io/core v0.7.3/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
xorm.io/xorm v0.8.1/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY=
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/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
+20 -17
View File
@@ -1,6 +1,6 @@
{
"name": "timely-datasource",
"version": "1.3.0",
"version": "2.0.0",
"description": "Timely",
"backend": true,
"alerting": true,
@@ -14,26 +14,29 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"devDependencies": {
"@grafana/toolkit": "^7.2.0"
"@grafana/toolkit": "^8.4.5"
},
"engines": {
"node": ">=12 <13"
"node": ">=12 <17"
},
"dependencies": {
"@grafana/data": "7.2.0",
"@grafana/runtime": "7.2.0",
"@grafana/slate-react": "0.22.9-grafana",
"@grafana/ui": "7.2.0",
"@material-ui/core": "^4.10.2",
"@types/classnames": "2.2.6",
"@types/lodash": "latest",
"@types/react-bootstrap-typeahead": "^3.4.6",
"@types/slate-plain-serializer": "0.7.0",
"@types/slate-react": "0.22.9",
"classnames": "2.2.6",
"dayjs": "^1.8.28",
"@grafana/data": "^8.4.5",
"@grafana/runtime": "^8.4.5",
"@grafana/slate-react": "0.22.10-grafana",
"@grafana/ui": "^8.4.5",
"@material-ui/core": "^4.12.3",
"@types/classnames": "2.3.1",
"@types/lodash": "4.14.176",
"@types/react-bootstrap-typeahead": "5.1.8",
"@types/slate-plain-serializer": "0.7.1",
"@types/slate-react": "0.50.1",
"classnames": "2.3.1",
"dayjs": "1.10.7",
"react-bootstrap-typeahead": "5.1.1",
"rxjs": "6.6.2",
"slate-plain-serializer": "0.7.0"
"rxjs": "7.3.0",
"slate-plain-serializer": "0.7.13",
"tmpl": "1.0.5",
"tslib": "^2.3.1",
"ws": "5.2.3"
}
}
-87
View File
@@ -1,87 +0,0 @@
package main
import (
"context"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
)
type TimelyDatasourceInstanceSettings struct {
}
func newDataSourceInstance(setting backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return &TimelyDatasourceInstanceSettings{
}, nil
}
func (s *TimelyDatasourceInstanceSettings) Dispose() {
// Called before creating a new instance to allow plugin authors
// to cleanup.
}
func getServeOpts() datasource.ServeOpts {
// creates a instance manager for your plugin. The function passed
// into `NewInstanceManger` is called when the instance is created
// for the first time or when a datasource configuration changed.
im := datasource.NewInstanceManager(newDataSourceInstance)
ds := &TimelyDatasource{
im: im,
}
return datasource.ServeOpts{
QueryDataHandler: ds,
CheckHealthHandler: ds,
CallResourceHandler: ds,
}
}
func (ds *TimelyDatasource) getSettings(pluginContext backend.PluginContext) (*TimelyDatasourceInstanceSettings, error) {
iface, err := ds.im.Get(pluginContext)
if err != nil {
return nil, err
}
return iface.(*TimelyDatasourceInstanceSettings), nil
}
// QueryData handles multiple queries and returns multiple responses.
// req contains the queries []DataQuery (where each query contains RefID as a unique identifer).
// The QueryDataResponse contains a map of RefID to the response for each query, and each response
// contains Frames ([]*Frame).
func (td *TimelyDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// create response struct
response := backend.NewQueryDataResponse()
// loop over queries and execute them individually.
for _, q := range req.Queries {
res, error := td.Query(req, q)
if error != nil {
errorResponse := backend.DataResponse{
Error: error,
}
response.Responses[q.RefID] = errorResponse
} else {
// save the response in a hashmap
// based on with RefID as identifier
response.Responses[q.RefID] = *res
}
}
return response, nil
}
// CheckHealth handles health checks sent from Grafana to the plugin.
// The main use case for these health checks is the test button on the
// datasource configuration page which allows users to verify that
// a datasource is working as expected.
func (td *TimelyDatasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
var status = backend.HealthStatusOk
var message = ""
return &backend.CheckHealthResult{
Status: status,
Message: message,
}, nil
}
-20
View File
@@ -1,20 +0,0 @@
package main
import (
"os"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
)
func main() {
// Start listening to requests send from Grafana. This call is blocking so
// it wont finish until Grafana shutsdown the process or the plugin choose
// to exit close down by itself
err := datasource.Serve(getServeOpts())
// Log any error if we could start the plugin.
if err != nil {
logger.Error(err.Error())
os.Exit(1)
}
}
-81
View File
@@ -1,81 +0,0 @@
package main
import (
"bytes"
"context"
"encoding/json"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
func (ds *TimelyDatasource) CallResource(ctx context.Context, request *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if (request.Body == nil) {
logger.Debug("CallResource", "Path", request.Path, "URL", request.URL)
} else {
logger.Debug("CallResource", "Path", request.Path, "URL", request.URL, "Body", string(request.Body))
}
var response backend.CallResourceResponse
pluginContext := request.PluginContext
var httpResponse *http.Response;
var timelyDataSourceOptions TimelyDataSourceOptions
err := json.Unmarshal(pluginContext.DataSourceInstanceSettings.JSONData, &timelyDataSourceOptions)
if err != nil {
logger.Error("Error unmarshalling datasource JSONData", "error", err)
return err
}
httpClient, err := GetHttpClient(timelyDataSourceOptions, true)
if err != nil {
logger.Error("Error getting httpClient", "error", err)
return err
}
if strings.HasPrefix(request.Path, "/api/aggregators") ||
strings.HasPrefix(request.Path, "/api/suggest") ||
strings.HasPrefix(request.Path, "/api/search/lookup") {
if (request.Method == "GET") {
var x = strings.Index(request.URL, request.Path);
finalParams := "";
if (x > -1) {
params := request.URL[x+len(request.Path) : len(request.URL)];
if (len(params) > 0 && strings.HasPrefix(params, "?")) {
finalParams = params;
}
}
url, err := url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + timelyDataSourceOptions.HttpsPort + request.Path + finalParams);
if err != nil {
return err
}
httpResponse, err = httpClient.Get(url.String())
} else if (request.Method == "POST") {
url, err := url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + timelyDataSourceOptions.HttpsPort + request.Path);
if err != nil {
return err
}
httpResponse, err = httpClient.Post(url.String(), "application/json", bytes.NewReader(request.Body))
}
if err != nil {
logger.Error("Error calling for resource", "Path", request.Path, "error", err)
return err
}
bytes, err := ioutil.ReadAll(httpResponse.Body)
if err != nil {
logger.Error("Error reading resource", "Path", request.Path, "error", err)
return err
}
response.Status = 200
response.Body = bytes
} else {
// no matching resource
response.Status = 404
}
sender.Send(&response)
return nil
}
+502 -289
View File
@@ -1,313 +1,526 @@
package main
import (
"bytes"
"crypto/tls"
"crypto/x509"
"fmt"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/hashicorp/go-hclog"
"sort"
"strconv"
"time"
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"sort"
"strconv"
"strings"
"sync"
"time"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/hashicorp/go-hclog"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
)
var (
logger = hclog.New(&hclog.LoggerOptions{
// Use debug as level since anything less severe is suppressed.
Level: hclog.Debug,
// Use JSON format to make the output in Grafana format and work
// when using multiple arguments such as Debug("message", "key", "value").
JSONFormat: true,
Name: "timely",
})
logger = hclog.New(&hclog.LoggerOptions{
// Use debug as level since anything less severe is suppressed.
Level: hclog.Debug,
// Use JSON format to make the output in Grafana format and work
// when using multiple arguments such as Debug("message", "key", "value").
JSONFormat: true,
Name: "timely",
})
)
func init() {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
// TimelyDatasource is an example datasource used to scaffold
// new datasource plugins with an backend.
type TimelyDatasource struct {
// The instance manager can help with lifecycle management
// of datasource instances in plugins. It's not a requirements
// but a best practice that we recommend that you follow.
im instancemgmt.InstanceManager
im instancemgmt.InstanceManager
Certificate *tls.Certificate
CertPool *x509.CertPool
ClientCertificatePath string
ClientKeyPath string
CertificateAuthorityPath string
Mutex *sync.Mutex
}
func (dataSource *TimelyDatasource) Query(queryDataRequest *backend.QueryDataRequest, dataQuery backend.DataQuery) (*backend.DataResponse, error) {
timelyRequest := TimelyRequest {
MsResolution: true,
GlobalAnnotations: true,
Start: dataQuery.TimeRange.From.Unix() * 1000,
End: dataQuery.TimeRange.To.Unix() * 1000,
}
var timelyQueryForm TimelyQueryForm
var timelyQueryServer TimelyQueryServer
var err error
var isUser bool
if queryDataRequest.PluginContext.User == nil {
isUser = false
err = json.Unmarshal(dataQuery.JSON, &timelyQueryServer)
if err == nil {
timelyQueryForm = TimelyQueryForm {
Metric: timelyQueryServer.Metric,
Aggregator: timelyQueryServer.Aggregator,
DisableDownsampling: timelyQueryServer.DisableDownsampling,
DownsampleAggregator: timelyQueryServer.DownsampleAggregator,
DownsampleFillPolicy: timelyQueryServer.DownsampleFillPolicy,
DownsampleInterval: timelyQueryServer.DownsampleInterval,
Tags: timelyQueryServer.Tags,
Filters: timelyQueryServer.Filters,
ShouldComputeRate: timelyQueryServer.ShouldComputeRate,
IsCounter: timelyQueryServer.IsCounter,
CounterMax: timelyQueryServer.CounterMax,
CounterResetValue: timelyQueryServer.CounterResetValue,
Tsuids: timelyQueryServer.Tsuids,
QueryType: timelyQueryServer.QueryType,
RefId: timelyQueryServer.RefId,
}
}
} else {
isUser = true
err = json.Unmarshal(dataQuery.JSON, &timelyQueryForm)
}
if err != nil {
logger.Error("Failed parsing timelyQuery", "error", err)
return nil, err
}
timelyQuery := dataSource.convertTimelyQuery(&timelyQueryForm)
timelyRequest.Queries = append(timelyRequest.Queries, *timelyQuery)
logger.Debug("Query", "timelyRequest", timelyRequest)
var timelyDatasourceOptions TimelyDataSourceOptions
err = json.Unmarshal(queryDataRequest.PluginContext.DataSourceInstanceSettings.JSONData, &timelyDatasourceOptions)
if err != nil {
logger.Error("Error unmarshalling datasource JSONData", "error", err)
return nil, err
}
var httpRequest *http.Request
httpRequest, err = dataSource.createRequest(timelyDatasourceOptions, timelyRequest)
if err != nil {
logger.Error("Error creating httpRequest", "error", err)
return nil, err
}
oauthToken, tokenExists := queryDataRequest.Headers["Authorization"]
if tokenExists {
logger.Debug("Adding Authorization:" + oauthToken)
httpRequest.Header.Add("Authorization", oauthToken)
}
var useClientCertIfAvailable = !isUser || (!tokenExists && timelyDatasourceOptions.UseClientCertWhenOAuthMissing)
httpClient, err := GetHttpClient(timelyDatasourceOptions, useClientCertIfAvailable)
if err != nil {
return nil, err
}
res, err := httpClient.Do(httpRequest)
if err != nil {
logger.Error("Error executing query", "error", err)
return nil, err
}
return dataSource.parseResponse(res)
type TimelyDatasourceInstanceSettings struct {
}
func (e *TimelyDatasource) createRequest(tdo TimelyDataSourceOptions, data TimelyRequest) (*http.Request, error) {
u, err := url.Parse("https://" + tdo.TimelyHost + ":" + tdo.HttpsPort + "/api/query")
if err != nil {
logger.Error("Failed creating query url", "error", err)
return nil, fmt.Errorf("Failed creating query url. error: %v", err)
}
postData, err := json.Marshal(data)
if err != nil {
logger.Error("Failed marshaling data", "error", err)
return nil, fmt.Errorf("Failed to create request. error: %v", err)
}
req, err := http.NewRequest(http.MethodPost, u.String(), bytes.NewReader(postData))
if err != nil {
logger.Error("Failed to create request", "error", err)
return nil, fmt.Errorf("Failed to create request. error: %v", err)
}
req.Header.Set("Content-Type", "application/json")
requestData, err := json.Marshal(data)
if err != nil {
logger.Error("Failed marshaling request", "error", err)
} else {
logger.Info("Created query request: " + string(requestData))
}
return req, err
func newDataSourceInstance(setting backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return &TimelyDatasourceInstanceSettings{}, nil
}
func (e *TimelyDatasource) parseResponse(res *http.Response) (*backend.DataResponse, error) {
body, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
return nil, err
}
if res.StatusCode/100 != 2 {
var errorResponse TimelyErrorResponse
err = json.Unmarshal(body, &errorResponse)
if err != nil {
logger.Error("Query failed", "status", res.Status, "body", string(body))
return nil, fmt.Errorf("Query failed - %v: %s", res.Status, string(body))
}
logger.Error("Query failed", "status", res.Status, "message", errorResponse.Message, "detailMessage", errorResponse.DetailMessage)
return nil, fmt.Errorf("Query failed - %v [%s] [%s]", res.Status, errorResponse.Message, errorResponse.DetailMessage)
}
var object []TimelyResponse
err = json.Unmarshal(body, &object)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal Timely response - body: %s status: %v", string(body), res.Status)
}
response := backend.DataResponse{}
for _, val := range object {
var name = val.Metric;
for k, v := range val.Tags {
name = name + " " + k + "=" + v;
}
frame := data.NewFrame(name)
timestamps := make([]*time.Time, 0)
values := make([]*float64, 0)
keys := make([]int64, 0, len(val.DataPoints));
for k := range val.DataPoints {
keys = append(keys, k);
}
sort.Slice(keys, func(i, j int) bool {
return keys[i] < keys[j];
});
for _, timestampInt64 := range keys {
value := val.DataPoints[timestampInt64];
timestampTime := time.Unix(timestampInt64/1000, 0);
timestamps = append(timestamps, &timestampTime)
newValue := float64(value);
values = append(values, &newValue)
}
frame.Fields = append(frame.Fields, data.NewField("time", val.Tags, timestamps))
frame.Fields = append(frame.Fields, data.NewField(val.Metric, val.Tags, values))
response.Frames = append(response.Frames, frame)
}
// add the frames to the response
return &response, nil
func (s *TimelyDatasourceInstanceSettings) Dispose() {
// Called before creating a new instance to allow plugin authors
// to cleanup.
}
func (e *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm) *TimelyQuery {
func getServeOpts() datasource.ServeOpts {
// creates a instance manager for your plugin. The function passed
// into `NewInstanceManger` is called when the instance is created
// for the first time or when a datasource configuration changed.
im := datasource.NewInstanceManager(newDataSourceInstance)
ds := &TimelyDatasource{
im: im,
CertPool: nil,
Certificate: nil,
ClientCertificatePath: "",
ClientKeyPath: "",
CertificateAuthorityPath: "",
Mutex: &sync.Mutex{},
}
if timelyQueryForm == nil {
return nil
}
timelyQuery := TimelyQuery{
Metric: timelyQueryForm.Metric,
Aggregator: "none",
Rate: false,
RateOptions: RateOptions{},
Downsample: "60000ms-avg",
Tags: timelyQueryForm.Tags,
Filters: timelyQueryForm.Filters,
Tsuids: timelyQueryForm.Tsuids,
}
// future work - replace scopedVariables in metric, tags, filters, aggregator
timelyQuery.Aggregator = "avg"
if timelyQueryForm.Aggregator != "" {
timelyQuery.Aggregator = timelyQueryForm.Aggregator
}
if timelyQueryForm.ShouldComputeRate {
timelyQuery.Rate = true
timelyQuery.RateOptions.Counter = timelyQueryForm.IsCounter
}
if len(timelyQueryForm.CounterMax) > 0 {
counterMax, error := strconv.ParseInt(timelyQueryForm.CounterMax, 10, 32)
if error == nil {
timelyQuery.RateOptions.CounterMax = int32(counterMax)
}
}
if len(timelyQueryForm.CounterResetValue) > 0 {
counterResetValue, error := strconv.ParseInt(timelyQueryForm.CounterResetValue, 10, 32)
if error == nil {
timelyQuery.RateOptions.ResetValue = int32(counterResetValue)
}
}
if !timelyQueryForm.DisableDownsampling {
downsampleDuration, error := time.ParseDuration(timelyQueryForm.DownsampleInterval)
if error == nil {
timelyQuery.Downsample = strconv.FormatInt(downsampleDuration.Milliseconds(), 10) + "ms-" + timelyQueryForm.DownsampleAggregator
}
if len(timelyQueryForm.DownsampleFillPolicy) > 0 && timelyQueryForm.DownsampleFillPolicy != "none" {
timelyQuery.Downsample += "-" + timelyQueryForm.DownsampleFillPolicy
}
}
return &timelyQuery
return datasource.ServeOpts{
CheckHealthHandler: ds,
CallResourceHandler: ds,
QueryDataHandler: ds,
}
}
func GetHttpClient(settings TimelyDataSourceOptions, useClientCertIfAvailable bool) (*http.Client, error) {
// handle call back
logger.Debug("Getting client", "allowInsecureSsl", strconv.FormatBool(settings.AllowInsecureSsl))
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: settings.AllowInsecureSsl,
},
}
httpClient := &http.Client{
Transport: tr,
}
//func (ds *TimelyDatasource) getSettings(pluginContext backend.PluginContext) (*TimelyDatasourceInstanceSettings, error) {
// iface, err := ds.im.Get(pluginContext)
// if err != nil {
// return nil, err
// }
//
// return iface.(*TimelyDatasourceInstanceSettings), nil
//}
logger.Debug("Getting httpClient", "useClientCertIfAvailable", strconv.FormatBool(useClientCertIfAvailable))
if useClientCertIfAvailable {
if settings.ClientCertificatePath != "" || settings.ClientKeyPath != "" {
cert, err := tls.LoadX509KeyPair(settings.ClientCertificatePath, settings.ClientKeyPath)
if err != nil {
logger.Error("Failed to setup client certificate", "cert_path", settings.ClientCertificatePath, "key_path", settings.ClientKeyPath, "error", err)
return nil, fmt.Errorf("Failed to setup client certificate")
}
logger.Debug("Adding certificate", "ca_path", settings.ClientCertificatePath, "key_path", settings.ClientKeyPath)
tr.TLSClientConfig.Certificates = append(tr.TLSClientConfig.Certificates, cert)
}
}
// CheckHealth handles health checks sent from Grafana to the plugin.
// The main use case for these health checks is the test button on the
// datasource configuration page which allows users to verify that
// a datasource is working as expected.
func (td *TimelyDatasource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
var status = backend.HealthStatusOk
var message = ""
if settings.CertificateAuthorityPath != "" {
caCert, err := ioutil.ReadFile(settings.CertificateAuthorityPath)
if err != nil {
logger.Error("Failed to setup certificate authority", "ca_path", settings.CertificateAuthorityPath, "error", err)
return nil, fmt.Errorf("Failed to setup certificate authority")
}
logger.Debug("Adding CA", "ca_path", settings.CertificateAuthorityPath)
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
tr.TLSClientConfig.RootCAs = caCertPool
}
return httpClient, nil
return &backend.CheckHealthResult{
Status: status,
Message: message,
}, nil
}
func (td *TimelyDatasource) CallResource(ctx context.Context, request *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
if request.Body == nil {
logger.Debug("CallResource", "Path", request.Path, "URL", request.URL)
} else {
logger.Debug("CallResource", "Path", request.Path, "URL", request.URL, "Body", string(request.Body))
}
var response backend.CallResourceResponse
pluginContext := request.PluginContext
var httpResponse *http.Response
var timelyDataSourceOptions TimelyDataSourceOptions
err := json.Unmarshal(pluginContext.DataSourceInstanceSettings.JSONData, &timelyDataSourceOptions)
if err != nil {
logger.Error("Error unmarshalling datasource JSONData", "error", err)
return err
}
httpClient, err := td.GetHttpClient(timelyDataSourceOptions, true)
if err != nil {
logger.Error("Error getting httpClient", "error", err)
return err
}
if strings.HasPrefix(request.Path, "/api/aggregators") ||
strings.HasPrefix(request.Path, "/api/suggest") ||
strings.HasPrefix(request.Path, "/api/search/lookup") {
if request.Method == "GET" {
var x = strings.Index(request.URL, request.Path)
finalParams := ""
if x > -1 {
params := request.URL[x+len(request.Path) : len(request.URL)]
if len(params) > 0 && strings.HasPrefix(params, "?") {
finalParams = params
}
}
url, err := url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + timelyDataSourceOptions.HttpsPort + request.Path + finalParams)
if err != nil {
return err
}
httpResponse, err = httpClient.Get(url.String())
} else if request.Method == "POST" {
url, err := url.Parse("https://" + timelyDataSourceOptions.TimelyHost + ":" + timelyDataSourceOptions.HttpsPort + request.Path)
if err != nil {
return err
}
httpResponse, err = httpClient.Post(url.String(), "application/json", bytes.NewReader(request.Body))
}
if err != nil {
logger.Error("Error calling for resource", "Path", request.Path, "error", err)
return err
}
bytes, err := ioutil.ReadAll(httpResponse.Body)
if err != nil {
logger.Error("Error reading resource", "Path", request.Path, "error", err)
return err
}
response.Status = 200
response.Body = bytes
} else {
// no matching resource
response.Status = 404
}
sender.Send(&response)
return nil
}
// QueryData handles multiple queries and returns multiple responses.
// req contains the queries []DataQuery (where each query contains RefID as a unique identifer).
// The QueryDataResponse contains a map of RefID to the response for each query, and each response
// contains Frames ([]*Frame).
func (td *TimelyDatasource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
// create response struct
response := backend.NewQueryDataResponse()
// loop over queries and execute them individually.
for _, q := range req.Queries {
res, error := td.Query(req, q)
if error != nil {
errorResponse := backend.DataResponse{
Error: error,
}
response.Responses[q.RefID] = errorResponse
} else {
// save the response in a hashmap
// based on with RefID as identifier
response.Responses[q.RefID] = *res
}
}
return response, nil
}
func (td *TimelyDatasource) Query(queryDataRequest *backend.QueryDataRequest, dataQuery backend.DataQuery) (*backend.DataResponse, error) {
timelyRequest := TimelyRequest{
MsResolution: true,
GlobalAnnotations: true,
Start: dataQuery.TimeRange.From.Unix() * 1000,
End: dataQuery.TimeRange.To.Unix() * 1000,
}
var timelyQueryForm TimelyQueryForm
var timelyQueryServer TimelyQueryServer
var err error
var isUser bool
if queryDataRequest.PluginContext.User == nil {
isUser = false
err = json.Unmarshal(dataQuery.JSON, &timelyQueryServer)
if err == nil {
timelyQueryForm = TimelyQueryForm{
Metric: timelyQueryServer.Metric,
Aggregator: timelyQueryServer.Aggregator,
DisableDownsampling: timelyQueryServer.DisableDownsampling,
DownsampleAggregator: timelyQueryServer.DownsampleAggregator,
DownsampleFillPolicy: timelyQueryServer.DownsampleFillPolicy,
DownsampleInterval: timelyQueryServer.DownsampleInterval,
Tags: timelyQueryServer.Tags,
Filters: timelyQueryServer.Filters,
ShouldComputeRate: timelyQueryServer.ShouldComputeRate,
IsCounter: timelyQueryServer.IsCounter,
CounterMax: timelyQueryServer.CounterMax,
CounterResetValue: timelyQueryServer.CounterResetValue,
Tsuids: timelyQueryServer.Tsuids,
QueryType: timelyQueryServer.QueryType,
RefId: timelyQueryServer.RefId,
}
}
} else {
isUser = true
err = json.Unmarshal(dataQuery.JSON, &timelyQueryForm)
}
if err != nil {
logger.Error("Failed parsing timelyQuery", "error", err)
return nil, err
}
timelyQuery := td.convertTimelyQuery(&timelyQueryForm)
timelyRequest.Queries = append(timelyRequest.Queries, *timelyQuery)
logger.Debug("Query", "timelyRequest", timelyRequest)
var timelyDatasourceOptions TimelyDataSourceOptions
err = json.Unmarshal(queryDataRequest.PluginContext.DataSourceInstanceSettings.JSONData, &timelyDatasourceOptions)
if err != nil {
logger.Error("Error unmarshalling datasource JSONData", "error", err)
return nil, err
}
var httpRequest *http.Request
httpRequest, err = td.createRequest(timelyDatasourceOptions, timelyRequest)
if err != nil {
logger.Error("Error creating httpRequest", "error", err)
return nil, err
}
oauthToken, tokenExists := queryDataRequest.Headers["Authorization"]
if tokenExists {
logger.Debug("Adding Authorization:" + oauthToken)
httpRequest.Header.Add("Authorization", oauthToken)
}
var useClientCertIfAvailable = !isUser || (!tokenExists && timelyDatasourceOptions.UseClientCertWhenOAuthMissing)
httpClient, err := td.GetHttpClient(timelyDatasourceOptions, useClientCertIfAvailable)
if err != nil {
return nil, err
}
res, err := httpClient.Do(httpRequest)
if err != nil {
logger.Error("Error executing query", "error", err)
return nil, err
}
return td.parseResponse(res)
}
func (td *TimelyDatasource) createRequest(tdo TimelyDataSourceOptions, timelyRequest TimelyRequest) (*http.Request, error) {
u, err := url.Parse("https://" + tdo.TimelyHost + ":" + tdo.HttpsPort + "/api/query")
if err != nil {
logger.Error("Failed creating query url", "error", err)
return nil, fmt.Errorf("Failed creating query url. error: %v", err)
}
postData, err := json.Marshal(timelyRequest)
if err != nil {
logger.Error("Failed marshaling timelyRequest", "error", err)
return nil, fmt.Errorf("Failed to create request. error: %v", err)
}
req, err := http.NewRequest(http.MethodPost, u.String(), bytes.NewReader(postData))
if err != nil {
logger.Error("Failed to create request", "error", err)
return nil, fmt.Errorf("Failed to create request. error: %v", err)
}
req.Header.Set("Content-Type", "application/json")
requestData, err := json.Marshal(timelyRequest)
if err != nil {
logger.Error("Failed marshaling request", "error", err)
} else {
logger.Debug("Created query request: " + string(requestData))
}
return req, err
}
func (td *TimelyDatasource) parseResponse(res *http.Response) (*backend.DataResponse, error) {
body, err := ioutil.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
return nil, err
}
if res.StatusCode/100 != 2 {
var errorResponse TimelyErrorResponse
err = json.Unmarshal(body, &errorResponse)
if err != nil {
logger.Error("Query failed", "status", res.Status, "body", string(body))
return nil, fmt.Errorf("Query failed - %v: %s", res.Status, string(body))
}
logger.Error("Query failed", "status", res.Status, "message", errorResponse.Message, "detailMessage", errorResponse.DetailMessage)
return nil, fmt.Errorf("Query failed - %v [%s] [%s]", res.Status, errorResponse.Message, errorResponse.DetailMessage)
}
var object []TimelyResponse
err = json.Unmarshal(body, &object)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal Timely response - body: %s status: %v", string(body), res.Status)
}
response := backend.DataResponse{}
for _, val := range object {
var name = val.Metric
for k, v := range val.Tags {
name = name + " " + k + "=" + v
}
frame := data.NewFrame(name)
timestamps := make([]*time.Time, 0)
values := make([]*float64, 0)
keys := make([]int64, 0, len(val.DataPoints))
for k := range val.DataPoints {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return keys[i] < keys[j]
})
for _, timestampInt64 := range keys {
value := val.DataPoints[timestampInt64]
timestampTime := time.Unix(timestampInt64/1000, 0)
timestamps = append(timestamps, &timestampTime)
newValue := float64(value)
values = append(values, &newValue)
}
frame.Fields = append(frame.Fields, data.NewField("time", val.Tags, timestamps))
frame.Fields = append(frame.Fields, data.NewField(val.Metric, val.Tags, values))
response.Frames = append(response.Frames, frame)
}
// add the frames to the response
return &response, nil
}
func (td *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm) *TimelyQuery {
if timelyQueryForm == nil {
return nil
}
timelyQuery := TimelyQuery{
Metric: timelyQueryForm.Metric,
Aggregator: "none",
Rate: false,
RateOptions: RateOptions{},
Downsample: "60000ms-avg",
Tags: timelyQueryForm.Tags,
Filters: timelyQueryForm.Filters,
Tsuids: timelyQueryForm.Tsuids,
}
// future work - replace scopedVariables in metric, tags, filters, aggregator
timelyQuery.Aggregator = "avg"
if timelyQueryForm.Aggregator != "" {
timelyQuery.Aggregator = timelyQueryForm.Aggregator
}
if timelyQueryForm.ShouldComputeRate {
timelyQuery.Rate = true
timelyQuery.RateOptions.Counter = timelyQueryForm.IsCounter
}
if len(timelyQueryForm.CounterMax) > 0 {
counterMax, error := strconv.ParseInt(timelyQueryForm.CounterMax, 10, 32)
if error == nil {
timelyQuery.RateOptions.CounterMax = int32(counterMax)
}
}
if len(timelyQueryForm.CounterResetValue) > 0 {
counterResetValue, error := strconv.ParseInt(timelyQueryForm.CounterResetValue, 10, 32)
if error == nil {
timelyQuery.RateOptions.ResetValue = int32(counterResetValue)
}
}
if !timelyQueryForm.DisableDownsampling {
downsampleDuration, error := time.ParseDuration(timelyQueryForm.DownsampleInterval)
if error == nil {
timelyQuery.Downsample = strconv.FormatInt(downsampleDuration.Milliseconds(), 10) + "ms-" + timelyQueryForm.DownsampleAggregator
}
if len(timelyQueryForm.DownsampleFillPolicy) > 0 && timelyQueryForm.DownsampleFillPolicy != "none" {
timelyQuery.Downsample += "-" + timelyQueryForm.DownsampleFillPolicy
}
}
return &timelyQuery
}
func (td *TimelyDatasource) clientSslSettingsChanged(settings TimelyDataSourceOptions) bool {
clientCertificatePath := settings.ClientCertificatePath
clientKeyPath := settings.ClientKeyPath
certificateAuthorityPath := settings.CertificateAuthorityPath
return clientCertificatePath != td.ClientCertificatePath || clientKeyPath != td.ClientKeyPath ||
certificateAuthorityPath != td.CertificateAuthorityPath
}
func (td *TimelyDatasource) GetHttpClient(settings TimelyDataSourceOptions, useClientCertIfAvailable bool) (*http.Client, error) {
// handle call back
logger.Debug("Getting client", "allowInsecureSsl", strconv.FormatBool(settings.AllowInsecureSsl))
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: settings.AllowInsecureSsl,
},
}
httpClient := &http.Client{
Transport: tr,
}
clientCertificatePath := settings.ClientCertificatePath
clientKeyPath := settings.ClientKeyPath
certificateAuthorityPath := settings.CertificateAuthorityPath
if td.clientSslSettingsChanged(settings) {
td.Mutex.Lock()
// check again to prevent double initialization
if td.clientSslSettingsChanged(settings) {
// if clientCertificatePath or clientKeyPath changed, then re-read the
// client cert into the datasource and also save the new paths
if clientCertificatePath != td.ClientCertificatePath || clientKeyPath != td.ClientKeyPath {
if clientCertificatePath != "" && clientKeyPath != "" {
cert, err := tls.LoadX509KeyPair(clientCertificatePath, clientKeyPath)
if err != nil {
logger.Error("Failed to setup client certificate", "cert_path", clientCertificatePath, "key_path", clientKeyPath, "error", err)
return nil, fmt.Errorf("Failed to setup client certificate")
}
td.Certificate = &cert
logger.Debug("Completed setup of client certificate", "cert_path", clientCertificatePath, "key_path", clientKeyPath)
} else {
// if one but not both items have been configured
if clientCertificatePath != "" || clientKeyPath != "" {
logger.Info("Both cert_path and key_path are required. Client connection updated with no client certificate.")
}
td.Certificate = nil
}
td.ClientCertificatePath = clientCertificatePath
td.ClientKeyPath = clientKeyPath
}
// if certificateAuthorityPath changed, then re-read the
// certificate authority into the datasource and also save the new path
if certificateAuthorityPath != td.CertificateAuthorityPath {
if certificateAuthorityPath != "" {
caCert, err := ioutil.ReadFile(certificateAuthorityPath)
if err != nil {
logger.Error("Failed to setup certificate authority", "ca_path", certificateAuthorityPath, "error", err)
return nil, fmt.Errorf("Failed to setup certificate authority")
}
td.CertPool = x509.NewCertPool()
td.CertPool.AppendCertsFromPEM(caCert)
logger.Debug("Completed setup of certificate authority", "ca_path", certificateAuthorityPath)
} else {
logger.Debug("Client connection updated with no certificate authority")
td.CertPool = nil
}
td.CertificateAuthorityPath = certificateAuthorityPath
}
}
td.Mutex.Unlock()
}
// protect against changes in-progress
td.Mutex.Lock()
if useClientCertIfAvailable && td.Certificate != nil {
tr.TLSClientConfig.Certificates = append(tr.TLSClientConfig.Certificates, *td.Certificate)
}
if td.CertPool != nil {
tr.TLSClientConfig.RootCAs = td.CertPool
}
td.Mutex.Unlock()
return httpClient, nil
}
func main() {
// Start listening to requests send from Grafana. This call is blocking so
// it wont finish until Grafana shutsdown the process or the plugin choose
// to exit close down by itself
err := datasource.Serve(getServeOpts())
// Log any error if we could not start the plugin.
if err != nil {
logger.Error("Plugin failed to start", "error", err)
os.Exit(1)
}
}
+49 -79
View File
@@ -1,35 +1,33 @@
import { DataSourcePluginOptionsEditorProps } from "@grafana/data";
import { LegacyForms } from "@grafana/ui";
import { ChangeEvent, PureComponent } from "react";
import { TimelyDataSourceOptions } from "./types";
import React from "react";
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { LegacyForms } from '@grafana/ui';
import { TimelyDataSourceOptions } from './types';
import * as React from 'react';
const { FormField, Switch } = LegacyForms;
interface Props
extends DataSourcePluginOptionsEditorProps<TimelyDataSourceOptions> {}
interface Props extends DataSourcePluginOptionsEditorProps<TimelyDataSourceOptions> {}
interface State {}
export class ConfigEditor extends PureComponent<Props, State> {
export class ConfigEditor extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
}
onTimelyHostChange = (event: ChangeEvent<HTMLInputElement>) => {
onTimelyHostChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
timelyHost: event.target.value
timelyHost: event.target.value,
};
onOptionsChange({ ...options, jsonData });
};
onHttpsPortChange = (event: ChangeEvent<HTMLInputElement>) => {
onHttpsPortChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
httpsPort: event.target.value
httpsPort: event.target.value,
};
onOptionsChange({ ...options, jsonData });
};
@@ -38,56 +36,52 @@ export class ConfigEditor extends PureComponent<Props, State> {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
oauthPassThru: event.currentTarget.checked
oauthPassThru: event.currentTarget.checked,
};
onOptionsChange({ ...options, jsonData });
};
onUseClientCertWhenOAuthMissingChange = (
event: React.SyntheticEvent<HTMLInputElement>
) => {
onUseClientCertWhenOAuthMissingChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
useClientCertWhenOAuthMissing: event.currentTarget.checked
useClientCertWhenOAuthMissing: event.currentTarget.checked,
};
onOptionsChange({ ...options, jsonData });
};
onClientCertificatePathChange = (event: ChangeEvent<HTMLInputElement>) => {
onClientCertificatePathChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
clientCertificatePath: event.target.value
clientCertificatePath: event.target.value,
};
onOptionsChange({ ...options, jsonData });
};
onClientKeyPathChange = (event: ChangeEvent<HTMLInputElement>) => {
onClientKeyPathChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
clientKeyPath: event.target.value
clientKeyPath: event.target.value,
};
onOptionsChange({ ...options, jsonData });
};
onCertificateAuthorityPathChange = (event: ChangeEvent<HTMLInputElement>) => {
onCertificateAuthorityPathChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
certificateAuthorityPath: event.target.value
certificateAuthorityPath: event.target.value,
};
onOptionsChange({ ...options, jsonData });
};
onAllowInsecureSslChange = (
event: React.SyntheticEvent<HTMLInputElement>
) => {
onAllowInsecureSslChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
const { onOptionsChange, options } = this.props;
const jsonData = {
...options.jsonData,
allowInsecureSsl: event.currentTarget.checked
allowInsecureSsl: event.currentTarget.checked,
};
onOptionsChange({ ...options, jsonData });
};
@@ -100,113 +94,89 @@ export class ConfigEditor extends PureComponent<Props, State> {
<div className="gf-form-group">
<div className="gf-form">
<FormField
label={"Hostname or IP"}
label={'Hostname or IP'}
labelWidth={10}
inputWidth={20}
disabled={false}
onChange={this.onTimelyHostChange}
tooltip={"Hostname or IP of Timely Server"}
value={jsonData.timelyHost || ""}
placeholder={"localhost"}
tooltip={'Hostname or IP of Timely Server'}
value={jsonData.timelyHost || ''}
placeholder={'localhost'}
/>
</div>
<div className="gf-form">
<FormField
label={"Https port"}
label={'Https port'}
labelWidth={10}
inputWidth={20}
onChange={this.onHttpsPortChange}
value={jsonData.httpsPort || ""}
placeholder={"4243"}
value={jsonData.httpsPort || ''}
placeholder={'4243'}
/>
</div>
<div className="gf-form">
<Switch
label={"Use OAuth token"}
label={'Use OAuth token'}
labelClass="width-10"
tooltipPlacement={"top"}
tooltip={"Send OAuth token if available"}
tooltipPlacement={'top'}
tooltip={'Send OAuth token if available'}
checked={jsonData.oauthPassThru || false}
onChange={this.onUseOAuthChange}
/>
</div>
<div className="gf-form">
<Switch
label={"Client cert for users"}
label={'Client cert for users'}
labelClass="width-10"
tooltipPlacement={"top"}
tooltip={"If user is missing OAuth token, use client cert instead"}
tooltipPlacement={'top'}
tooltip={'If user is missing OAuth token, use client cert instead'}
checked={jsonData.useClientCertWhenOAuthMissing || false}
onChange={this.onUseClientCertWhenOAuthMissingChange}
/>
</div>
<div className="gf-form">
<FormField
label={"Client cert path"}
label={'Client cert path'}
labelWidth={10}
inputWidth={40}
inputWidth={30}
disabled={false}
onChange={this.onClientCertificatePathChange}
tooltip={"Full path to client certificate"}
value={jsonData.clientCertificatePath || ""}
tooltip={'Full path to client certificate'}
value={jsonData.clientCertificatePath || ''}
/>
</div>
<div className="gf-form">
<FormField
label={"Client key path"}
label={'Client key path'}
labelWidth={10}
inputWidth={40}
inputWidth={30}
disabled={false}
onChange={this.onClientKeyPathChange}
tooltip={"Full path to client key"}
value={jsonData.clientKeyPath || ""}
tooltip={'Full path to client key'}
value={jsonData.clientKeyPath || ''}
/>
</div>
<div className="gf-form">
<FormField
label={"CA path"}
label={'CA path'}
labelWidth={10}
inputWidth={40}
inputWidth={30}
disabled={false}
onChange={this.onCertificateAuthorityPathChange}
tooltip={"Full path to certificate authority"}
value={jsonData.certificateAuthorityPath || ""}
tooltip={'Full path to certificate authority'}
value={jsonData.certificateAuthorityPath || ''}
/>
</div>
<div className="gf-form">
<Switch
label={"Allow insecure ssl"}
label={'Allow insecure ssl'}
labelClass="width-10"
tooltipPlacement={"top"}
tooltip={
"Allow ssl connection with unverified or self-signed certificates"
}
tooltipPlacement={'top'}
tooltip={'Allow ssl connection with unverified or self-signed certificates'}
checked={jsonData.allowInsecureSsl || false}
onChange={this.onAllowInsecureSslChange}
/>
</div>
<div className="gf-form">
<p>
<a
className="external-link"
target="_blank"
href=""
onClick={() =>
window.open(
"https://" +
jsonData.timelyHost +
":" +
jsonData.httpsPort +
"/version",
"_blank"
)
}
>
Open a new browser tab/window to test https access
</a>
</p>
</div>
</div>
);
}
+99 -166
View File
@@ -1,25 +1,17 @@
import _ from "lodash";
import { QueryEditorProps } from "@grafana/data";
import { Input, Select, LegacyForms } from "@grafana/ui";
import React, { Component } from "react";
import { TimelyDataSource } from "./TimelyDataSource";
import {
TimelyDataSourceOptions,
TimelyErrors,
TimelyQueryForm
} from "./types";
import { SelectableValue } from "@grafana/data/types/select";
import dayjs from "dayjs";
import { TagEditor } from "./TagEditor";
import { AsyncTypeahead, TypeaheadModel } from "react-bootstrap-typeahead";
import _ from 'lodash';
import { QueryEditorProps } from '@grafana/data';
import { Input, Select, LegacyForms } from '@grafana/ui';
import React, { Component } from 'react';
import { TimelyDataSource } from './TimelyDataSource';
import { TimelyDataSourceOptions, TimelyErrors, TimelyQueryForm } from './types';
import { SelectableValue } from '@grafana/data/types/select';
import dayjs from 'dayjs';
import { TagEditor } from './TagEditor';
import { AsyncTypeahead, TypeaheadModel } from 'react-bootstrap-typeahead';
const { Switch } = LegacyForms;
export type Props = QueryEditorProps<
TimelyDataSource,
TimelyQueryForm,
TimelyDataSourceOptions
>;
export type Props = QueryEditorProps<TimelyDataSource, TimelyQueryForm, TimelyDataSourceOptions>;
interface State {
aggregatorTypes: string[];
@@ -35,37 +27,33 @@ export class QueryEditor extends Component<Props, State> {
constructor(props: Props) {
super(props);
const defaultQuery: Partial<TimelyQueryForm> = {
metric: "",
alias: "",
aggregator: "none",
refId: "A",
queryType: "metricQuery",
metric: '',
alias: '',
aggregator: 'none',
refId: 'A',
queryType: 'metricQuery',
disableDownsampling: false,
downsampleFillPolicy: "none",
downsampleInterval: "1m",
downsampleAggregator: "avg",
downsampleFillPolicy: 'none',
downsampleInterval: '1m',
downsampleAggregator: 'avg',
shouldComputeRate: false,
isCounter: false,
tags: {}
tags: {},
};
this.state = {
aggregatorTypes: ["none", "avg", "dev", "max", "min", "sum", "count"],
aggregatorTypes: ['none', 'avg', 'dev', 'max', 'min', 'sum', 'count'],
errors: {
downsample: undefined
downsample: undefined,
},
query: Object.assign({}, defaultQuery, props.query),
queryOptionsLoading: false,
queryOptions: []
queryOptions: [],
};
this.getAggregators();
this.getMetrics();
}
shouldComponentUpdate(
nextProps: Readonly<Props>,
nextState: Readonly<State>,
nextContext: any
): boolean {
shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any): boolean {
return true;
}
@@ -180,16 +168,15 @@ export class QueryEditor extends Component<Props, State> {
try {
let valid = false;
if (downsampleInterval) {
valid = dayjs("", "").isValid();
valid = dayjs('', '').isValid();
}
if (!valid) {
this.setState((state, props) => {
this.setState(
{
errors: {
downsample:
"You must supply a downsample interval (e.g. '1m' or '1h')."
}
downsample: "You must supply a downsample interval (e.g. '1m' or '1h').",
},
},
this.updateQueryFromState
);
@@ -199,9 +186,8 @@ export class QueryEditor extends Component<Props, State> {
this.setState(
{
errors: {
downsample:
"You must supply a downsample interval (e.g. '1m' or '1h')."
}
downsample: "You must supply a downsample interval (e.g. '1m' or '1h').",
},
},
this.updateQueryFromState
);
@@ -210,28 +196,24 @@ export class QueryEditor extends Component<Props, State> {
};
getAggregators = () => {
this.props.datasource
.getResource("/api/aggregators")
.then((result: any) => {
if (result && _.isArray(result)) {
this.setState({ aggregatorTypes: result }, this.updateQueryFromState);
}
});
this.props.datasource.getResource('/api/aggregators').then((result: any) => {
if (result && _.isArray(result)) {
this.setState({ aggregatorTypes: result }, this.updateQueryFromState);
}
});
};
getMetrics = () => {
this.props.datasource
.getResource("/api/suggest", { type: "metrics", max: "-1" })
.then((result: any) => {
if (result && _.isArray(result)) {
const metrics: string[] = result;
this.metricArray = metrics
.map(value => {
return value;
})
.concat();
}
});
this.props.datasource.getResource('/api/suggest', { type: 'metrics', max: '-1' }).then((result: any) => {
if (result && _.isArray(result)) {
const metrics: string[] = result;
this.metricArray = metrics
.map((value) => {
return value;
})
.concat();
}
});
};
updateTags = (tags: { [key: string]: string }) => {
@@ -244,18 +226,15 @@ export class QueryEditor extends Component<Props, State> {
handleSearch = (query: string) => {
const results = this.metricArray
.filter(
metric =>
query === "" || metric.toLowerCase().includes(query.toLowerCase())
)
.map(value => {
.filter((metric) => query === '' || metric.toLowerCase().includes(query.toLowerCase()))
.map((value) => {
return value;
});
this.setState({ queryOptions: results });
};
getInputValue = (id: string): string | null => {
var fullId = "div#" + id + " div div input.rbt-input-main";
var fullId = 'div#' + id + ' div div input.rbt-input-main';
var inputElement = document.querySelector(fullId);
if (inputElement !== null) {
return (inputElement as HTMLInputElement).value;
@@ -264,29 +243,15 @@ export class QueryEditor extends Component<Props, State> {
};
render() {
var queryEditorId = Math.random()
.toString(36)
.substr(2, 9);
var queryEditorId = Math.random().toString(36).substr(2, 9);
const { metric, aggregator, alias } = this.state.query;
const {
downsampleInterval,
downsampleAggregator,
disableDownsampling
} = this.state.query;
const { downsampleInterval, downsampleAggregator, disableDownsampling } = this.state.query;
const { tags } = this.state.query;
const {
shouldComputeRate,
isCounter,
counterResetValue,
counterMax
} = this.state.query;
const aggregatorOptions: Array<{}> = _.map(
this.state.aggregatorTypes,
(value: string) => ({
label: value,
value: value
})
);
const { shouldComputeRate, isCounter, counterResetValue, counterMax } = this.state.query;
const aggregatorOptions: Array<{}> = _.map(this.state.aggregatorTypes, (value: string) => ({
label: value,
value: value,
}));
const { queryOptionsLoading, queryOptions } = this.state;
var multiplier = 7.5;
@@ -300,22 +265,15 @@ export class QueryEditor extends Component<Props, State> {
}
var dynamicStyle =
"div.timely-query input.form-control, div#timelyQuery-" +
'div.timely-query input.form-control, div#timelyQuery-' +
queryEditorId +
" { " +
"width:" +
' { ' +
'width:' +
metricWidth +
"px!important " +
"}";
'px!important ' +
'}';
dynamicStyle +=
"#timelyAlias-" +
queryEditorId +
" { " +
"width:" +
aliasWidth +
"px!important " +
"}";
dynamicStyle += '#timelyAlias-' + queryEditorId + ' { ' + 'width:' + aliasWidth + 'px!important ' + '}';
return (
<div className="timely-edior-row">
@@ -323,73 +281,58 @@ export class QueryEditor extends Component<Props, State> {
<style>{dynamicStyle}</style>
<div className="gf-form timely">
<label className="gf-form-label width-10">Metric</label>
<div
id={"timelyQuery-" + queryEditorId}
className="timely timely-query"
>
<div id={'timelyQuery-' + queryEditorId} className="timely timely-query">
<AsyncTypeahead
id={"timelyQuery-" + queryEditorId + "-Typeahead"}
id={'timelyQuery-' + queryEditorId + '-Typeahead'}
inputProps={{ spellCheck: false }}
defaultInputValue={metric}
isLoading={queryOptionsLoading}
onSearch={query => {
onSearch={(query) => {
this.setState({ queryOptionsLoading: true });
this.handleSearch(query);
this.setState({ queryOptionsLoading: false });
}}
onChange={e => {
var inputValue = this.getInputValue(
"timelyQuery-" + queryEditorId
);
onChange={(e) => {
var inputValue = this.getInputValue('timelyQuery-' + queryEditorId);
if (inputValue !== null) {
this.onMetricTextChange(inputValue);
}
}}
onBlur={e => {
var inputValue = this.getInputValue(
"timelyQuery-" + queryEditorId
);
onBlur={(e) => {
var inputValue = this.getInputValue('timelyQuery-' + queryEditorId);
if (inputValue !== null) {
this.onMetricTextChange(inputValue);
}
}}
onFocus={e => {
var inputValue = this.getInputValue(
"timelyQuery-" + queryEditorId
);
if (
queryOptions.length === 0 ||
inputValue === null ||
inputValue.length === 0
) {
this.handleSearch("");
onFocus={(e) => {
var inputValue = this.getInputValue('timelyQuery-' + queryEditorId);
if (queryOptions.length === 0 || inputValue === null || inputValue.length === 0) {
this.handleSearch('');
}
}}
options={queryOptions}
selectHintOnEnter={true}
align={"left"}
align={'left'}
allowNew={true}
newSelectionPrefix={""}
bodyContainer={true}
newSelectionPrefix={''}
paginate={true}
paginationText={"more"}
paginationText={'more'}
minLength={0}
maxResults={100}
caseSensitive={false}
placeholder={"metric"}
placeholder={'metric'}
/>
</div>
</div>
<div className="gf-form timely">
<label className="gf-form-label width-5">Alias</label>
<Input
id={"timelyAlias-" + queryEditorId}
css={""}
id={'timelyAlias-' + queryEditorId}
className="min-width-10 flex-grow-1"
spellCheck={false}
value={alias || ""}
value={alias || ''}
onChange={this.onAliasChange}
placeholder={"series alias"}
placeholder={'series alias'}
/>
</div>
</div>
@@ -398,31 +341,28 @@ export class QueryEditor extends Component<Props, State> {
<div className="gf-form timely">
<label className="gf-form-label width-10">Downsample</label>
<Input
className={"min-width-5 flex-grow-1"}
css={""}
className={'min-width-5 flex-grow-1'}
spellCheck={false}
value={downsampleInterval || ""}
value={downsampleInterval || ''}
onChange={this.onDownsampleChange}
placeholder={"interval"}
placeholder={'interval'}
/>
</div>
<div className="gf-form timely">
<label className="gf-form-label width-10">
Downsample Aggregator
</label>
<label className="gf-form-label width-10">Downsample Aggregator</label>
<Select
className={"min-width-5 flex-grow-1"}
className={'min-width-5 flex-grow-1'}
isSearchable={false}
options={aggregatorOptions}
value={downsampleAggregator}
placeholder={"aggregator"}
placeholder={'aggregator'}
onChange={this.onDownsampleAggregatorChange}
menuPlacement={"bottom"}
menuPlacement={'bottom'}
/>
</div>
<div className="gf-form timely">
<Switch
label={"Disable downsampling"}
label={'Disable downsampling'}
labelClass="width-10"
checked={disableDownsampling || false}
onChange={this.onDisableDownsamplingChange}
@@ -431,55 +371,48 @@ export class QueryEditor extends Component<Props, State> {
</div>
<div className="gf-form-inline">
<div className="gf-form timely">
<label className="gf-form-label width-10">
All Results Aggregator
</label>
<label className="gf-form-label width-10">All Results Aggregator</label>
<Select
className={"min-width-5 flex-grow-1"}
className={'min-width-5 flex-grow-1'}
isSearchable={false}
options={aggregatorOptions}
value={aggregator}
placeholder={"aggregator"}
placeholder={'aggregator'}
onChange={this.onAggregatorChange}
menuPlacement={"bottom"}
menuPlacement={'bottom'}
/>
</div>
<div className="gf-form timely">
<Switch
label={"Rate"}
label={'Rate'}
labelClass="width-5"
checked={shouldComputeRate || false}
onChange={this.onRateChange}
/>
<div hidden={!shouldComputeRate}>
<Switch
label={"Counter"}
label={'Counter'}
labelClass="width-10"
checked={isCounter || false}
onChange={this.onCounterChange}
/>
</div>
<div
className="gf-form timely"
hidden={!shouldComputeRate || !isCounter}
>
<div className="gf-form timely" hidden={!shouldComputeRate || !isCounter}>
<label className="gf-form-label width-10">Max Value</label>
<Input
className={"min-width-6 flex-grow-1"}
css={""}
className={'min-width-6 flex-grow-1'}
spellCheck={false}
value={counterMax || ""}
value={counterMax || ''}
onChange={this.onCounterMaxChange}
placeholder={"max value"}
placeholder={'max value'}
/>
<label className="gf-form-label width-10">Reset Value</label>
<Input
className={"min-width-6 flex-grow-1"}
css={""}
className={'min-width-6 flex-grow-1'}
spellCheck={false}
value={counterResetValue || ""}
value={counterResetValue || ''}
onChange={this.onCounterResetValueChange}
placeholder={"reset value"}
placeholder={'reset value'}
/>
</div>
</div>
+107 -176
View File
@@ -1,10 +1,10 @@
import React, { Component } from "react";
import { QueryEditor } from "./QueryEditor";
import { withStyles } from "@material-ui/core/styles";
import { Tooltip } from "@material-ui/core";
import { Icon } from "@grafana/ui";
import _ from "lodash";
import { AsyncTypeahead, TypeaheadModel } from "react-bootstrap-typeahead";
import React, { Component } from 'react';
import { QueryEditor } from './QueryEditor';
import { withStyles } from '@material-ui/core/styles';
import { Tooltip } from '@material-ui/core';
import { Icon } from '@grafana/ui';
import _ from 'lodash';
import { AsyncTypeahead, TypeaheadModel } from 'react-bootstrap-typeahead';
export interface Props {
tags: { [key: string]: string };
@@ -26,14 +26,14 @@ interface Tag {
errors: string[] | undefined;
}
const HtmlTooltip = withStyles(theme => ({
const HtmlTooltip = withStyles((theme) => ({
tooltip: {
backgroundColor: "#f5f5f9",
color: "rgba(0, 0, 0, 0.87)",
backgroundColor: '#f5f5f9',
color: 'rgba(0, 0, 0, 0.87)',
maxWidth: 220,
fontSize: theme.typography.pxToRem(12),
border: "1px solid #dadde9"
}
border: '1px solid #dadde9',
},
}))(Tooltip);
export class TagEditor extends Component<Props, State> {
@@ -45,28 +45,24 @@ export class TagEditor extends Component<Props, State> {
key: key,
value: value,
editing: false,
errors: undefined
errors: undefined,
}))
.concat(),
tagKeyOptionsLoading: false,
tagKeyOptions: [],
tagValueOptionsLoading: false,
tagValueOptions: []
tagValueOptions: [],
};
}
shouldComponentUpdate(
nextProps: Readonly<Props>,
nextState: Readonly<State>,
nextContext: any
): boolean {
shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any): boolean {
return true;
}
validateTags = (tags: Tag[], tagNumber: number): boolean => {
var count = new Map<string, number>();
var anyErrors = false;
tags.forEach(tag => {
tags.forEach((tag) => {
var n = count.get(tag.key);
if (n === undefined) {
count.set(tag.key, 1);
@@ -89,11 +85,11 @@ export class TagEditor extends Component<Props, State> {
anyErrors = true;
}
if (tag.key.length === 0) {
tag.errors.push("tag key can not be empty");
tag.errors.push('tag key can not be empty');
anyErrors = true;
}
if (tag.value.length === 0) {
tag.errors.push("tag value can not be empty");
tag.errors.push('tag value can not be empty');
anyErrors = true;
}
if (tag.errors.length === 0) {
@@ -110,11 +106,11 @@ export class TagEditor extends Component<Props, State> {
var tags = [
...stateTags,
{
key: "",
value: "",
key: '',
value: '',
editing: true,
errors: ["tag key can not be empty", "tag value can not be empty"]
}
errors: ['tag key can not be empty', 'tag value can not be empty'],
},
];
return { tags: tags };
});
@@ -177,19 +173,17 @@ export class TagEditor extends Component<Props, State> {
};
updateTags = (tags: Tag[]) => {
var entries = Object.fromEntries(
[...tags.values()].map(tag => [tag.key, tag.value]).concat()
);
var entries = Object.fromEntries([...tags.values()].map((tag) => [tag.key, tag.value]).concat());
this.props.parent.updateTags(entries);
};
handleTagKeySearch = (query: string, metric: string | undefined) => {
if (metric !== undefined) {
this.props.parent.props.datasource
.postResource("/api/suggest", {
type: "tagk",
.postResource('/api/suggest', {
type: 'tagk',
m: metric,
max: "1000"
max: '1000',
})
.then((result: any) => {
if (result && _.isArray(result)) {
@@ -198,27 +192,21 @@ export class TagEditor extends Component<Props, State> {
// find all tag keys that are being used in non-edited tags
var existingTags = tags
.filter(t => t.editing === false)
.map(t => {
.filter((t) => t.editing === false)
.map((t) => {
return t.key;
})
.concat();
// exclude keys that are bing used
var filteredResults = tagKeyArray.filter(t => {
return (
existingTags.find(existing => t === existing) === undefined
);
var filteredResults = tagKeyArray.filter((t) => {
return existingTags.find((existing) => t === existing) === undefined;
});
// exclude keys that don't match the search (if there is one)
filteredResults = filteredResults
.filter(
tagKey =>
query === "" ||
tagKey.toLowerCase().includes(query.toLowerCase())
)
.map(value => {
.filter((tagKey) => query === '' || tagKey.toLowerCase().includes(query.toLowerCase()))
.map((value) => {
return value;
});
this.setState({ tagKeyOptions: filteredResults });
@@ -227,29 +215,21 @@ export class TagEditor extends Component<Props, State> {
}
};
handleTagValueSearch = (
query: string,
metric: string | undefined,
tagKey: string | undefined
) => {
handleTagValueSearch = (query: string, metric: string | undefined, tagKey: string | undefined) => {
if (metric !== undefined && tagKey !== undefined) {
this.props.parent.props.datasource
.postResource("/api/suggest", {
type: "tagv",
.postResource('/api/suggest', {
type: 'tagv',
m: metric,
t: tagKey,
max: "1000"
max: '1000',
})
.then((result: any) => {
if (result && _.isArray(result)) {
const tagValueArray: string[] = [".*", ...result];
const tagValueArray: string[] = ['.*', ...result];
const filteredResults = tagValueArray
.filter(
tagValue =>
query === "" ||
tagValue.toLowerCase().includes(query.toLowerCase())
)
.map(value => {
.filter((tagValue) => query === '' || tagValue.toLowerCase().includes(query.toLowerCase()))
.map((value) => {
return value;
});
this.setState({ tagValueOptions: filteredResults });
@@ -259,7 +239,7 @@ export class TagEditor extends Component<Props, State> {
};
getInputValue = (id: string): string | null => {
var fullId = "div#" + id + " div div input.rbt-input-main";
var fullId = 'div#' + id + ' div div input.rbt-input-main';
var inputElement = document.querySelector(fullId);
if (inputElement !== null) {
return (inputElement as HTMLInputElement).value;
@@ -268,39 +248,32 @@ export class TagEditor extends Component<Props, State> {
};
render() {
const {
tagKeyOptionsLoading,
tagKeyOptions,
tagValueOptionsLoading,
tagValueOptions
} = this.state;
const { tagKeyOptionsLoading, tagKeyOptions, tagValueOptionsLoading, tagValueOptions } = this.state;
var { tags } = this.state;
var tagEditorId = Math.random()
.toString(36)
.substr(2, 9);
var tagEditorId = Math.random().toString(36).substr(2, 9);
var lastSearchMetric: string;
const { metric } = this.props.parent.state.query;
var allowAddNewTag = tags.filter(t => t.editing === true).length === 0;
var allowAddNewTag = tags.filter((t) => t.editing === true).length === 0;
return (
<div className="gf-form-inline">
<div className="gf-form timely">
<label className="gf-form-label width-10">Tags</label>
{[...tags.values()].map((tag, tagNum) => (
<div id={"timelytag-" + tagNum.toString()}>
<div key={tagNum.toString()} id={'timelytag-' + tagNum.toString()}>
<div hidden={tag.editing}>
<label className="gf-form-label">
{tag.key}&nbsp;=&nbsp;{tag.value}
<div className="timely tag edit">
<HtmlTooltip title={"edit tag"} placement={"bottom"}>
<HtmlTooltip title={'edit tag'} placement={'bottom'}>
<Icon
name="edit"
tabIndex={0}
onClick={e => {
onClick={(e) => {
this.beginEdit(tagNum);
}}
onKeyPress={e => {
if (e.key === "Enter") {
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.beginEdit(tagNum);
}
}}
@@ -308,15 +281,15 @@ export class TagEditor extends Component<Props, State> {
</HtmlTooltip>
</div>
<div className="timely tag delete">
<HtmlTooltip title={"delete tag"} placement={"bottom"}>
<HtmlTooltip title={'delete tag'} placement={'bottom'}>
<Icon
name="trash-alt"
tabIndex={0}
onClick={e => {
onClick={(e) => {
this.removeTag(tagNum);
}}
onKeyPress={e => {
if (e.key === "Enter") {
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.removeTag(tagNum);
}
}}
@@ -327,48 +300,40 @@ export class TagEditor extends Component<Props, State> {
</div>
<div className="gf-form" hidden={!tag.editing}>
<div
id={"timelyTagKey-" + tagEditorId + "-" + tagNum.toString()}
id={'timelyTagKey-' + tagEditorId + '-' + tagNum.toString()}
className="timely timely-tag-key"
onMouseLeave={e => {
var inputValue = this.getInputValue(
"timelyTagKey-" + tagEditorId + "-" + tagNum.toString()
);
onMouseLeave={(e) => {
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
if (inputValue !== null) {
this.updateTagKey(tagNum, inputValue);
}
}}
>
<AsyncTypeahead
id={"timelyTagKey-" + tagEditorId + "-Typeahead"}
id={'timelyTagKey-' + tagEditorId + '-Typeahead'}
selected={[tag.key]}
isLoading={tagKeyOptionsLoading}
inputProps={{ spellCheck: false }}
onSearch={query => {
onSearch={(query) => {
this.setState({ tagKeyOptionsLoading: true });
lastSearchMetric = metric!;
this.handleTagKeySearch(query, metric);
this.setState({ tagKeyOptionsLoading: false });
}}
onChange={e => {
var inputValue = this.getInputValue(
"timelyTagKey-" + tagEditorId + "-" + tagNum.toString()
);
onChange={(e) => {
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
if (inputValue !== null) {
this.updateTagKey(tagNum, inputValue);
}
}}
onBlur={e => {
var inputValue = this.getInputValue(
"timelyTagKey-" + tagEditorId + "-" + tagNum.toString()
);
onBlur={(e) => {
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
if (inputValue !== null) {
this.updateTagKey(tagNum, inputValue);
}
}}
onFocus={e => {
var inputValue = this.getInputValue(
"timelyTagKey-" + tagEditorId + "-" + tagNum.toString()
);
onFocus={(e) => {
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
if (
tagKeyOptions.length === 0 ||
inputValue === null ||
@@ -377,14 +342,12 @@ export class TagEditor extends Component<Props, State> {
) {
this.setState({ tagKeyOptionsLoading: true });
lastSearchMetric = metric!;
this.handleTagKeySearch("", metric);
this.handleTagKeySearch('', metric);
this.setState({ tagKeyOptionsLoading: false });
}
}}
onKeyDown={e => {
var inputValue = this.getInputValue(
"timelyTagKey-" + tagEditorId + "-" + tagNum.toString()
);
onKeyDown={(e) => {
var inputValue = this.getInputValue('timelyTagKey-' + tagEditorId + '-' + tagNum.toString());
if (
tagKeyOptions.length === 0 ||
inputValue === null ||
@@ -393,115 +356,83 @@ export class TagEditor extends Component<Props, State> {
) {
this.setState({ tagKeyOptionsLoading: true });
lastSearchMetric = metric!;
this.handleTagKeySearch("", metric);
this.handleTagKeySearch('', metric);
this.setState({ tagKeyOptionsLoading: false });
}
}}
autoFocus={tag.key.length === 0}
options={tagKeyOptions}
selectHintOnEnter={false}
align={"left"}
align={'left'}
allowNew={true}
newSelectionPrefix={""}
bodyContainer={true}
newSelectionPrefix={''}
paginate={true}
paginationText={"more"}
paginationText={'more'}
minLength={0}
maxResults={100}
caseSensitive={false}
placeholder={"key"}
placeholder={'key'}
/>
</div>
<div
id={"timelyTagValue-" + tagEditorId + "-" + tagNum.toString()}
id={'timelyTagValue-' + tagEditorId + '-' + tagNum.toString()}
className="timely timely-tag-value"
onMouseLeave={e => {
var inputValue = this.getInputValue(
"timelyTagValue-" + tagEditorId + "-" + tagNum.toString()
);
onMouseLeave={(e) => {
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
if (inputValue !== null) {
this.updateTagValue(tagNum, inputValue);
}
}}
>
<AsyncTypeahead
id={"timelyTagValue-" + tagEditorId + "-Typeahead"}
id={'timelyTagValue-' + tagEditorId + '-Typeahead'}
selected={[tag.value]}
isLoading={tagValueOptionsLoading}
inputProps={{ spellCheck: false }}
onSearch={query => {
onSearch={(query) => {
this.setState({ tagValueOptionsLoading: true });
this.handleTagValueSearch(query, metric, tag.key);
this.setState({ tagValueOptionsLoading: false });
}}
onChange={e => {
var inputValue = this.getInputValue(
"timelyTagValue-" +
tagEditorId +
"-" +
tagNum.toString()
);
onChange={(e) => {
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
if (inputValue !== null) {
this.updateTagValue(tagNum, inputValue);
}
}}
onBlur={e => {
var inputValue = this.getInputValue(
"timelyTagValue-" +
tagEditorId +
"-" +
tagNum.toString()
);
onBlur={(e) => {
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
if (inputValue !== null) {
this.updateTagValue(tagNum, inputValue);
}
}}
onFocus={e => {
var inputValue = this.getInputValue(
"timelyTagValue-" +
tagEditorId +
"-" +
tagNum.toString()
);
if (
tagValueOptions.length === 0 ||
inputValue === null ||
inputValue.length === 0
) {
onFocus={(e) => {
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
if (tagValueOptions.length === 0 || inputValue === null || inputValue.length === 0) {
this.setState({ tagValueOptionsLoading: true });
this.handleTagValueSearch("", metric, tag.key);
this.handleTagValueSearch('', metric, tag.key);
this.setState({ tagValueOptionsLoading: false });
}
}}
onKeyDown={e => {
var inputValue = this.getInputValue(
"timelyTagValue-" +
tagEditorId +
"-" +
tagNum.toString()
);
if (
tagValueOptions.length === 0 ||
inputValue === null ||
inputValue.length === 0
) {
onKeyDown={(e) => {
var inputValue = this.getInputValue('timelyTagValue-' + tagEditorId + '-' + tagNum.toString());
if (tagValueOptions.length === 0 || inputValue === null || inputValue.length === 0) {
this.setState({ tagValueOptionsLoading: true });
this.handleTagValueSearch("", metric, tag.key);
this.handleTagValueSearch('', metric, tag.key);
this.setState({ tagValueOptionsLoading: false });
}
}}
options={tagValueOptions}
selectHintOnEnter={false}
align={"left"}
align={'left'}
allowNew={true}
newSelectionPrefix={""}
bodyContainer={true}
newSelectionPrefix={''}
paginate={true}
paginationText={"more"}
paginationText={'more'}
minLength={0}
maxResults={100}
caseSensitive={false}
placeholder={"value"}
placeholder={'value'}
/>
</div>
<label className="gf-form-label max-width-5 flex-shrink-1">
@@ -511,13 +442,13 @@ export class TagEditor extends Component<Props, State> {
title={
<React.Fragment>
<ul>
{tag.errors.map(error => {
return <li>{error}</li>;
{tag.errors.map((error) => {
return <li key={error}>{error}</li>;
})}
</ul>
</React.Fragment>
}
placement={"bottom"}
placement={'bottom'}
>
<Icon name="exclamation-triangle" />
</HtmlTooltip>
@@ -525,15 +456,15 @@ export class TagEditor extends Component<Props, State> {
)}
{tag.errors === undefined && (
<div className="timely tag save">
<HtmlTooltip title={"save tag"} placement={"bottom"}>
<HtmlTooltip title={'save tag'} placement={'bottom'}>
<Icon
name="save"
tabIndex={0}
onClick={e => {
onClick={(e) => {
this.endEdit(tagNum);
}}
onKeyPress={e => {
if (e.key === "Enter") {
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.endEdit(tagNum);
}
}}
@@ -542,15 +473,15 @@ export class TagEditor extends Component<Props, State> {
</div>
)}
<div className="timely tag delete">
<HtmlTooltip title={"delete tag"} placement={"bottom"}>
<HtmlTooltip title={'delete tag'} placement={'bottom'}>
<Icon
name="trash-alt"
tabIndex={0}
onClick={e => {
onClick={(e) => {
this.removeTag(tagNum);
}}
onKeyPress={e => {
if (e.key === "Enter") {
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.removeTag(tagNum);
}
}}
@@ -564,15 +495,15 @@ export class TagEditor extends Component<Props, State> {
<div className="gf-form" hidden={!allowAddNewTag}>
<label className="gf-form-label">
<div className="timely tag addtag">
<HtmlTooltip title={"add tag"} placement={"bottom"}>
<HtmlTooltip title={'add tag'} placement={'bottom'}>
<Icon
name="plus"
tabIndex={0}
onClick={e => {
onClick={(e) => {
this.addTag();
}}
onKeyPress={e => {
if (e.key === "Enter") {
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.addTag();
}
}}
+72 -97
View File
@@ -1,4 +1,4 @@
import _ from "lodash";
import _ from 'lodash';
import {
DataQuery,
DataQueryRequest,
@@ -6,35 +6,28 @@ import {
DataSourceInstanceSettings,
Field,
Labels,
MetricFindValue
} from "@grafana/data";
import { DataSourceWithBackend, getTemplateSrv } from "@grafana/runtime";
import { TimelyDataSourceOptions, TimelyQueryForm } from "./types";
import { Observable } from "rxjs";
import { HealthCheckResult } from "@grafana/runtime/utils/DataSourceWithBackend";
import { DataFrame } from "@grafana/data/types/dataFrame";
import { ScopedVars } from "@grafana/data/types/ScopedVars";
import { map } from "rxjs/operators";
MetricFindValue,
} from '@grafana/data';
import { DataSourceWithBackend, getTemplateSrv } from '@grafana/runtime';
import { TimelyDataSourceOptions, TimelyQueryForm } from './types';
import { Observable } from 'rxjs';
import { HealthCheckResult } from '@grafana/runtime/utils/DataSourceWithBackend';
import { DataFrame } from '@grafana/data/types/dataFrame';
import { ScopedVars } from '@grafana/data/types/ScopedVars';
import { map } from 'rxjs/operators';
export class TimelyDataSource extends DataSourceWithBackend<
TimelyQueryForm,
TimelyDataSourceOptions
> {
constructor(
instanceSettings: DataSourceInstanceSettings<TimelyDataSourceOptions>
) {
export class TimelyDataSource extends DataSourceWithBackend<TimelyQueryForm, TimelyDataSourceOptions> {
constructor(instanceSettings: DataSourceInstanceSettings<TimelyDataSourceOptions>) {
super(instanceSettings);
}
/**
* Ideally final -- any other implementation may not work as expected
*/
query(
request: DataQueryRequest<TimelyQueryForm>
): Observable<DataQueryResponse> {
query(request: DataQueryRequest<TimelyQueryForm>): Observable<DataQueryResponse> {
// match query refId to TimelyQueryForm for correlation to results
var targetIndex: { [key: string]: TimelyQueryForm } = {};
request.targets.forEach(target => {
request.targets.forEach((target) => {
var query = target as TimelyQueryForm;
targetIndex[query.refId] = query;
});
@@ -43,19 +36,14 @@ export class TimelyDataSource extends DataSourceWithBackend<
// to set the series name for display in the legend
// there should be a better way to do this, but there isn't yet AFAIK
return super.query(request).pipe(
map(dataQueryResponse => {
dataQueryResponse.data.forEach(data => {
map((dataQueryResponse) => {
dataQueryResponse.data.forEach((data) => {
var dataFrame = data as DataFrame;
var currentQuery = targetIndex[dataFrame.refId!];
// prevent grafana from prepending the dataFrame name
// to the series names by naming them all the same
dataFrame.fields.forEach(field => {
this.setSeriesName(
currentQuery,
request.scopedVars,
field,
currentQuery.alias
);
dataFrame.fields.forEach((field) => {
this.setSeriesName(currentQuery, request.scopedVars, field, currentQuery.alias);
});
});
return dataQueryResponse;
@@ -75,25 +63,18 @@ export class TimelyDataSource extends DataSourceWithBackend<
return singleName;
}
joinLabels(labels: Labels, defaultValue = ""): string {
joinLabels(labels: Labels, defaultValue = ''): string {
if (!labels || Object.keys(labels).length === 0) {
return defaultValue;
}
const labelKeys = Object.keys(labels).sort();
const cleanSelector = labelKeys
.map(key => `${key}="${labels[key]}"`)
.join(", ");
return ["{", cleanSelector, "}"].join("");
const cleanSelector = labelKeys.map((key) => `${key}="${labels[key]}"`).join(', ');
return ['{', cleanSelector, '}'].join('');
}
setSeriesName(
query: TimelyQueryForm,
scopedVars: ScopedVars,
field: Field,
alias: string | undefined
) {
setSeriesName(query: TimelyQueryForm, scopedVars: ScopedVars, field: Field, alias: string | undefined) {
var title: string | null = null;
if (alias === undefined || alias === "") {
if (alias === undefined || alias === '') {
if (field.labels === undefined) {
title = query.metric!;
} else {
@@ -101,25 +82,25 @@ export class TimelyDataSource extends DataSourceWithBackend<
if (singleTagName === null) {
title = query.metric! + this.joinLabels(field.labels);
} else {
title = query.metric! + " " + field.labels[singleTagName];
title = query.metric! + ' ' + field.labels[singleTagName];
}
}
} else {
var newScopedVars = _.clone(scopedVars || {});
for (const labelKey in field.labels) {
newScopedVars["tag_" + labelKey] = {
newScopedVars['tag_' + labelKey] = {
text: field.labels[labelKey],
value: field.labels[labelKey]
value: field.labels[labelKey],
};
}
scopedVars["metric"] = {
scopedVars['metric'] = {
text: query.metric,
value: query.metric
value: query.metric,
};
title = getTemplateSrv().replace(alias, newScopedVars);
}
field.config = {
displayName: title
displayName: title,
};
}
@@ -128,9 +109,7 @@ export class TimelyDataSource extends DataSourceWithBackend<
if (timelyQuery.metric !== undefined) {
timelyQuery.metric = getTemplateSrv().replace(timelyQuery.metric);
for (let tagsKey in timelyQuery.tags) {
timelyQuery.tags[tagsKey] = getTemplateSrv().replace(
timelyQuery.tags[tagsKey]
);
timelyQuery.tags[tagsKey] = getTemplateSrv().replace(timelyQuery.tags[tagsKey]);
}
}
return timelyQuery;
@@ -145,7 +124,7 @@ export class TimelyDataSource extends DataSourceWithBackend<
}
_performSuggestQuery(params: object): Promise<string[]> {
return this.postResource("/api/suggest", params).then(function(result) {
return this.postResource('/api/suggest', params).then(function (result) {
return result;
});
}
@@ -167,10 +146,10 @@ export class TimelyDataSource extends DataSourceWithBackend<
});
}
var responseTransform = function(result: string[]): MetricFindValue[] {
return _.map(result, function(value) {
var responseTransform = function (result: string[]): MetricFindValue[] {
return _.map(result, function (value) {
var mfv: MetricFindValue = {
text: value
text: value,
};
return mfv;
}).concat();
@@ -185,47 +164,47 @@ export class TimelyDataSource extends DataSourceWithBackend<
var metrics_query = interpolated.match(metrics_regex);
if (metrics_query) {
return this._performSuggestQuery({
type: "metrics",
type: 'metrics',
m: metrics_query[1],
max: "1000"
max: '1000',
}).then(responseTransform);
}
var tag_names_suggest_query = interpolated.match(tag_names_suggest_regex);
if (tag_names_suggest_query) {
return this._performSuggestQuery({
type: "tagk",
type: 'tagk',
m: tag_names_suggest_query[1],
max: "1000"
max: '1000',
}).then(responseTransform);
}
var tag_values_suggest_query = interpolated.match(tag_values_suggest_regex);
if (tag_values_suggest_query) {
return this._performSuggestQuery({
type: "tagv",
type: 'tagv',
m: tag_values_suggest_query[1],
t: tag_values_suggest_query[2],
max: "1000"
max: '1000',
}).then(responseTransform);
}
var tag_names_query = interpolated.match(tag_names_regex);
if (tag_names_query) {
return this._performSuggestQuery({
type: "tagk",
type: 'tagk',
m: tag_names_query[1],
max: "1000"
max: '1000',
}).then(responseTransform);
}
var tag_values_query = interpolated.match(tag_values_regex);
if (tag_values_query) {
return this._performSuggestQuery({
type: "tagv",
type: 'tagv',
m: tag_values_query[1],
t: tag_values_query[2],
max: "1000"
max: '1000',
}).then(responseTransform);
}
@@ -246,43 +225,39 @@ export class TimelyDataSource extends DataSourceWithBackend<
// DataSourceApi
getTagKeys(options?: any): Promise<MetricFindValue[]> {
return this._performSuggestQuery({ type: "tagk", max: "10000" }).then(
(result: any) => {
if (result && _.isArray(result)) {
const metrics: string[] = result;
return metrics
.map(value => {
var mfv: MetricFindValue = {
text: value
};
return mfv;
})
.concat();
} else {
return [];
}
return this._performSuggestQuery({ type: 'tagk', max: '10000' }).then((result: any) => {
if (result && _.isArray(result)) {
const metrics: string[] = result;
return metrics
.map((value) => {
var mfv: MetricFindValue = {
text: value,
};
return mfv;
})
.concat();
} else {
return [];
}
);
});
}
// DataSourceApi
getTagValues(options: any): Promise<MetricFindValue[]> {
return this._performSuggestQuery({ type: "tagv", max: "10000" }).then(
(result: any) => {
if (result && _.isArray(result)) {
const metrics: string[] = result;
return metrics
.map(value => {
var mfv: MetricFindValue = {
text: value
};
return mfv;
})
.concat();
} else {
return [];
}
return this._performSuggestQuery({ type: 'tagv', max: '10000' }).then((result: any) => {
if (result && _.isArray(result)) {
const metrics: string[] = result;
return metrics
.map((value) => {
var mfv: MetricFindValue = {
text: value,
};
return mfv;
})
.concat();
} else {
return [];
}
);
});
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -1,5 +1,5 @@
describe("placeholder test", () => {
it("should return true", () => {
describe('placeholder test', () => {
it('should return true', () => {
expect(true).toBeTruthy();
});
});
+11 -15
View File
@@ -1,21 +1,17 @@
import { DataSourcePlugin } from "@grafana/data";
import { TimelyDataSource } from "./TimelyDataSource";
import { ConfigEditor } from "./ConfigEditor";
import { QueryEditor } from "./QueryEditor";
import { TimelyDataSourceOptions, TimelyQueryForm } from "./types";
import "static/css/timely-bootstrap.css";
import "static/css/timely.css";
import { loadPluginCss } from "@grafana/runtime";
import { DataSourcePlugin } from '@grafana/data';
import { TimelyDataSource } from './TimelyDataSource';
import { ConfigEditor } from './ConfigEditor';
import { QueryEditor } from './QueryEditor';
import { TimelyDataSourceOptions, TimelyQueryForm } from './types';
import 'static/css/timely-bootstrap.css';
import 'static/css/timely.css';
import { loadPluginCss } from '@grafana/runtime';
loadPluginCss({
dark: "plugins/nsa-timely-datasource/styles/dark.css",
light: "plugins/nsa-timely-datasource/styles/light.css"
dark: 'plugins/nsa-timely-datasource/styles/dark.css',
light: 'plugins/nsa-timely-datasource/styles/light.css',
});
export const plugin = new DataSourcePlugin<
TimelyDataSource,
TimelyQueryForm,
TimelyDataSourceOptions
>(TimelyDataSource)
export const plugin = new DataSourcePlugin<TimelyDataSource, TimelyQueryForm, TimelyDataSourceOptions>(TimelyDataSource)
.setConfigEditor(ConfigEditor)
.setQueryEditor(QueryEditor);
+1 -3
View File
@@ -12,9 +12,7 @@
"author": {
"name": "National Security Agency"
},
"keywords": [
"Simple"
],
"keywords": ["Simple"],
"logos": {
"small": "static/img/timely_square_small.png",
"large": "static/img/timely_square_large.png"
@@ -1,54 +0,0 @@
$box-shadow-dimensions: 0 0 0 0.2rem;
$placeholder-color: #6c757d;
.rbt {
&-input-multi {
// Bootstrap 4 focus style
&.focus {
background-color: #fff;
border-color: #80bdff;
box-shadow: $box-shadow-dimensions rgba(0, 123, 255, 0.25);
color: #495057;
outline: 0;
}
&.is-invalid.focus {
border-color: #dc3545;
box-shadow: $box-shadow-dimensions rgba(220, 53, 69, 0.25);
}
&.is-valid.focus {
border-color: #28a745;
box-shadow: $box-shadow-dimensions rgba(40, 167, 69, 0.25);
}
input {
// Firefox
&::-moz-placeholder {
color: $placeholder-color;
opacity: 1;
}
// Internet Explorer 10+
&:-ms-input-placeholder {
color: $placeholder-color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
color: $placeholder-color;
}
}
// Override height in main CSS file :/
& .rbt-input-main,
&.form-control-lg .rbt-input-main,
&.form-control-sm .rbt-input-main {
height: auto;
}
}
&-token {
margin: 1px 3px 2px 0;
}
}
@@ -1,201 +0,0 @@
.rbt .rbt-input-main::-ms-clear {
display: none !important;
}
/**
* Menu
*/
.rbt-menu {
margin-bottom: 2px !important;
}
.rbt-menu > .dropdown-item {
overflow: hidden !important;
text-overflow: ellipsis !important;
}
.rbt-menu > .dropdown-item:focus {
outline: none !important;
}
.rbt-menu-pagination-option {
text-align: center !important;
}
/**
* Multi-select Input
*/
.rbt-input-multi {
cursor: text !important;
overflow: hidden !important;
position: relative !important;
}
.rbt-input-multi.focus {
border-color: #80bdff !important;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
color: #495057 !important;
outline: 0 !important;
}
.rbt-input-multi.form-control {
height: auto !important;
}
.rbt-input-multi.form-control[disabled] {
background-color: #e9ecef !important;
opacity: 1 !important;
}
.rbt-input-multi.is-invalid.focus {
border-color: #dc3545 !important;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
}
.rbt-input-multi.is-valid.focus {
border-color: #28a745 !important;
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25) !important;
}
.rbt-input-multi input::-moz-placeholder {
color: #6c757d !important;
opacity: 1 !important;
}
.rbt-input-multi input:-ms-input-placeholder {
color: #6c757d !important;
}
.rbt-input-multi input::-webkit-input-placeholder {
color: #6c757d !important;
}
.rbt-input-multi .rbt-input-wrapper {
align-items: flex-start !important;
display: flex !important;
flex-wrap: wrap !important;
margin-bottom: -4px !important;
margin-top: -1px !important;
overflow: hidden !important;
}
.rbt-input-multi .rbt-input-main {
margin: 1px 0 4px !important;
}
/**
* Close Button
*/
.rbt-close {
z-index: 1 !important;
}
.rbt-close-lg {
font-size: 24px !important;
}
/**
* Token
*/
.rbt-token {
background-color: #e7f4ff !important;
border: 0 !important;
border-radius: .25rem !important;
color: #007bff !important;
display: inline-block !important;
line-height: 1em !important;
margin: 1px 3px 2px 0 !important;
padding: 4px 7px !important;
position: relative !important;
}
.rbt-token-disabled {
background-color: rgba(0, 0, 0, 0.1) !important;
color: #495057 !important;
pointer-events: none !important;
}
.rbt-token-removeable {
cursor: pointer !important;
padding-right: 21px !important;
}
.rbt-token-active {
background-color: #007bff !important;
color: #fff !important;
outline: none !important;
text-decoration: none !important;
}
.rbt-token .rbt-token-remove-button {
bottom: 0 !important;
color: inherit !important;
font-size: inherit !important;
font-weight: normal !important;
opacity: 1 !important;
outline: none !important;
padding: 3px 7px !important;
position: absolute !important;
right: 0 !important;
text-shadow: none !important;
top: -2px !important;
}
/**
* Loader + CloseButton container
*/
.rbt-aux {
align-items: center !important;
display: flex !important;
bottom: 0 !important;
justify-content: center !important;
pointer-events: none !important;
/* Don't block clicks on the input */
position: absolute !important;
right: 0 !important;
top: 0 !important;
width: 34px !important;
}
.rbt-aux-lg {
width: 46px !important;
}
.rbt-aux .rbt-close {
margin-top: -4px !important;
pointer-events: auto !important;
/* Override pointer-events: none; above */
}
.has-aux .rbt-input {
padding-right: 34px !important;
}
.rbt-highlight-text {
background-color: inherit !important;
color: inherit !important;
font-weight: bold !important;
padding: 0 !important;
}
/**
* Input Groups
*/
.input-group > .rbt {
flex: 1 !important;
}
.input-group > .rbt .rbt-input-hint,
.input-group > .rbt .rbt-aux {
z-index: 5 !important;
}
.input-group > .rbt:not(:first-child) .form-control {
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
}
.input-group > .rbt:not(:last-child) .form-control {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
@@ -1,240 +0,0 @@
$animation: loader-animation 600ms infinite linear;
$inset: inset 0 1px 1px rgba(0, 0, 0, 0.075);
$placeholder-color: #999;
.rbt {
&-menu {
margin-bottom: 2px; // Spacing for dropup
& > li a {
overflow: hidden;
text-overflow: ellipsis;
&:focus {
outline: none;
}
}
&-pagination-option {
text-align: center;
}
}
// Hide IE's native "clear" button
& .rbt-input-main::-ms-clear {
display: none;
}
&-input-multi {
cursor: text;
overflow: hidden;
position: relative;
height: auto;
// Apply Bootstrap focus styles
&.focus {
box-shadow: $inset, 0 0 8px rgba(102, 175, 233, 0.6);
border-color: #66afe9;
outline: 0;
}
// BS4 uses the :disabled pseudo-class, which doesn't work with non-inputs.
&.form-control[disabled] {
background-color: #e9ecef;
opacity: 1;
}
// Apply Bootstrap placeholder styles
input {
// Firefox
&::-moz-placeholder {
color: $placeholder-color;
opacity: 1;
}
// Internet Explorer 10+
&:-ms-input-placeholder {
color: $placeholder-color;
}
// Safari and Chrome
&::-webkit-input-placeholder {
color: $placeholder-color;
}
}
.rbt-input-wrapper {
align-items: flex-start;
display: flex;
flex-wrap: wrap;
margin-bottom: -4px;
margin-top: -1px;
overflow: hidden;
}
.rbt-input-main {
// Set input height for cross-browser consistency
height: 20px;
margin: 1px 0 4px;
}
&.input,
&.form-control {
&-lg {
.rbt-input-main {
height: 24px;
}
}
&-sm {
.rbt-input-main {
height: 18px;
}
}
}
}
&-close {
z-index: 1;
&-lg {
font-size: 24px;
}
}
&-token {
background-color: #e7f4ff;
border: 0;
border-radius: 2px;
color: #1f8dd6;
display: inline-block;
line-height: 1em;
margin: 0 3px 3px 0;
padding: 4px 7px;
position: relative;
&-disabled {
background-color: #ddd;
color: #888;
pointer-events: none;
}
&-removeable {
cursor: pointer;
padding-right: 21px;
}
&-active {
background-color: #1f8dd6;
color: #fff;
outline: none;
text-decoration: none;
}
& &-remove-button {
bottom: 0;
color: inherit;
font-size: inherit;
font-weight: normal;
opacity: 1;
outline: none;
padding: 3px 7px;
position: absolute;
right: 0;
text-shadow: none;
top: -2px;
}
}
&-loader {
-moz-animation: $animation;
-webkit-animation: $animation;
animation: $animation;
border: 1px solid #d5d5d5;
border-radius: 50%;
border-top-color: #1f8dd6;
display: block;
height: 16px;
width: 16px;
&-lg {
height: 20px;
width: 20px;
}
}
&-aux {
align-items: center;
display: flex;
bottom: 0;
justify-content: center;
pointer-events: none; /* Don't block clicks on the input */
position: absolute;
right: 0;
top: 0;
width: 34px;
&-lg {
width: 46px;
}
& .rbt-close {
margin-top: -4px;
pointer-events: auto; /* Override pointer-events: none; above */
}
}
.has-aux &-input {
padding-right: 34px;
}
&-highlight-text {
background-color: inherit;
color: inherit;
font-weight: bold;
padding: 0;
}
}
/* Input Groups */
.input-group > .rbt {
flex: 1;
// Form-controls within input-groups have a higher z-index.
& .rbt-input-hint,
& .rbt-aux {
z-index: 5;
}
&:not(:first-child) .form-control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
&:not(:last-child) .form-control {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
/* Validation States */
.has-error .rbt-input-multi.focus {
border-color: #843534;
box-shadow: $inset, 0 0 6px #ce8483;
}
.has-warning .rbt-input-multi.focus {
border-color: #66512c;
box-shadow: $inset, 0 0 6px #c0a16b;
}
.has-success .rbt-input-multi.focus {
border-color: #2b542c;
box-shadow: $inset, 0 0 6px #67b168;
}
@keyframes loader-animation {
to {
transform: rotate(1turn);
}
}
-408
View File
@@ -1,408 +0,0 @@
div.timely .form-control {
display: block;
width: 100%;
height: calc(1.5em + 0.75rem + 2px);
padding: 0.375rem 0.75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
/*@media (prefers-reduced-motion: reduce) {*/
/* .form-control {*/
/* transition: none;*/
/* }*/
/*}*/
div.timely .form-control::-ms-expand {
background-color: transparent;
border: 0;
}
div.timely .form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #495057;
}
div.timely .form-control:focus {
color: #495057;
/*background-color: #fff;*/
border-color: #80bdff;
outline: 0;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
/*box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);*/
}
div.timely .form-control::-webkit-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-moz-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:disabled, div.timely .form-control[readonly] {
background-color: #e9ecef;
opacity: 1;
}
div.timely select.form-control:focus::-ms-value {
color: #495057;
background-color: #fff;
}
div.timely .form-control-file,
div.timely .form-control-range {
display: block;
width: 100%;
}
div.timely .form-control-plaintext {
display: block;
width: 100%;
padding: 0.375rem 0;
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
border: solid transparent;
border-width: 1px 0;
}
div.timely .form-control-plaintext.form-control-sm, div.timely .form-control-plaintext.form-control-lg {
padding-right: 0;
padding-left: 0;
}
div.timely .form-control-sm {
height: calc(1.5em + 0.5rem + 2px);
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
}
div.timely .form-control-lg {
height: calc(1.5em + 1rem + 2px);
padding: 0.5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: 0.3rem;
}
div.timely select.form-control[size], div.timely select.form-control[multiple] {
height: auto;
}
div.timely textarea.form-control {
height: auto;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
div.timely .dropup,
div.timely .dropright,
div.timely .dropdown,
div.timely .dropleft {
position: relative;
}
div.timely .dropdown-toggle {
white-space: nowrap;
}
div.timely .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
}
div.timely .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
}
div.timely .dropdown-menu-left {
right: auto;
left: 0;
}
div.timely .dropdown-menu-right {
right: 0;
left: auto;
}
/*@media (min-width: 576px) {*/
/* .dropdown-menu-sm-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-sm-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
/*@media (min-width: 768px) {*/
/* .dropdown-menu-md-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-md-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
/*@media (min-width: 992px) {*/
/* .dropdown-menu-lg-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-lg-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
/*@media (min-width: 1200px) {*/
/* .dropdown-menu-xl-left {*/
/* right: auto;*/
/* left: 0;*/
/* }*/
/* .dropdown-menu-xl-right {*/
/* right: 0;*/
/* left: auto;*/
/* }*/
/*}*/
div.timely .dropup .dropdown-menu {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 0.125rem;
}
div.timely .dropup .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0;
border-right: 0.3em solid transparent;
border-bottom: 0.3em solid;
border-left: 0.3em solid transparent;
}
div.timely .dropup .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropright .dropdown-menu {
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: 0.125rem;
}
div.timely .dropright .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
}
div.timely .dropright .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropright .dropdown-toggle::after {
vertical-align: 0;
}
div.timely .dropleft .dropdown-menu {
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: 0.125rem;
}
div.timely .dropleft .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
}
div.timely .dropleft .dropdown-toggle::after {
display: none;
}
div.timely .dropleft .dropdown-toggle::before {
display: inline-block;
margin-right: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0.3em solid;
border-bottom: 0.3em solid transparent;
}
div.timely .dropleft .dropdown-toggle:empty::after {
margin-left: 0;
}
div.timely .dropleft .dropdown-toggle::before {
vertical-align: 0;
}
div.timely .dropdown-menu[x-placement^="top"], div.timely .dropdown-menu[x-placement^="right"], div.timely .dropdown-menu[x-placement^="bottom"], div.timely .dropdown-menu[x-placement^="left"] {
right: auto;
bottom: auto;
}
div.timely .dropdown-divider {
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid #e9ecef;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-menu.show {
display: block;
}
div.timely .dropdown-header {
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
color: #6c757d;
white-space: nowrap;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
File diff suppressed because it is too large. Load diff
@@ -1,359 +1,323 @@
div.timely .form-control {
display: block;
width: 100%;
/*height: calc(1.5em + 0.75rem + 2px);*/
height: 32px;
/*padding: 0.375rem 0.75rem;*/
padding: 0px 8px;
/*font-size: 1rem;*/
font-size: 14px;
font-weight: 400;
line-height: 1.5;
border: 1px solid #ced4da;
/*border-radius: 0.25rem;*/
border-radius: 2px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
color: #495057;
background-color: #fff;
background-clip: padding-box;
display: block;
width: 100%;
height: 32px;
padding: 0px 8px;
font-size: 14px;
font-weight: 400;
line-height: 1.5;
border: 1px solid #ced4da;
border-radius: 2px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
background-clip: padding-box;
}
div.timely .form-control::-ms-expand {
background-color: transparent;
border: 0;
background-color: transparent;
border: 0;
}
div.timely .form-control:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #495057;
color: transparent;
text-shadow: 0 0 0 #495057;
}
div.timely .form-control:focus, div.timely input:focus {
border-color: #80bdff;
outline: 0;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
div.timely .form-control::-webkit-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-moz-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::-ms-input-placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control::placeholder {
color: #6c757d;
opacity: 1;
}
div.timely .form-control:disabled, div.timely .form-control[readonly] {
background-color: #e9ecef;
opacity: 1;
}
div.timely select.form-control:focus::-ms-value {
color: #495057;
background-color: #fff;
div.timely .form-control:focus,
div.timely input:focus {
border-color: #80bdff;
outline: 0;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
div.timely .form-control-file,
div.timely .form-control-range {
display: block;
width: 100%;
display: block;
width: 100%;
}
div.timely .form-control-plaintext {
display: block;
width: 100%;
padding: 0.375rem 0;
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
border: solid transparent;
border-width: 1px 0;
display: block;
width: 100%;
padding: 0.375rem 0;
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
border: solid transparent;
border-width: 1px 0;
}
div.timely .form-control-plaintext.form-control-sm, div.timely .form-control-plaintext.form-control-lg {
padding-right: 0;
padding-left: 0;
div.timely .form-control-plaintext.form-control-sm,
div.timely .form-control-plaintext.form-control-lg {
padding-right: 0;
padding-left: 0;
}
div.timely .form-control-sm {
height: calc(1.5em + 0.5rem + 2px);
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
height: calc(1.5em + 0.5rem + 2px);
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
}
div.timely .form-control-lg {
height: calc(1.5em + 1rem + 2px);
padding: 0.5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: 0.3rem;
height: calc(1.5em + 1rem + 2px);
padding: 0.5rem 1rem;
font-size: 1.25rem;
line-height: 1.5;
border-radius: 0.3rem;
}
div.timely select.form-control[size], div.timely select.form-control[multiple] {
height: auto;
div.timely select.form-control[size],
div.timely select.form-control[multiple] {
height: auto;
}
div.timely textarea.form-control {
height: auto;
height: auto;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
div.timely .dropdown-item:hover,
div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
div.timely .dropdown-item.active,
div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
div.timely .dropdown-item.disabled,
div.timely .dropdown-item:disabled {
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
div.timely .dropup,
div.timely .dropright,
div.timely .dropdown,
div.timely .dropleft {
position: relative;
position: relative;
}
div.timely .dropdown-toggle {
white-space: nowrap;
white-space: nowrap;
}
div.timely .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
}
div.timely .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 10rem;
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
}
div.timely .dropdown-menu-left {
right: auto;
left: 0;
right: auto;
left: 0;
}
div.timely .dropdown-menu-right {
right: 0;
left: auto;
right: 0;
left: auto;
}
div.timely .dropup .dropdown-menu {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 0.125rem;
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 0.125rem;
}
div.timely .dropup .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0;
border-right: 0.3em solid transparent;
border-bottom: 0.3em solid;
border-left: 0.3em solid transparent;
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0;
border-right: 0.3em solid transparent;
border-bottom: 0.3em solid;
border-left: 0.3em solid transparent;
}
div.timely .dropup .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropright .dropdown-menu {
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: 0.125rem;
top: 0;
right: auto;
left: 100%;
margin-top: 0;
margin-left: 0.125rem;
}
div.timely .dropright .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid transparent;
border-right: 0;
border-bottom: 0.3em solid transparent;
border-left: 0.3em solid;
}
div.timely .dropright .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropright .dropdown-toggle::after {
vertical-align: 0;
vertical-align: 0;
}
div.timely .dropleft .dropdown-menu {
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: 0.125rem;
top: 0;
right: 100%;
left: auto;
margin-top: 0;
margin-right: 0.125rem;
}
div.timely .dropleft .dropdown-toggle::after {
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: "";
display: inline-block;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
}
div.timely .dropleft .dropdown-toggle::after {
display: none;
display: none;
}
div.timely .dropleft .dropdown-toggle::before {
display: inline-block;
margin-right: 0.255em;
vertical-align: 0.255em;
content: "";
border-top: 0.3em solid transparent;
border-right: 0.3em solid;
border-bottom: 0.3em solid transparent;
display: inline-block;
margin-right: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid transparent;
border-right: 0.3em solid;
border-bottom: 0.3em solid transparent;
}
div.timely .dropleft .dropdown-toggle:empty::after {
margin-left: 0;
margin-left: 0;
}
div.timely .dropleft .dropdown-toggle::before {
vertical-align: 0;
vertical-align: 0;
}
div.timely .dropdown-menu[x-placement^="top"], div.timely .dropdown-menu[x-placement^="right"], div.timely .dropdown-menu[x-placement^="bottom"], div.timely .dropdown-menu[x-placement^="left"] {
right: auto;
bottom: auto;
div.timely .dropdown-menu[x-placement^='top'],
div.timely .dropdown-menu[x-placement^='right'],
div.timely .dropdown-menu[x-placement^='bottom'],
div.timely .dropdown-menu[x-placement^='left'] {
right: auto;
bottom: auto;
}
div.timely .dropdown-divider {
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid #e9ecef;
height: 0;
margin: 0.5rem 0;
overflow: hidden;
border-top: 1px solid #e9ecef;
}
div.timely .dropdown-item {
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
display: block;
width: 100%;
padding: 0.25rem 1.5rem;
clear: both;
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
div.timely .dropdown-item:hover, div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
div.timely .dropdown-item:hover,
div.timely .dropdown-item:focus {
color: #16181b;
text-decoration: none;
background-color: #f8f9fa;
}
div.timely .dropdown-item.active, div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
div.timely .dropdown-item.active,
div.timely .dropdown-item:active {
color: #fff;
text-decoration: none;
background-color: #007bff;
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
div.timely .dropdown-item.disabled,
div.timely .dropdown-item:disabled {
pointer-events: none;
background-color: transparent;
}
div.timely .dropdown-menu.show {
display: block;
display: block;
}
div.timely .dropdown-header {
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
color: #6c757d;
white-space: nowrap;
display: block;
padding: 0.5rem 1.5rem;
margin-bottom: 0;
font-size: 0.875rem;
white-space: nowrap;
}
div.timely .dropdown-item-text {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
display: block;
padding: 0.25rem 1.5rem;
}
+29 -33
View File
@@ -1,81 +1,77 @@
div.timely input:focus {
z-index: 1;
z-index: 1;
}
div.timely-edior-row div.gf-form-inline {
height: 40px !important;
height: 40px !important;
}
div.timely input.form-control {
border-color: rgb(44, 50, 53);
border-top-color: rgb(44, 50, 53);
border-right-color: rgb(44, 50, 53);
border-bottom-color: rgb(44, 50, 53);
border-left-color: rgb(44, 50, 53);
border-color: rgb(44, 50, 53);
border-top-color: rgb(44, 50, 53);
border-right-color: rgb(44, 50, 53);
border-bottom-color: rgb(44, 50, 53);
border-left-color: rgb(44, 50, 53);
}
div.timely.tag {
min-width: 16px !important;
padding-left: 2px;
padding-right: 2px;
min-width: 16px !important;
padding-left: 2px;
padding-right: 2px;
}
div.timely-edior-row div.gf-form {
margin-right: 4px !important;
margin-right: 4px !important;
}
div.timely.tag.error {
margin-left: 4px;
margin-left: 4px;
}
div.timely.tag.error svg {
color: #f19d06;
color: #f19d06;
}
div.timely.tag.edit {
margin-left: 6px;
margin-left: 6px;
}
div.timely.tag.edit svg {
color: #62A562;
color: #62a562;
}
div.timely.tag.save {
margin-left: 6px;
margin-left: 6px;
}
div.timely.tag.save svg {
color: #62A562;
color: #62a562;
}
div.timely.tag.delete svg {
color: #D9162D;
color: #d9162d;
}
div.timely.tag.addtag svg {
color: #62A562;
color: #62a562;
}
button[title="Move query down"] div svg {
color: #B3BFBD;
button[title='Move query down'] div svg {
color: #b3bfbd;
}
button[title="Move query up"] div svg {
color: #B3BFBD;
button[title='Move query up'] div svg {
color: #b3bfbd;
}
button[title="Duplicate query"] div svg {
color: #62A562;
button[title='Duplicate query'] div svg {
color: #62a562;
}
button[title="Disable/enable query"] div svg {
color: #2AB4F5;
button[title='Disable/enable query'] div svg {
color: #2ab4f5;
}
button[title="Remove query"] div svg {
color: #D9162D;
button[title='Remove query'] div svg {
color: #d9162d;
}
Loaded 100 of 202 files, more files were not shown because too many files have changed in this diff. Show more