Compare commits

..
Author SHA1 Message Date
Bill Oley 3072c2b0e7 Only reload cert and CA when changed
Only reload cert and CA when changed
2020-10-14 12:36:01 -04:00
71 changed files with 25351 additions and 3211 deletions

No files matched your search

+257 -257
View File
@@ -1,257 +1,257 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>timely-analytics</artifactId>
<!--
Execute "mvn clean package -Pbuild-jar"
to build a jar file out of this project!
How to use the Flink Quickstart pom:
a) Adding new dependencies:
You can add dependencies to the list below.
Please check if the maven-shade-plugin below is filtering out your dependency
and remove the exclude from there.
b) Build a jar for running on the cluster:
There are two options for creating a jar from this project
b.1) "mvn clean package" -> this will create a fat jar which contains all
dependencies necessary for running the jar created by this pom in a cluster.
The "maven-shade-plugin" excludes everything that is provided on a running Flink cluster.
b.2) "mvn clean package -Pbuild-jar" -> This will also create a fat-jar, but with much
nicer dependency exclusion handling. This approach is preferred and leads to
much cleaner jar files.
-->
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerId>jdt</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-compiler-jdt</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<!-- We use the maven-shade plugin to create a fat jar that contains all dependencies
except flink and it's transitive dependencies. The resulting fat-jar can be executed
on a cluster. Change the value of Program-Class if your program entry point changes. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<artifactSet>
<excludes>
<!-- This list contains all dependencies of flink-dist
Everything else will be packaged into the fat-jar
-->
<exclude>org.apache.flink:flink-annotations</exclude>
<exclude>org.apache.flink:flink-shaded-hadoop1_2.11</exclude>
<exclude>org.apache.flink:flink-shaded-hadoop2</exclude>
<exclude>org.apache.flink:flink-shaded-curator-recipes</exclude>
<exclude>org.apache.flink:flink-core</exclude>
<exclude>org.apache.flink:flink-java</exclude>
<exclude>org.apache.flink:flink-scala_2.11</exclude>
<exclude>org.apache.flink:flink-runtime_2.11</exclude>
<exclude>org.apache.flink:flink-optimizer_2.11</exclude>
<exclude>org.apache.flink:flink-clients_2.11</exclude>
<exclude>org.apache.flink:flink-avro_2.11</exclude>
<exclude>org.apache.flink:flink-examples-batch_2.11</exclude>
<exclude>org.apache.flink:flink-examples-streaming_2.11</exclude>
<exclude>org.apache.flink:flink-streaming-java_2.11</exclude>
<!-- Also exclude very big transitive dependencies of Flink
WARNING: You have to remove these excludes if your code relies on other
versions of these dependencies.
-->
<exclude>org.scala-lang:scala-library</exclude>
<exclude>org.scala-lang:scala-compiler</exclude>
<exclude>org.scala-lang:scala-reflect</exclude>
<exclude>com.typesafe.akka:akka-actor_*</exclude>
<exclude>com.typesafe.akka:akka-remote_*</exclude>
<exclude>com.typesafe.akka:akka-slf4j_*</exclude>
<exclude>io.netty:netty-all</exclude>
<exclude>io.netty:netty</exclude>
<exclude>commons-fileupload:commons-fileupload</exclude>
<exclude>org.apache.avro:avro</exclude>
<exclude>commons-collections:commons-collections</exclude>
<exclude>org.codehaus.jackson:jackson-core-asl</exclude>
<exclude>org.codehaus.jackson:jackson-mapper-asl</exclude>
<exclude>com.thoughtworks.paranamer:paranamer</exclude>
<exclude>org.xerial.snappy:snappy-java</exclude>
<exclude>org.apache.commons:commons-compress</exclude>
<exclude>org.tukaani:xz</exclude>
<exclude>com.esotericsoftware.kryo:kryo</exclude>
<exclude>com.esotericsoftware.minlog:minlog</exclude>
<exclude>org.objenesis:objenesis</exclude>
<exclude>com.twitter:chill_*</exclude>
<exclude>com.twitter:chill-java</exclude>
<exclude>commons-lang:commons-lang</exclude>
<exclude>junit:junit</exclude>
<exclude>org.apache.commons:commons-lang3</exclude>
<exclude>org.slf4j:slf4j-api</exclude>
<exclude>org.slf4j:slf4j-log4j12</exclude>
<exclude>log4j:log4j</exclude>
<exclude>org.apache.commons:commons-math</exclude>
<exclude>org.apache.sling:org.apache.sling.commons.json</exclude>
<exclude>commons-logging:commons-logging</exclude>
<exclude>commons-codec:commons-codec</exclude>
<exclude>com.fasterxml.jackson.core:jackson-core</exclude>
<exclude>com.fasterxml.jackson.core:jackson-databind</exclude>
<exclude>com.fasterxml.jackson.core:jackson-annotations</exclude>
<exclude>stax:stax-api</exclude>
<exclude>com.typesafe:config</exclude>
<exclude>org.uncommons.maths:uncommons-maths</exclude>
<exclude>com.github.scopt:scopt_*</exclude>
<exclude>commons-io:commons-io</exclude>
<exclude>commons-cli:commons-cli</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>org.apache.flink:*</artifact>
<excludes>
<!-- exclude shaded google but include shaded curator -->
<exclude>org/apache/flink/shaded/com/**</exclude>
<exclude>web-docs/**</exclude>
</excludes>
</filter>
<filter>
<!-- Do not copy the signatures in the META-INF folder.
Otherwise, this might cause SecurityExceptions when using the JAR.
-->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<!-- If you want to use ./bin/flink run <quickstart jar> uncomment the following lines.
This will add a Main-Class entry to the manifest file -->
<!--
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>jar.StreamingJob</mainClass>
</transformer>
</transformers>
-->
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- Profile for packaging correct JAR files -->
<id>build-jar</id>
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- disable the exclusion rules -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<artifactSet>
<excludes combine.self="override" />
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>timely-analytics</artifactId>
<!--
Execute "mvn clean package -Pbuild-jar"
to build a jar file out of this project!
How to use the Flink Quickstart pom:
a) Adding new dependencies:
You can add dependencies to the list below.
Please check if the maven-shade-plugin below is filtering out your dependency
and remove the exclude from there.
b) Build a jar for running on the cluster:
There are two options for creating a jar from this project
b.1) "mvn clean package" -> this will create a fat jar which contains all
dependencies necessary for running the jar created by this pom in a cluster.
The "maven-shade-plugin" excludes everything that is provided on a running Flink cluster.
b.2) "mvn clean package -Pbuild-jar" -> This will also create a fat-jar, but with much
nicer dependency exclusion handling. This approach is preferred and leads to
much cleaner jar files.
-->
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerId>jdt</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-compiler-jdt</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
<!-- We use the maven-shade plugin to create a fat jar that contains all dependencies
except flink and it's transitive dependencies. The resulting fat-jar can be executed
on a cluster. Change the value of Program-Class if your program entry point changes. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<!-- Run shade goal on package phase -->
<execution>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<artifactSet>
<excludes>
<!-- This list contains all dependencies of flink-dist
Everything else will be packaged into the fat-jar
-->
<exclude>org.apache.flink:flink-annotations</exclude>
<exclude>org.apache.flink:flink-shaded-hadoop1_2.11</exclude>
<exclude>org.apache.flink:flink-shaded-hadoop2</exclude>
<exclude>org.apache.flink:flink-shaded-curator-recipes</exclude>
<exclude>org.apache.flink:flink-core</exclude>
<exclude>org.apache.flink:flink-java</exclude>
<exclude>org.apache.flink:flink-scala_2.11</exclude>
<exclude>org.apache.flink:flink-runtime_2.11</exclude>
<exclude>org.apache.flink:flink-optimizer_2.11</exclude>
<exclude>org.apache.flink:flink-clients_2.11</exclude>
<exclude>org.apache.flink:flink-avro_2.11</exclude>
<exclude>org.apache.flink:flink-examples-batch_2.11</exclude>
<exclude>org.apache.flink:flink-examples-streaming_2.11</exclude>
<exclude>org.apache.flink:flink-streaming-java_2.11</exclude>
<!-- Also exclude very big transitive dependencies of Flink
WARNING: You have to remove these excludes if your code relies on other
versions of these dependencies.
-->
<exclude>org.scala-lang:scala-library</exclude>
<exclude>org.scala-lang:scala-compiler</exclude>
<exclude>org.scala-lang:scala-reflect</exclude>
<exclude>com.typesafe.akka:akka-actor_*</exclude>
<exclude>com.typesafe.akka:akka-remote_*</exclude>
<exclude>com.typesafe.akka:akka-slf4j_*</exclude>
<exclude>io.netty:netty-all</exclude>
<exclude>io.netty:netty</exclude>
<exclude>commons-fileupload:commons-fileupload</exclude>
<exclude>org.apache.avro:avro</exclude>
<exclude>commons-collections:commons-collections</exclude>
<exclude>org.codehaus.jackson:jackson-core-asl</exclude>
<exclude>org.codehaus.jackson:jackson-mapper-asl</exclude>
<exclude>com.thoughtworks.paranamer:paranamer</exclude>
<exclude>org.xerial.snappy:snappy-java</exclude>
<exclude>org.apache.commons:commons-compress</exclude>
<exclude>org.tukaani:xz</exclude>
<exclude>com.esotericsoftware.kryo:kryo</exclude>
<exclude>com.esotericsoftware.minlog:minlog</exclude>
<exclude>org.objenesis:objenesis</exclude>
<exclude>com.twitter:chill_*</exclude>
<exclude>com.twitter:chill-java</exclude>
<exclude>commons-lang:commons-lang</exclude>
<exclude>junit:junit</exclude>
<exclude>org.apache.commons:commons-lang3</exclude>
<exclude>org.slf4j:slf4j-api</exclude>
<exclude>org.slf4j:slf4j-log4j12</exclude>
<exclude>log4j:log4j</exclude>
<exclude>org.apache.commons:commons-math</exclude>
<exclude>org.apache.sling:org.apache.sling.commons.json</exclude>
<exclude>commons-logging:commons-logging</exclude>
<exclude>commons-codec:commons-codec</exclude>
<exclude>com.fasterxml.jackson.core:jackson-core</exclude>
<exclude>com.fasterxml.jackson.core:jackson-databind</exclude>
<exclude>com.fasterxml.jackson.core:jackson-annotations</exclude>
<exclude>stax:stax-api</exclude>
<exclude>com.typesafe:config</exclude>
<exclude>org.uncommons.maths:uncommons-maths</exclude>
<exclude>com.github.scopt:scopt_*</exclude>
<exclude>commons-io:commons-io</exclude>
<exclude>commons-cli:commons-cli</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>org.apache.flink:*</artifact>
<excludes>
<!-- exclude shaded google but include shaded curator -->
<exclude>org/apache/flink/shaded/com/**</exclude>
<exclude>web-docs/**</exclude>
</excludes>
</filter>
<filter>
<!-- Do not copy the signatures in the META-INF folder.
Otherwise, this might cause SecurityExceptions when using the JAR.
-->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<!-- If you want to use ./bin/flink run <quickstart jar> uncomment the following lines.
This will add a Main-Class entry to the manifest file -->
<!--
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>jar.StreamingJob</mainClass>
</transformer>
</transformers>
-->
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- Profile for packaging correct JAR files -->
<id>build-jar</id>
<dependencies>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-clients_2.11</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- disable the exclusion rules -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<artifactSet>
<excludes combine.self="override" />
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
+291 -291
View File
@@ -1,291 +1,291 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>timely-balancer</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-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>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>timely-balancer</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-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>
@@ -386,7 +386,7 @@ public class Balancer {
ensureZkPaths(curatorFramework, zkPaths);
AuthCache.configure(balancerConfig.getSecurity());
JWTTokenHandler.init(balancerConfig.getSecurity(), null);
JWTTokenHandler.init(balancerConfig.getSecurity());
final boolean useEpoll = useEpoll();
Class<? extends ServerSocketChannel> channelClass;
Class<? extends Channel> datagramChannelClass;
@@ -529,7 +529,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(4096, 32768, 8192, true, 128));
ch.pipeline().addLast("decoder", new HttpRequestDecoder());
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) {
if (request != null && request instanceof AutoCloseable) {
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.debug("Channel closed, closing subscriptions for subscriptionId:{}",
LOG.info("Channel closed, closing subscriptions for subscriptionId:%s",
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:{} - createSubscription not called?",
LOG.info("ChannelHandlerContext not found for subscriptionId:%s - 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:{} metric:{}", subscriptionId, metric);
LOG.info("client not found for subscriptionId:%s metric:%s", subscriptionId, metric);
}
}
}
@@ -550,8 +550,7 @@ 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()) {
TimelyBalancedHost tbh = metricToHostMap.get(e.getKey());
if (tbh != null && tbh.equals(h)) {
if (metricToHostMap.get(e.getKey()).equals(h)) {
rateSortedMetrics.put(e.getValue().getRate(), e.getKey());
}
}
@@ -738,26 +737,18 @@ 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);
// already write locked above
if (!balancerLock.isWriteLockedByCurrentThread()) {
balancerLock.readLock().unlock();
balancerLock.writeLock().lock();
}
metricMap.put(metric, rate);
}
rate.arrived();
} else {
if (rate != null) {
// already write locked above
metricMap.remove(metric);
}
metric = null;
}
@@ -973,9 +964,6 @@ 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()));
@@ -1038,8 +1026,6 @@ 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();
+150 -150
View File
@@ -1,150 +1,150 @@
<?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.3-SNAPSHOT</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.3.dev0</python.client.version>
</properties>
<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.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly-client</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</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>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>filter-setup</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<outputDirectory>${project.basedir}/src/main/python</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/python/template</directory>
<includes>
<include>setup.py</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>python</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>python-dist</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
<configuration>
<executable>python</executable>
<workingDirectory>${project.basedir}/src/main/python</workingDirectory>
<commandlineArgs>setup.py sdist --dist-dir ${project.build.directory}</commandlineArgs>
</configuration>
</execution>
<execution>
<id>python-clean</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
<configuration>
<executable>rm</executable>
<workingDirectory>${project.basedir}/src/main/python</workingDirectory>
<commandlineArgs>-rf timely.egg-info setup.py</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
<?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.1-SNAPSHOT</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.1.dev0</python.client.version>
</properties>
<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.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-client</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly-client</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</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>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>filter-setup</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<outputDirectory>${project.basedir}/src/main/python</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/python/template</directory>
<includes>
<include>setup.py</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>python</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>python-dist</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
<configuration>
<executable>python</executable>
<workingDirectory>${project.basedir}/src/main/python</workingDirectory>
<commandlineArgs>setup.py sdist --dist-dir ${project.build.directory}</commandlineArgs>
</configuration>
</execution>
<execution>
<id>python-clean</id>
<goals>
<goal>exec</goal>
</goals>
<phase>package</phase>
<configuration>
<executable>rm</executable>
<workingDirectory>${project.basedir}/src/main/python</workingDirectory>
<commandlineArgs>-rf timely.egg-info setup.py</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
@@ -2,14 +2,12 @@ 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;
@@ -96,42 +96,17 @@ 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);
osw = new OutputStreamWriter(sock.getOutputStream());
out = new BufferedWriter(osw);
out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
backoff = 2000;
LOG.trace("Connected to Timely at {}:{}", host, port);
} catch (Exception e) {
} catch (IOException e) {
LOG.error("Error connecting to Timely at {}:" + host + ":" + port + ". Error: " + 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;
}
+51 -51
View File
@@ -1,51 +1,51 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>collectd-nsq-plugin</artifactId>
<dependencies>
<dependency>
<groupId>collectd</groupId>
<artifactId>collectd-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>collectd-plugin-parent</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<artifactSet>
<includes />
</artifactSet>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>collectd-nsq-plugin</artifactId>
<dependencies>
<dependency>
<groupId>collectd</groupId>
<artifactId>collectd-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>collectd-plugin-parent</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<artifactSet>
<includes />
</artifactSet>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+32 -32
View File
@@ -1,32 +1,32 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>collectd-plugin-parent</artifactId>
<dependencies>
<dependency>
<groupId>collectd</groupId>
<artifactId>collectd-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-easymock-release-full</artifactId>
<classifier>full</classifier>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>collectd-plugin-parent</artifactId>
<dependencies>
<dependency>
<groupId>collectd</groupId>
<artifactId>collectd-api</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-easymock-release-full</artifactId>
<classifier>full</classifier>
<scope>test</scope>
</dependency>
</dependencies>
</project>
+68 -68
View File
@@ -1,68 +1,68 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>collectd-timely-plugin</artifactId>
<dependencies>
<dependency>
<groupId>collectd</groupId>
<artifactId>collectd-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>collectd-plugin-parent</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-easymock-release-full</artifactId>
<classifier>full</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<artifactSet>
<includes />
</artifactSet>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>collectd-timely-plugin</artifactId>
<dependencies>
<dependency>
<groupId>collectd</groupId>
<artifactId>collectd-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>collectd-plugin-parent</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.jcip</groupId>
<artifactId>jcip-annotations</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-easymock-release-full</artifactId>
<classifier>full</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<artifactSet>
<includes />
</artifactSet>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<id>shade</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+17 -17
View File
@@ -1,17 +1,17 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>timely-common</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>timely-common</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
+295 -295
View File
@@ -1,295 +1,295 @@
<?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.3-SNAPSHOT</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>
<?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.1-SNAPSHOT</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>
@@ -164,7 +164,7 @@ public class GrafanaRelayHandler extends SimpleChannelInboundHandler<HttpRequest
e.getMessage(), e.getLocalizedMessage(), e));
return;
} finally {
if (request != null) {
if (request != null && request instanceof AutoCloseable) {
ReferenceCountUtil.release(request);
}
}
+33 -33
View File
@@ -1,33 +1,33 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>timely-app</artifactId>
<packaging>pom</packaging>
<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>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>timely-app</artifactId>
<packaging>pom</packaging>
<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>assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+11 -2
View File
@@ -46079,7 +46079,7 @@ function t(t){return null!=t&&"object"==typeof t&&1===t.nodeType}function e(t,e)
var ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ "../node_modules/css-loader/dist/runtime/api.js");
exports = ___CSS_LOADER_API_IMPORT___(true);
// Module
exports.push([module.i, "div.timely .form-control {\n display: block;\n width: 100%;\n height: 32px;\n padding: 0px 8px;\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n border: 1px solid #ced4da;\n border-radius: 2px;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n background-clip: padding-box; }\n\ndiv.timely .form-control::-ms-expand {\n background-color: transparent;\n border: 0; }\n\ndiv.timely .form-control:-moz-focusring {\n color: transparent;\n text-shadow: 0 0 0 #495057; }\n\ndiv.timely .form-control:focus, div.timely input:focus {\n border-color: #80bdff;\n outline: 0;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }\n\ndiv.timely .form-control-file,\ndiv.timely .form-control-range {\n display: block;\n width: 100%; }\n\ndiv.timely .form-control-plaintext {\n display: block;\n width: 100%;\n padding: 0.375rem 0;\n margin-bottom: 0;\n font-size: 1rem;\n line-height: 1.5;\n border: solid transparent;\n border-width: 1px 0; }\n\ndiv.timely .form-control-plaintext.form-control-sm, div.timely .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0; }\n\ndiv.timely .form-control-sm {\n height: calc(1.5em + 0.5rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem; }\n\ndiv.timely .form-control-lg {\n height: calc(1.5em + 1rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem; }\n\ndiv.timely select.form-control[size], div.timely select.form-control[multiple] {\n height: auto; }\n\ndiv.timely textarea.form-control {\n height: auto; }\n\ndiv.timely .dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0; }\n\ndiv.timely .dropdown-item:hover, div.timely .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa; }\n\ndiv.timely .dropdown-item.active, div.timely .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff; }\n\ndiv.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {\n pointer-events: none;\n background-color: transparent; }\n\ndiv.timely .dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529; }\n\ndiv.timely .dropup,\ndiv.timely .dropright,\ndiv.timely .dropdown,\ndiv.timely .dropleft {\n position: relative; }\n\ndiv.timely .dropdown-toggle {\n white-space: nowrap; }\n\ndiv.timely .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent; }\n\ndiv.timely .dropdown-toggle:empty::after {\n margin-left: 0; }\n\ndiv.timely .dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem; }\n\ndiv.timely .dropdown-menu-left {\n right: auto;\n left: 0; }\n\ndiv.timely .dropdown-menu-right {\n right: 0;\n left: auto; }\n\ndiv.timely .dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem; }\n\ndiv.timely .dropup .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent; }\n\ndiv.timely .dropup .dropdown-toggle:empty::after {\n margin-left: 0; }\n\ndiv.timely .dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem; }\n\ndiv.timely .dropright .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0;\n border-bottom: 0.3em solid transparent;\n border-left: 0.3em solid; }\n\ndiv.timely .dropright .dropdown-toggle:empty::after {\n margin-left: 0; }\n\ndiv.timely .dropright .dropdown-toggle::after {\n vertical-align: 0; }\n\ndiv.timely .dropleft .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: 0.125rem; }\n\ndiv.timely .dropleft .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\"; }\n\ndiv.timely .dropleft .dropdown-toggle::after {\n display: none; }\n\ndiv.timely .dropleft .dropdown-toggle::before {\n display: inline-block;\n margin-righLine truncated
exports.push([module.i, "div.timely .form-control {\n display: block;\n width: 100%;\n /*height: calc(1.5em + 0.75rem + 2px);*/\n height: 32px;\n /*padding: 0.375rem 0.75rem;*/\n padding: 0px 8px;\n /*font-size: 1rem;*/\n font-size: 14px;\n font-weight: 400;\n line-height: 1.5;\n border: 1px solid #ced4da;\n /*border-radius: 0.25rem;*/\n border-radius: 2px;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n color: #495057;\n background-color: #fff;\n background-clip: padding-box; }\n\ndiv.timely .form-control::-ms-expand {\n background-color: transparent;\n border: 0; }\n\ndiv.timely .form-control:-moz-focusring {\n color: transparent;\n text-shadow: 0 0 0 #495057; }\n\ndiv.timely .form-control:focus, div.timely input:focus {\n border-color: #80bdff;\n outline: 0;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }\n\ndiv.timely .form-control::-moz-placeholder {\n color: #6c757d;\n opacity: 1; }\n\ndiv.timely .form-control:-ms-input-placeholder {\n color: #6c757d;\n opacity: 1; }\n\ndiv.timely .form-control::placeholder {\n color: #6c757d;\n opacity: 1; }\n\ndiv.timely .form-control:disabled, div.timely .form-control[readonly] {\n background-color: #e9ecef;\n opacity: 1; }\n\ndiv.timely select.form-control:focus::-ms-value {\n color: #495057;\n background-color: #fff; }\n\ndiv.timely .form-control-file,\ndiv.timely .form-control-range {\n display: block;\n width: 100%; }\n\ndiv.timely .form-control-plaintext {\n display: block;\n width: 100%;\n padding: 0.375rem 0;\n margin-bottom: 0;\n font-size: 1rem;\n line-height: 1.5;\n color: #212529;\n background-color: transparent;\n border: solid transparent;\n border-width: 1px 0; }\n\ndiv.timely .form-control-plaintext.form-control-sm, div.timely .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0; }\n\ndiv.timely .form-control-sm {\n height: calc(1.5em + 0.5rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem; }\n\ndiv.timely .form-control-lg {\n height: calc(1.5em + 1rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem; }\n\ndiv.timely select.form-control[size], div.timely select.form-control[multiple] {\n height: auto; }\n\ndiv.timely textarea.form-control {\n height: auto; }\n\ndiv.timely .dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0; }\n\ndiv.timely .dropdown-item:hover, div.timely .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa; }\n\ndiv.timely .dropdown-item.active, div.timely .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff; }\n\ndiv.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {\n color: #6c757d;\n pointer-events: none;\n background-color: transparent; }\n\ndiv.timely .dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529; }\n\ndiv.timely .dropup,\ndiv.timely .dropright,\ndiv.timely .dropdown,\ndiv.timely .dropleft {\n position: relative; }\n\ndiv.timely .dropdown-toggle {\n white-space: nowrap; }\n\ndiv.timely .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent; }\n\ndiv.timely .dropdown-toggle:empty::after {\n margin-left: 0; }\n\ndiv.timely .dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n color: #212529;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem; }\n\ndiv.timely .dropdown-menu-left {\n right: auto;\n left: 0; }\n\ndiv.timely .dropdown-menu-right {\n right: 0;\n left: auto; }\n\ndiv.timely .dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem; }\n\ndiv.timely .dropup .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent; }\n\ndiv.timely .dropup .dropdown-toggle:empty::after {\n margin-left: 0; }\n\ndiv.timely .dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem; }\n\ndiv.timely .dropright .dropdown-toggle::after {\n display: inline-block;\n margin-left: 0.255em;\n vertical-align: 0.255em;\nLine truncated
// Exports
module.exports = exports;
@@ -73571,7 +73571,16 @@ function (_super) {
tooltip: "Allow ssl connection with unverified or self-signed certificates",
checked: jsonData.allowInsecureSsl || false,
onChange: this.onAllowInsecureSslChange
})));
})), react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement("div", {
className: "gf-form"
}, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement("p", null, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement("a", {
className: "external-link",
target: "_blank",
href: "",
onClick: function onClick() {
return window.open("https://" + jsonData.timelyHost + ":" + jsonData.httpsPort + "/version", "_blank");
}
}, "Open a new browser tab/window to test https access"))));
};
return ConfigEditor;
+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:///../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
+2 -2
View File
@@ -30,8 +30,8 @@
}
],
"screenshots": [],
"version": "1.3.3-SNAPSHOT",
"updated": "2020-11-06"
"version": "1.3.1-SNAPSHOT",
"updated": "2020-10-14"
},
"dependencies": {
"classnames": "2.2.6",
+54
View File
@@ -0,0 +1,54 @@
$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
@@ -0,0 +1,201 @@
.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
@@ -0,0 +1,240 @@
$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
@@ -0,0 +1,408 @@
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
+48
View File
@@ -1,14 +1,20 @@
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;
}
@@ -28,6 +34,41 @@ div.timely .form-control:focus, div.timely input:focus {
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-file,
div.timely .form-control-range {
display: block;
@@ -41,6 +82,8 @@ div.timely .form-control-plaintext {
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
border: solid transparent;
border-width: 1px 0;
}
@@ -100,6 +143,7 @@ div.timely .dropdown-item.active, div.timely .dropdown-item:active {
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
@@ -147,6 +191,7 @@ div.timely .dropdown-menu {
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
@@ -289,6 +334,7 @@ div.timely .dropdown-item.active, div.timely .dropdown-item:active {
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
@@ -302,10 +348,12 @@ div.timely .dropdown-header {
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;
}
-1
View File
@@ -36,7 +36,6 @@ div.timely .dropdown-menu {
}
div.timely input.form-control:focus {
color: #c7d0d9;
outline: 0;
box-shadow: 0px 0px 0px 2px #141619, 0px 0px 0px 4px #1F60C4;
outline-offset: 2px;
+1 -1
View File
@@ -1 +1 @@
{"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,cAAc;IACd,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 color: #c7d0d9;\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":""}
{"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
View File
@@ -35,7 +35,6 @@ div.timely .dropdown-menu {
}
div.timely input.form-control:focus {
color: #464C54;
outline: 0;
box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #5794f2;
outline-offset: 2px;
+1 -1
View File
@@ -1 +1 @@
{"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,cAAc;IACd,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 color: #464C54;\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":""}
{"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.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "timely-datasource",
"version": "1.3.3-SNAPSHOT",
"version": "1.3.1-SNAPSHOT",
"description": "Timely",
"backend": true,
"alerting": true,
+94
View File
@@ -0,0 +1,94 @@
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"
"sync"
)
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,
CertPool: nil,
Certificate: nil,
ClientCertificatePath: "",
ClientKeyPath: "",
CertificateAuthorityPath: "",
Mutex: &sync.Mutex{},
}
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
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,81 @@
package main
import (
"bytes"
"context"
"encoding/json"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
func (dataSource *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 := dataSource.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
}
+332 -496
View File
@@ -1,526 +1,362 @@
package main
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"sort"
"strconv"
"strings"
"sync"
"time"
"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"
"sync"
"time"
"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"
"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}
}
type TimelyDatasource struct {
im instancemgmt.InstanceManager
Certificate *tls.Certificate
CertPool *x509.CertPool
ClientCertificatePath string
ClientKeyPath string
CertificateAuthorityPath string
Mutex *sync.Mutex
im instancemgmt.InstanceManager
Certificate *tls.Certificate
CertPool *x509.CertPool
ClientCertificatePath string
ClientKeyPath string
CertificateAuthorityPath string
Mutex *sync.Mutex
}
type TimelyDatasourceInstanceSettings struct {
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 := dataSource.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)
}
func newDataSourceInstance(setting backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
return &TimelyDatasourceInstanceSettings{}, nil
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 (s *TimelyDatasourceInstanceSettings) Dispose() {
// Called before creating a new instance to allow plugin authors
// to cleanup.
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 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{},
}
func (e *TimelyDatasource) convertTimelyQuery(timelyQueryForm *TimelyQueryForm) *TimelyQuery {
return datasource.ServeOpts{
CheckHealthHandler: ds,
CallResourceHandler: ds,
QueryDataHandler: ds,
}
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 (ds *TimelyDatasource) getSettings(pluginContext backend.PluginContext) (*TimelyDatasourceInstanceSettings, error) {
// iface, err := ds.im.Get(pluginContext)
// if err != nil {
// return nil, err
// }
//
// return iface.(*TimelyDatasourceInstanceSettings), nil
//}
func (dataSource *TimelyDatasource) changedClientSSLSettings(settings TimelyDataSourceOptions) bool {
// 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
clientCertificatePath := settings.ClientCertificatePath
clientKeyPath := settings.ClientKeyPath
certificateAuthorityPath := settings.CertificateAuthorityPath
return clientCertificatePath != dataSource.ClientCertificatePath || clientKeyPath != dataSource.ClientKeyPath ||
certificateAuthorityPath != dataSource.CertificateAuthorityPath
}
func (td *TimelyDatasource) CallResource(ctx context.Context, request *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
func (dataSource *TimelyDatasource) GetHttpClient(settings TimelyDataSourceOptions, useClientCertIfAvailable bool) (*http.Client, 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
}
// 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,
}
httpClient, err := td.GetHttpClient(timelyDataSourceOptions, true)
if err != nil {
logger.Error("Error getting httpClient", "error", err)
return err
}
clientCertificatePath := settings.ClientCertificatePath
clientKeyPath := settings.ClientKeyPath
certificateAuthorityPath := settings.CertificateAuthorityPath
if strings.HasPrefix(request.Path, "/api/aggregators") ||
strings.HasPrefix(request.Path, "/api/suggest") ||
strings.HasPrefix(request.Path, "/api/search/lookup") {
if dataSource.changedClientSSLSettings(settings) {
dataSource.Mutex.Lock()
// check again to prevent double initialization
if dataSource.changedClientSSLSettings(settings) {
// if clientCertificatePath or clientKeyPath changed, then re-read the
// client cert into the datasource and also save the new paths
if clientCertificatePath != dataSource.ClientCertificatePath || clientKeyPath != dataSource.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")
}
dataSource.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.")
}
dataSource.Certificate = nil
}
dataSource.ClientCertificatePath = clientCertificatePath
dataSource.ClientKeyPath = clientKeyPath
}
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 certificateAuthorityPath changed, then re-read the
// certificate authority into the datasource and also save the new path
if certificateAuthorityPath != dataSource.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")
}
dataSource.CertPool = x509.NewCertPool()
dataSource.CertPool.AppendCertsFromPEM(caCert)
logger.Debug("Completed setup of certificate authority", "ca_path", certificateAuthorityPath)
} else {
logger.Debug("Client connection updated with no certificate authority")
dataSource.CertPool = nil
}
dataSource.CertificateAuthorityPath = certificateAuthorityPath
}
}
dataSource.Mutex.Unlock()
}
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)
}
// protect against changes in-progress
dataSource.Mutex.Lock()
if useClientCertIfAvailable && dataSource.Certificate != nil {
tr.TLSClientConfig.Certificates = append(tr.TLSClientConfig.Certificates, *dataSource.Certificate)
}
if dataSource.CertPool != nil {
tr.TLSClientConfig.RootCAs = dataSource.CertPool
}
dataSource.Mutex.Unlock()
return httpClient, nil
}
+22
View File
@@ -185,6 +185,28 @@ export class ConfigEditor extends PureComponent<Props, State> {
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>
);
}
@@ -0,0 +1,54 @@
$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;
}
}
@@ -0,0 +1,201 @@
.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;
}
@@ -0,0 +1,240 @@
$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
@@ -0,0 +1,408 @@
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,14 +1,20 @@
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;
}
@@ -28,6 +34,41 @@ div.timely .form-control:focus, div.timely input:focus {
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-file,
div.timely .form-control-range {
display: block;
@@ -41,6 +82,8 @@ div.timely .form-control-plaintext {
margin-bottom: 0;
font-size: 1rem;
line-height: 1.5;
color: #212529;
background-color: transparent;
border: solid transparent;
border-width: 1px 0;
}
@@ -100,6 +143,7 @@ div.timely .dropdown-item.active, div.timely .dropdown-item:active {
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
@@ -147,6 +191,7 @@ div.timely .dropdown-menu {
padding: 0.5rem 0;
margin: 0.125rem 0 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
@@ -289,6 +334,7 @@ div.timely .dropdown-item.active, div.timely .dropdown-item:active {
}
div.timely .dropdown-item.disabled, div.timely .dropdown-item:disabled {
color: #6c757d;
pointer-events: none;
background-color: transparent;
}
@@ -302,10 +348,12 @@ div.timely .dropdown-header {
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;
}
-1
View File
@@ -36,7 +36,6 @@ div.timely .dropdown-menu {
}
div.timely input.form-control:focus {
color: #c7d0d9;
outline: 0;
box-shadow: 0px 0px 0px 2px #141619, 0px 0px 0px 4px #1F60C4;
outline-offset: 2px;
-1
View File
@@ -35,7 +35,6 @@ div.timely .dropdown-menu {
}
div.timely input.form-control:focus {
color: #464C54;
outline: 0;
box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #5794f2;
outline-offset: 2px;
+839 -839
View File
File diff suppressed because it is too large. Load diff
-47
View File
@@ -1,47 +0,0 @@
#!/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-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.yml
else
FILENAME=timely-${i}.yml
fi
echo "creating configuration file ${CONF_DIR}/${FILENAME}"
cp ${CONF_DIR}/timely-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}
sed -i "s/\${AGE_OFF_DAYS}/${AGE_OFF_DAYS}/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/\${ACCUMULO_USER}/${ACCUMULO_USER}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${ACCUMULO_PASSWORD}/${ACCUMULO_PASSWORD}/g" ${CONF_DIR}/${FILENAME}
sed -i "s/\${INSTANCE}/${i}/g" ${CONF_DIR}/${FILENAME}
done
+1 -1
View File
@@ -7,7 +7,7 @@ else
fi
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BASE_DIR=${THIS_DIR}/..
CONF_DIR="${BASE_DIR}/conf"
LIB_DIR="${BASE_DIR}/lib"
+1 -1
View File
@@ -7,7 +7,7 @@ else
fi
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BASE_DIR=${THIS_DIR}/..
CONF_DIR="${BASE_DIR}/conf"
LIB_DIR="${BASE_DIR}/lib"
+1 -1
View File
@@ -7,7 +7,7 @@ else
fi
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BASE_DIR=${THIS_DIR}/..
LIB_DIR="${BASE_DIR}/lib"
NUM_SERVER_THREADS=4
CONF_DIR="${BASE_DIR}/conf"
+1 -1
View File
@@ -7,7 +7,7 @@ else
fi
THIS_DIR="${THIS_SCRIPT%/*}"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BASE_DIR=${THIS_DIR}/..
LIB_DIR="${BASE_DIR}/lib"
NUM_SERVER_THREADS=4
CONF_DIR="${BASE_DIR}/conf"
-23
View File
@@ -1,23 +0,0 @@
#!/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-env.sh
if [ "$NUM_PROFILES" -eq "1" ]; then
echo ${BIN_DIR}/timely-server.sh
${BIN_DIR}/timely-server.sh
else
for i in $(seq 1 $NUM_PROFILES); do
echo ${BIN_DIR}/timely-server.sh $i
${BIN_DIR}/timely-server.sh $i
done
fi
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
pkill -9 -f timely.Server
-12
View File
@@ -1,12 +0,0 @@
#!/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
AGE_OFF_DAYS=7
ACCUMULO_USER=root
ACCUMULO_PASSWORD=secret
+26 -55
View File
@@ -9,62 +9,33 @@ 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 [ -n "$1" ]; then
export PROFILE_NUM=$1
PROFILE_ARG="--spring.profiles.active=${PROFILE_NUM}"
PID=`jps -m | grep Server | grep "spring.profiles.active=${PROFILE_NUM}" | awk '{print $1}'`
else
export PROFILE_NUM=""
PID=`jps -m | grep Server | awk '{print $1}'`
if [[ -e ${TMP_DIR} ]]; then
rm -rf ${TMP_DIR}
fi
mkdir ${TMP_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="-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} -Xmx4G -Xms4G -XX:NewSize=1G -XX:MaxNewSize=1G -XX:+UnlockDiagnosticVMOptions"
JVM_ARGS="${JVM_ARGS} -XX:+UseConcMarkSweepGC -XX:+CMSScavengeBeforeRemark -XX:+ScavengeBeforeFullGC -XX:ReservedCodeCacheSize=384M -XX:+UseCodeCacheFlushing -XX:+UseParNewGC"
JVM_ARGS="${JVM_ARGS} -XX:SurvivorRatio=8 -XX:ParallelGCThreads=16 -XX:ConcGCThreads=8 -XX:+UseCondCardMark -XX:ParGCCardsPerStrideChunk=32768"
JVM_ARGS="${JVM_ARGS} -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=30 -XX:+UseCMSInitiatingOccupancyOnly"
JVM_ARGS="${JVM_ARGS} -XX:+UseCompressedOops -XX:+UseNUMA -Djava.net.preferIPv4Stack=true"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely ${PROFILE_ARG}"
nohup $JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely ${PROFILE_ARG} >> ${LOG_DIR}/timely-server${PROFILE_NUM}-startup.log 2>&1 &
else
if [ "$PROFILE_NUM" == ""]; then
echo "timely-server already running with pid ${PID}"
else
echo "timely-server ${PROFILE_NUM} already running with pid ${PID}"
fi
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="-Xmx256m -Xms256m -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}"
echo "$JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely"
$JAVA_HOME/bin/java ${JVM_ARGS} timely.Server --spring.config.name=timely
+1 -1
View File
@@ -10,7 +10,7 @@ fi
THIS_DIR="${THIS_SCRIPT%/*}"
NATIVE_DIR="${THIS_DIR}/META-INF/native"
BASE_DIR=$(cd $THIS_DIR/.. && pwd)
BASE_DIR=${THIS_DIR}/..
TMP_DIR="${BASE_DIR}/tmp"
CONF_DIR="${BASE_DIR}/conf"
LIB_DIR="${BASE_DIR}/lib"
+18 -4
View File
@@ -5,19 +5,33 @@
<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="${env:LOG_DIR}/timely-server${env:PROFILE_NUM}.log"
filePattern="${env:LOG_DIR}/$${date:yyyy-MM}/timely-server${env:PROFILE_NUM}-%d{MM-dd-yyyy}-%i.log.gz">
<RollingRandomAccessFile name="Rolling" fileName="logs/timely-server.log"
filePattern="logs/$${date:yyyy-MM}/timely-server-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1024 MB" />
</Policies>
<DefaultRolloverStrategy max="10" />
</RollingRandomAccessFile>
<RollingRandomAccessFile name="Subscription" fileName="logs/timely-subscriptions.log"
filePattern="logs/$${date:yyyy-MM}/timely-subscriptions-%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="warn" includeLocation="false">
<Root level="debug" includeLocation="false">
<AppenderRef ref="Console" level="warn" />
<AppenderRef ref="Rolling" level="debug" />
</Root>
<Logger name="timely" level="debug"/>
<Logger name="timely" additivity="false">
<AppenderRef ref="Console" level="debug" />
</Logger>
</Loggers>
</Configuration>
-74
View File
@@ -1,74 +0,0 @@
timely:
instance: ${INSTANCE}
metrics-table: timely.metrics
meta-table: timely.meta
metric-age-off-days:
default: ${AGE_OFF_DAYS}
cache:
enabled: true
age-off-hours:
default: 26
metrics-report-ignored-tags:
defaultVisibility:
accumulo:
instance-name: accumulo
zookeepers: ${ZOOKEEPERS}
username: ${ACCUMULO_USER}
password: ${ACCUMULO_PASSWORD}
write:
latency: 5s
threads: 3
bufferSize: 52428800
scan:
threads: 4
max-downsample-memory: 10000000
security:
session-max-age: 86400
cache-expiration-minutes: 60
cache-refresh-minutes: 5
allow-anonymous-http-access: true
allow-anonymous-ws-access: true
server-ssl:
certificate-file:
key-file:
key-password:
use-generated-keypair: true
trust-store-file:
use-openssl: true
#use-ciphers:
jwtCheckKeyStore:
jwtCheckKeyType:
jwtCheckKeyPassword:
server:
ip: ${HOST_IP}
tcp-port: ${TCP_PORT}
udp-port: ${UDP_PORT}
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
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
meta-cache:
expiration-minutes: 1440
cache-refresh-minutes: 60
max-tag-values: 100
visibility-cache:
expiration-minutes: 60
+303 -303
View File
@@ -1,303 +1,303 @@
<?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.3-SNAPSHOT</version>
</parent>
<artifactId>timely-server</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-guava</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>fi.iki.yak</groupId>
<artifactId>compression-gorilla</artifactId>
</dependency>
<dependency>
<groupId>io.github.lukehutch</groupId>
<artifactId>fast-classpath-scanner</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</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.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.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-client</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.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-easymock-release-full</artifactId>
<classifier>full</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</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>
<?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.1-SNAPSHOT</version>
</parent>
<artifactId>timely-server</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-guava</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>fi.iki.yak</groupId>
<artifactId>compression-gorilla</artifactId>
</dependency>
<dependency>
<groupId>io.github.lukehutch</groupId>
<artifactId>fast-classpath-scanner</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</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.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.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-client</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.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-easymock-release-full</artifactId>
<classifier>full</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>timely</groupId>
<artifactId>timely-common</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>
+2 -2
View File
@@ -453,7 +453,7 @@ public class Server {
MetaCacheFactory.getCache(config);
AuthCache.configure(config.getSecurity());
VisibilityCache.init(config);
JWTTokenHandler.init(config.getSecurity(), config.getAccumulo());
JWTTokenHandler.init(config.getSecurity());
final boolean useEpoll = useEpoll();
Class<? extends ServerSocketChannel> channelClass;
Class<? extends Channel> datagramChannelClass;
@@ -604,7 +604,7 @@ public class Server {
ch.pipeline().addLast("ssl", new NonSslRedirectHandler(config.getHttp(), sslCtx));
ch.pipeline().addLast("encoder", new HttpResponseEncoder());
ch.pipeline().addLast("decoder", new HttpRequestDecoder(4096, 32768, 8192, true, 128));
ch.pipeline().addLast("decoder", new HttpRequestDecoder());
ch.pipeline().addLast("compressor", new HttpContentCompressor());
ch.pipeline().addLast("decompressor", new HttpContentDecompressor());
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
@@ -1,18 +1,17 @@
package timely.api.response.timeseries;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang3.builder.ToStringBuilder;
@JsonPropertyOrder({ "metric", "tags", "aggregatedTags", "dps" })
public class QueryResponse {
private String metric;
private Map<String, String> tags = new LinkedHashMap<>();
private Map<String, String> tags = new HashMap<>();
private List<String> aggregatedTags = new ArrayList<>();
private Map<String, Object> dps = new LinkedHashMap<>();
@@ -1,21 +1,18 @@
package timely.api.response.timeseries;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
@JsonPropertyOrder({ "type", "metric", "tags", "limit", "time", "totalResults", "results" })
public class SearchLookupResponse {
@JsonPropertyOrder({ "tags", "metric", "tsuid" })
public static class Result {
private Map<String, String> tags = new LinkedHashMap<>();
private Map<String, String> tags = new HashMap<>();
private String metric;
private String tsuid;
@@ -80,7 +77,7 @@ public class SearchLookupResponse {
private String type;
private String metric;
private Map<String, String> tags = new LinkedHashMap<>();
private Map<String, String> tags = new HashMap<>();
private int limit;
private int time;
private int totalResults;
@@ -134,15 +134,11 @@ public class AuthCache {
}
TimelyAuthenticationToken token = request.getToken();
String sessionId = request.getSessionId();
String oauthToken = request.getRequestHeader(AuthenticationService.AUTH_HEADER);
if (oauthToken != null) {
auths = getAuthorizations(token.getTimelyPrincipal().getName());
} else if (StringUtils.isBlank(sessionId) && token.getClientCert() == null) {
if (StringUtils.isBlank(sessionId) && token.getClientCert() == null) {
if (anonAccessAllowed) {
auths = Collections.singletonList(Authorizations.EMPTY);
} else {
throw new IllegalArgumentException(
"User must authenticate with a client certificate, OAuth token, or login credentials");
throw new IllegalArgumentException("User must provide either a sessionId or a client certificate");
}
} else if (StringUtils.isNotBlank(sessionId)) {
auths = getAuthorizations(sessionId);
@@ -1,29 +1,18 @@
package timely.auth;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import io.jsonwebtoken.*;
import org.apache.accumulo.core.client.ClientConfiguration;
import org.apache.accumulo.core.client.Connector;
import org.apache.accumulo.core.client.Instance;
import org.apache.accumulo.core.client.ZooKeeperInstance;
import org.apache.accumulo.core.client.security.tokens.PasswordToken;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import timely.configuration.Accumulo;
import timely.configuration.Security;
/**
@@ -35,50 +24,24 @@ public class JWTTokenHandler {
private static final Logger logger = LoggerFactory.getLogger(JWTTokenHandler.class);
private static Key signatureCheckKey;
private static ObjectMapper objectMapper;
private static Collection<String> accumuloAuths = new TreeSet<>();
public static void init(Security security, Accumulo accumulo) {
public static void init(Security security) {
if (StringUtils.isNotBlank(security.getJwtCheckKeyStore())) {
try {
String type = security.getJwtCheckKeyType();
if (type.equals("X.509")) {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
InputStream is = ResourceUtils.getURL(security.getJwtCheckKeyStore()).openStream();
X509Certificate certificate = (X509Certificate) factory.generateCertificate(is);
JWTTokenHandler.signatureCheckKey = certificate.getPublicKey();
} else {
KeyStore keyStore = KeyStore.getInstance(type == null ? "JKS" : type);
char[] keyPassword = security.getJwtCheckKeyPassword() == null ? null
: security.getJwtCheckKeyPassword().toCharArray();
keyStore.load(ResourceUtils.getURL(security.getJwtCheckKeyStore()).openStream(), keyPassword);
String alias = keyStore.aliases().nextElement();
Certificate cert = keyStore.getCertificate(alias);
JWTTokenHandler.signatureCheckKey = cert.getPublicKey();
}
KeyStore keyStore = KeyStore
.getInstance(security.getJwtCheckKeyType() == null ? "JKS" : security.getJwtCheckKeyType());
char[] keyPassword = security.getJwtCheckKeyPassword() == null ? null
: security.getJwtCheckKeyPassword().toCharArray();
keyStore.load(ResourceUtils.getURL(security.getJwtCheckKeyStore()).openStream(), keyPassword);
String alias = keyStore.aliases().nextElement();
Certificate cert = keyStore.getCertificate(alias);
JWTTokenHandler.signatureCheckKey = cert.getPublicKey();
JWTTokenHandler.objectMapper = new ObjectMapper();
JWTTokenHandler.objectMapper.registerModule(new GuavaModule());
} catch (Exception e) {
throw new IllegalStateException("Invalid SSL configuration.", e);
}
}
JWTTokenHandler.objectMapper = new ObjectMapper();
JWTTokenHandler.objectMapper.registerModule(new GuavaModule());
if (accumulo != null) {
try {
final Map<String, String> properties = new HashMap<>();
properties.put("instance.name", accumulo.getInstanceName());
properties.put("instance.zookeeper.host", accumulo.getZookeepers());
properties.put("instance.zookeeper.timeout", accumulo.getZookeeperTimeout());
final ClientConfiguration aconf = ClientConfiguration.fromMap(properties);
final Instance instance = new ZooKeeperInstance(aconf);
Connector connector = instance.getConnector(accumulo.getUsername(),
new PasswordToken(accumulo.getPassword()));
Authorizations currentAccumuloAuths = connector.securityOperations()
.getUserAuthorizations(connector.whoami());
currentAccumuloAuths.iterator()
.forEachRemaining(a -> accumuloAuths.add(new String(a, Charset.forName("UTF-8"))));
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
public static Collection<TimelyUser> createUsersFromToken(String token, String claimName) {
@@ -91,14 +54,7 @@ public class JWTTokenHandler {
throw new IllegalArgumentException(
"JWT for " + claims.getSubject() + " does not contain any proxied principals.");
}
// convert to TimelyUser and downgrade auths to contain only what the
// accumuloUser has
return principalsClaim.stream().map(obj -> objectMapper.convertValue(obj, TimelyUser.class)).map(u -> {
Collection<String> intersectedAuths = new ArrayList<>(u.getAuths());
intersectedAuths.removeIf(a -> !accumuloAuths.contains(a));
return new TimelyUser(u.getDn(), u.getUserType(), u.getEmail(), intersectedAuths, u.getRoles(),
u.getRoleToAuthMapping(), u.getCreationTime(), u.getExpirationTime());
}).collect(Collectors.toList());
return principalsClaim.stream().map(obj -> objectMapper.convertValue(obj, TimelyUser.class))
.collect(Collectors.toList());
}
}
@@ -134,13 +134,15 @@ public class HttpRequestDecoder extends MessageToMessageDecoder<FullHttpRequest>
}
((AuthenticatedRequest) request).setToken(token);
}
request.setHttpRequest(msg.retain());
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
out.add(msg.retain());
// Return the original http request to route to the static file
// server
msg.retain();
out.add(msg);
return;
}
try {
@@ -142,7 +142,7 @@ public class WebSocketRequestDecoder extends MessageToMessageDecoder<WebSocketFr
}
} else if (evt instanceof SslCompletionEvent) {
LOG.debug("{}", ((SslCompletionEvent) evt).getClass().getSimpleName());
} else if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
} else if (evt instanceof WebSocketServerProtocolHandler.ServerHandshakeStateEvent) {
// The handshake completed succesfully and the channel was upgraded to
// websockets
LOG.trace("SSL handshake completed successfully, upgraded channel to websockets");
@@ -350,7 +350,7 @@ public class DataStoreCache {
}
private void ageOffGorillaStores() {
long stamp = gorillaMapLock.writeLock();
long stamp = gorillaMapLock.readLock();
try {
long numRemovedTotal = 0;
long now = System.currentTimeMillis();
@@ -393,7 +393,7 @@ public class DataStoreCache {
}
LOG.trace("ageOffGorillaStores aged off {} archived Gorilla compressors", numRemovedTotal);
} finally {
gorillaMapLock.unlockWrite(stamp);
gorillaMapLock.unlockRead(stamp);
}
}
@@ -24,7 +24,7 @@ public class QueryResponseTest {
r.putDps("1234567900", 3.5);
r.putDps("1234567910", 2.5);
String result = JsonUtil.getObjectMapper().writeValueAsString(Collections.singletonList(r));
String expected = "[{\"metric\":\"sys.cpu.user\",\"tags\":{\"host\":\"localhost\",\"rack\":\"r1\"},\"aggregatedTags\":[],\"dps\":{\"1234567890\":4.5,\"1234567900\":3.5,\"1234567910\":2.5}}]";
String expected = "[{\"metric\":\"sys.cpu.user\",\"tags\":{\"rack\":\"r1\",\"host\":\"localhost\"},\"aggregatedTags\":[],\"dps\":{\"1234567890\":4.5,\"1234567900\":3.5,\"1234567910\":2.5}}]";
Assert.assertEquals(expected, result);
}
}
@@ -35,7 +35,7 @@ public class SearchLookupResponseTest {
response.setResults(results);
response.setTotalResults(results.size());
String r = JsonUtil.getObjectMapper().writeValueAsString(response);
String expected = "{\"type\":\"LOOKUP\",\"metric\":\"sys.cpu.user\",\"tags\":{\"host\":\"localhost\",\"rack\":\"r1\"},\"limit\":0,\"time\":1500,\"totalResults\":2,\"results\":[{\"tags\":{\"host\":\"localhost\",\"rack\":\"r1\"},\"metric\":\"sys.cpu.idle\",\"tsuid\":\"000011000008203D00\"},{\"tags\":{\"host\":\"localhost\",\"rack\":\"r1\"},\"metric\":\"sys.cpu.user\",\"tsuid\":\"000011000008203D01\"}]}";
String expected = "{\"type\":\"LOOKUP\",\"metric\":\"sys.cpu.user\",\"tags\":{\"rack\":\"r1\",\"host\":\"localhost\"},\"limit\":0,\"time\":1500,\"totalResults\":2,\"results\":[{\"tags\":{\"rack\":\"r1\",\"host\":\"localhost\"},\"metric\":\"sys.cpu.idle\",\"tsuid\":\"000011000008203D00\"},{\"tags\":{\"rack\":\"r1\",\"host\":\"localhost\"},\"metric\":\"sys.cpu.user\",\"tsuid\":\"000011000008203D01\"}]}";
Assert.assertEquals(expected, r);
SearchLookupResponse slr = JsonUtil.getObjectMapper().readValue(r, SearchLookupResponse.class);
Assert.assertEquals(response, slr);
@@ -2,7 +2,6 @@ package timely.auth;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.UUID;
@@ -56,9 +55,7 @@ public class AuthCacheTest {
Collection<Authorizations> auths = AuthCache.getAuthorizations(cookie);
Assert.assertEquals(1, auths.size());
Authorizations a = auths.iterator().next();
String[] authStrings = a.toString().split(",");
Arrays.sort(authStrings);
Assert.assertEquals("[A, B, C]", Arrays.toString(authStrings));
Assert.assertEquals("A,B,C", a.toString());
}
}