summaryrefslogtreecommitdiffstats
path: root/sources/hv-collector-utils
diff options
context:
space:
mode:
Diffstat (limited to 'sources/hv-collector-utils')
-rw-r--r--sources/hv-collector-utils/pom.xml140
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/core.kt47
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/effects.kt69
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/ArgBasedConfiguration.kt57
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt142
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentError.kt70
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/extensions.kt66
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/http.kt81
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/ratpack.kt77
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/Logger.kt137
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/reactive_logging.kt28
-rw-r--r--sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/server_handle.kt46
-rw-r--r--sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/CoreKtTest.kt141
-rw-r--r--sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOptionTest.kt62
-rw-r--r--sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentErrorTest.kt61
-rw-r--r--sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/http/ResponsesTest.kt101
-rw-r--r--sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/logging/LoggerTest.kt230
17 files changed, 1555 insertions, 0 deletions
diff --git a/sources/hv-collector-utils/pom.xml b/sources/hv-collector-utils/pom.xml
new file mode 100644
index 00000000..66879ff7
--- /dev/null
+++ b/sources/hv-collector-utils/pom.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ ============LICENSE_START=======================================================
+ ~ dcaegen2-collectors-veshv
+ ~ ================================================================================
+ ~ Copyright (C) 2018 NOKIA
+ ~ ================================================================================
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~ ============LICENSE_END=========================================================
+ -->
+<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>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+
+ <properties>
+ <skipAnalysis>false</skipAnalysis>
+ </properties>
+
+ <parent>
+ <groupId>org.onap.dcaegen2.collectors.hv-ves</groupId>
+ <artifactId>hv-collector-sources</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <artifactId>hv-collector-utils</artifactId>
+ <description>VES HighVolume Collector :: Utilities</description>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <groupId>org.jetbrains.kotlin</groupId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <groupId>org.apache.maven.plugins</groupId>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.parent.groupId}</groupId>
+ <artifactId>hv-collector-domain</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-reflect</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.arrow-kt</groupId>
+ <artifactId>arrow-instances-data</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.arrow-kt</groupId>
+ <artifactId>arrow-effects</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.arrow-kt</groupId>
+ <artifactId>arrow-syntax</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-coroutines-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.ratpack</groupId>
+ <artifactId>ratpack-core</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>javax.json</groupId>
+ <artifactId>javax.json-api</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-test</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.spek</groupId>
+ <artifactId>spek-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.spek</groupId>
+ <artifactId>spek-junit-platform-engine</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-test</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.nhaarman.mockitokotlin2</groupId>
+ <artifactId>mockito-kotlin</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish</groupId>
+ <artifactId>javax.json</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/core.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/core.kt
new file mode 100644
index 00000000..7381592d
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/core.kt
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.arrow
+
+import arrow.core.Either
+import arrow.core.Option
+import arrow.core.identity
+import arrow.syntax.collections.firstOption
+import java.util.concurrent.atomic.AtomicReference
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since July 2018
+ */
+
+fun <A> Either<A, A>.flatten() = fold(::identity, ::identity)
+
+fun <B> Either<Throwable, B>.rightOrThrow() = fold({ throw it }, ::identity)
+
+fun <A, B> Either<A, B>.rightOrThrow(mapper: (A) -> Throwable) = fold({ throw mapper(it) }, ::identity)
+
+fun <A> AtomicReference<A>.getOption() = Option.fromNullable(get())
+
+fun <A> Option.Companion.fromNullablesChain(firstValue: A?, vararg nextValues: () -> A?): Option<A> =
+ if (firstValue != null)
+ Option.just(firstValue)
+ else nextValues.asSequence()
+ .map { it() }
+ .filter { it != null }
+ .firstOption()
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/effects.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/effects.kt
new file mode 100644
index 00000000..05d13094
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/effects.kt
@@ -0,0 +1,69 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.arrow
+
+import arrow.core.Either
+import arrow.core.Left
+import arrow.core.Right
+import arrow.effects.IO
+import reactor.core.publisher.Flux
+import reactor.core.publisher.Mono
+import kotlin.system.exitProcess
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since June 2018
+ */
+
+sealed class ExitCode {
+ abstract val code: Int
+
+ fun io() = IO {
+ exitProcess(code)
+ }
+}
+
+object ExitSuccess : ExitCode() {
+ override val code = 0
+}
+
+data class ExitFailure(override val code: Int) : ExitCode()
+
+fun Either<IO<Unit>, IO<Unit>>.unsafeRunEitherSync(onError: (Throwable) -> ExitCode, onSuccess: () -> Unit) =
+ flatten().attempt().unsafeRunSync().fold({ onError(it).io().unsafeRunSync() }, { onSuccess() })
+
+
+fun IO<Any>.unit() = map { Unit }
+
+fun <T> Mono<T>.asIo() = IO.async<T> { callback ->
+ subscribe({
+ callback(Right(it))
+ }, {
+ callback(Left(it))
+ })
+}
+
+fun <T> Flux<IO<T>>.evaluateIo(): Flux<T> =
+ flatMap { io ->
+ io.attempt().unsafeRunSync().fold(
+ { Flux.error<T>(it) },
+ { Flux.just<T>(it) }
+ )
+ }
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/ArgBasedConfiguration.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/ArgBasedConfiguration.kt
new file mode 100644
index 00000000..b14f1be5
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/ArgBasedConfiguration.kt
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.commandline
+
+import arrow.core.Either
+import arrow.core.Option
+import arrow.core.Try
+import arrow.core.flatMap
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.CommandLineParser
+import org.apache.commons.cli.Options
+import java.io.File
+import java.nio.file.Path
+import java.nio.file.Paths
+
+abstract class ArgBasedConfiguration<T>(private val parser: CommandLineParser) {
+ abstract val cmdLineOptionsList: List<CommandLineOption>
+
+ fun parse(args: Array<out String>): Either<WrongArgumentError, T> {
+ val parseResult = Try {
+ val commandLineOptions = cmdLineOptionsList.map { it.option }.fold(Options(), Options::addOption)
+ parser.parse(commandLineOptions, args)
+ }
+ return parseResult
+ .toEither()
+ .mapLeft { ex -> WrongArgumentError(ex, cmdLineOptionsList) }
+ .map(this::getConfiguration)
+ .flatMap {
+ it.toEither {
+ WrongArgumentError(
+ message = "Unexpected error when parsing command line arguments",
+ cmdLineOptionsList = cmdLineOptionsList)
+ }
+ }
+ }
+
+ protected abstract fun getConfiguration(cmdLine: CommandLine): Option<T>
+
+ protected fun stringPathToPath(path: String): Path = Paths.get(File(path).toURI())
+}
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt
new file mode 100644
index 00000000..9439bff5
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt
@@ -0,0 +1,142 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.commandline
+
+import org.apache.commons.cli.Option
+
+
+enum class CommandLineOption(val option: Option, val required: Boolean = false) {
+ HEALTH_CHECK_API_PORT(Option.builder("H")
+ .longOpt("health-check-api-port")
+ .hasArg()
+ .desc("Health check rest api listen port")
+ .build()
+ ),
+ LISTEN_PORT(Option.builder("p")
+ .longOpt("listen-port")
+ .hasArg()
+ .desc("Listen port")
+ .build(),
+ required = true
+ ),
+ CONSUL_CONFIG_URL(Option.builder("c")
+ .longOpt("config-url")
+ .hasArg()
+ .desc("URL of ves configuration on consul")
+ .build(),
+ required = true
+ ),
+ CONSUL_FIRST_REQUEST_DELAY(Option.builder("d")
+ .longOpt("first-request-delay")
+ .hasArg()
+ .desc("Delay of first request to consul in seconds")
+ .build()
+ ),
+ CONSUL_REQUEST_INTERVAL(Option.builder("I")
+ .longOpt("request-interval")
+ .hasArg()
+ .desc("Interval of consul configuration requests in seconds")
+ .build()
+ ),
+ VES_HV_PORT(Option.builder("v")
+ .longOpt("ves-port")
+ .hasArg()
+ .desc("VesHvCollector port")
+ .build(),
+ required = true
+ ),
+ VES_HV_HOST(Option.builder("h")
+ .longOpt("ves-host")
+ .hasArg()
+ .desc("VesHvCollector host")
+ .build(),
+ required = true
+ ),
+ KAFKA_SERVERS(Option.builder("s")
+ .longOpt("kafka-bootstrap-servers")
+ .hasArg()
+ .desc("Comma-separated Kafka bootstrap servers in <host>:<port> format")
+ .build(),
+ required = true
+ ),
+ KAFKA_TOPICS(Option.builder("f")
+ .longOpt("kafka-topics")
+ .hasArg()
+ .desc("Comma-separated Kafka topics")
+ .build(),
+ required = true
+ ),
+ SSL_DISABLE(Option.builder("l")
+ .longOpt("ssl-disable")
+ .desc("Disable SSL encryption")
+ .build()
+ ),
+ KEY_STORE_FILE(Option.builder("k")
+ .longOpt("key-store")
+ .hasArg()
+ .desc("Key store in PKCS12 format")
+ .build()
+ ),
+ KEY_STORE_PASSWORD(Option.builder("kp")
+ .longOpt("key-store-password")
+ .hasArg()
+ .desc("Key store password")
+ .build()
+ ),
+ TRUST_STORE_FILE(Option.builder("t")
+ .longOpt("trust-store")
+ .hasArg()
+ .desc("File with trusted certificate bundle in PKCS12 format")
+ .build()
+ ),
+ TRUST_STORE_PASSWORD(Option.builder("tp")
+ .longOpt("trust-store-password")
+ .hasArg()
+ .desc("Trust store password")
+ .build()
+ ),
+ IDLE_TIMEOUT_SEC(Option.builder("i")
+ .longOpt("idle-timeout-sec")
+ .hasArg()
+ .desc("""Idle timeout for remote hosts. After given time without any data exchange the
+ |connection might be closed.""".trimMargin())
+ .build()
+ ),
+ MAXIMUM_PAYLOAD_SIZE_BYTES(Option.builder("m")
+ .longOpt("max-payload-size")
+ .hasArg()
+ .desc("Maximum supported payload size in bytes")
+ .build()
+ ),
+ DUMMY_MODE(Option.builder("u")
+ .longOpt("dummy")
+ .desc("If present will start in dummy mode (dummy external services)")
+ .build()
+ );
+
+ fun environmentVariableName(prefix: String = DEFAULT_ENV_PREFIX): String =
+ option.longOpt.toUpperCase().replace('-', '_').let { mainPart ->
+ "${prefix}_${mainPart}"
+ }
+
+ companion object {
+ private const val DEFAULT_ENV_PREFIX = "VESHV"
+ }
+}
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentError.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentError.kt
new file mode 100644
index 00000000..9c2a20c1
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentError.kt
@@ -0,0 +1,70 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.commandline
+
+import arrow.core.Option
+import org.apache.commons.cli.HelpFormatter
+import org.apache.commons.cli.Options
+
+
+data class WrongArgumentError(
+ val message: String,
+ val cause: Throwable? = null,
+ val cmdLineOptionsList: List<CommandLineOption>) {
+
+ constructor(par: Throwable, cmdLineOptionsList: List<CommandLineOption>) :
+ this(par.message ?: "",
+ par,
+ cmdLineOptionsList)
+
+ fun printMessage() {
+ println(message)
+ }
+
+ fun printHelp(programName: String) {
+ val formatter = HelpFormatter()
+ val footer = "All parameters can be specified as environment variables using upper-snake-case full " +
+ "name with prefix `VESHV_`."
+
+ formatter.printHelp(
+ programName,
+ generateRequiredParametersNote(cmdLineOptionsList),
+ getOptions(),
+ footer)
+ }
+
+ private fun getOptions() = cmdLineOptionsList.map { it.option }.fold(Options(), Options::addOption)
+
+ companion object {
+ fun generateRequiredParametersNote(cmdLineOptionsList: List<CommandLineOption>): String {
+ val requiredParams = Option.fromNullable(cmdLineOptionsList.filter { it.required }
+ .takeUnless { it.isEmpty() })
+ return requiredParams.fold(
+ { "" },
+ {
+ it.map { commandLineOption -> commandLineOption.option.opt }
+ .joinToString(prefix = "Required parameters: ", separator = ", ")
+ }
+ )
+ }
+ }
+
+}
+
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/extensions.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/extensions.kt
new file mode 100644
index 00000000..a8414472
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/extensions.kt
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.commandline
+
+import arrow.core.Option
+import arrow.core.getOrElse
+import arrow.effects.IO
+import arrow.syntax.function.curried
+import org.apache.commons.cli.CommandLine
+import org.onap.dcae.collectors.veshv.utils.arrow.ExitFailure
+import org.onap.dcae.collectors.veshv.utils.arrow.fromNullablesChain
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since June 2018
+ */
+
+fun handleWrongArgumentError(programName: String, err: WrongArgumentError): IO<Unit> = IO {
+ err.printMessage()
+ err.printHelp(programName)
+}.flatMap { ExitFailure(2).io() }
+
+val handleWrongArgumentErrorCurried = ::handleWrongArgumentError.curried()
+
+fun CommandLine.longValue(cmdLineOpt: CommandLineOption, default: Long): Long =
+ longValue(cmdLineOpt).getOrElse { default }
+
+fun CommandLine.stringValue(cmdLineOpt: CommandLineOption, default: String): String =
+ optionValue(cmdLineOpt).getOrElse { default }
+
+fun CommandLine.intValue(cmdLineOpt: CommandLineOption, default: Int): Int =
+ intValue(cmdLineOpt).getOrElse { default }
+
+fun CommandLine.intValue(cmdLineOpt: CommandLineOption): Option<Int> =
+ optionValue(cmdLineOpt).map(String::toInt)
+
+fun CommandLine.longValue(cmdLineOpt: CommandLineOption): Option<Long> =
+ optionValue(cmdLineOpt).map(String::toLong)
+
+fun CommandLine.stringValue(cmdLineOpt: CommandLineOption): Option<String> =
+ optionValue(cmdLineOpt)
+
+fun CommandLine.hasOption(cmdLineOpt: CommandLineOption): Boolean =
+ this.hasOption(cmdLineOpt.option.opt) ||
+ System.getenv(cmdLineOpt.environmentVariableName()) != null
+
+private fun CommandLine.optionValue(cmdLineOpt: CommandLineOption) = Option.fromNullablesChain(
+ getOptionValue(cmdLineOpt.option.opt),
+ { System.getenv(cmdLineOpt.environmentVariableName()) })
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/http.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/http.kt
new file mode 100644
index 00000000..c5c46397
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/http.kt
@@ -0,0 +1,81 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.http
+
+import arrow.typeclasses.Show
+import java.util.*
+import javax.json.Json
+
+/**
+ * @author Jakub Dudycz <jakub.dudycz@nokia.com>
+ * @since August 2018
+ */
+object HttpConstants {
+ const val STATUS_OK = 200
+ const val STATUS_ACCEPTED = 202
+ const val STATUS_BAD_REQUEST = 400
+ const val STATUS_NOT_FOUND = 404
+ const val STATUS_INTERNAL_SERVER_ERROR = 500
+ const val STATUS_SERVICE_UNAVAILABLE = 503
+
+ const val CONTENT_TYPE_JSON = "application/json"
+ const val CONTENT_TYPE_TEXT = "text/plain"
+}
+
+enum class HttpStatus(val number: Int) {
+ OK(HttpConstants.STATUS_OK),
+ ACCEPTED(HttpConstants.STATUS_ACCEPTED),
+ BAD_REQUEST(HttpConstants.STATUS_BAD_REQUEST),
+ NOT_FOUND(HttpConstants.STATUS_NOT_FOUND),
+ INTERNAL_SERVER_ERROR(HttpConstants.STATUS_INTERNAL_SERVER_ERROR),
+ SERVICE_UNAVAILABLE(HttpConstants.STATUS_SERVICE_UNAVAILABLE)
+}
+
+
+enum class ContentType(val value: String) {
+ JSON(HttpConstants.CONTENT_TYPE_JSON),
+ TEXT(HttpConstants.CONTENT_TYPE_TEXT)
+}
+
+data class Response(val status: HttpStatus, val content: Content<Any>)
+data class Content<T>(val type: ContentType, val value: T, val serializer: Show<T> = Show.any())
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since September 2018
+ */
+object Responses {
+
+ fun acceptedResponse(id: UUID): Response {
+ return Response(
+ HttpStatus.ACCEPTED,
+ Content(ContentType.TEXT, id)
+ )
+ }
+
+ fun statusResponse(name: String, message: String, httpStatus: HttpStatus = HttpStatus.OK): Response {
+ return Response(httpStatus,
+ Content(ContentType.JSON,
+ Json.createObjectBuilder()
+ .add("status", name)
+ .add("message", message)
+ .build()))
+ }
+}
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/ratpack.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/ratpack.kt
new file mode 100644
index 00000000..0282d0c7
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/http/ratpack.kt
@@ -0,0 +1,77 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.http
+
+import arrow.core.Either
+import arrow.effects.IO
+import org.onap.dcae.collectors.veshv.utils.logging.Logger
+import javax.json.Json
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since August 2018
+ */
+
+private val logger = Logger("org.onap.dcae.collectors.veshv.utils.arrow.ratpack")
+
+fun ratpack.http.Response.sendOrError(action: IO<Unit>) {
+ sendAndHandleErrors(action.map {
+ Response(
+ HttpStatus.OK,
+ Content(
+ ContentType.JSON,
+ Json.createObjectBuilder().add("response", "Request accepted").build()))
+ })
+}
+
+fun <A> ratpack.http.Response.sendEitherErrorOrResponse(response: Either<A, Response>) {
+ when(response) {
+ is Either.Left -> send(errorResponse(response.a.toString()))
+ is Either.Right -> sendAndHandleErrors(IO.just(response.b))
+ }
+}
+
+fun ratpack.http.Response.sendAndHandleErrors(response: IO<Response>) {
+ response.attempt().unsafeRunSync().fold(
+ { err ->
+ logger.warn("Error occurred. Sending .", err)
+ val message = err.message
+ send(errorResponse(message))
+ },
+ ::send
+ )
+}
+
+private fun errorResponse(message: String?): Response {
+ return Response(
+ HttpStatus.INTERNAL_SERVER_ERROR,
+ Content(
+ ContentType.JSON,
+ Json.createObjectBuilder().add("error", message).build()))
+}
+
+fun ratpack.http.Response.send(response: Response) {
+ val respWithStatus = status(response.status.number)
+ response.content.apply {
+ respWithStatus.send(
+ type.value,
+ serializer.run { value.show() })
+ }
+}
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/Logger.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/Logger.kt
new file mode 100644
index 00000000..033dd5e5
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/Logger.kt
@@ -0,0 +1,137 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.logging
+
+import kotlin.reflect.KClass
+import org.slf4j.LoggerFactory
+
+@Suppress("TooManyFunctions", "SuboptimalLoggerUsage")
+class Logger(val logger: org.slf4j.Logger) {
+ constructor(clazz: KClass<out Any>) : this(LoggerFactory.getLogger(clazz.java))
+ constructor(name: String) : this(LoggerFactory.getLogger(name))
+
+ //
+ // TRACE
+ //
+
+ val traceEnabled: Boolean
+ get() = logger.isTraceEnabled
+
+ fun trace(messageProvider: () -> String) {
+ if (logger.isTraceEnabled) {
+ logger.trace(messageProvider())
+ }
+ }
+
+ //
+ // DEBUG
+ //
+
+ fun debug(message: String) {
+ logger.debug(message)
+ }
+
+ fun debug(message: String, t: Throwable) {
+ logger.debug(message, t)
+ }
+
+ fun debug(messageProvider: () -> String) {
+ if (logger.isDebugEnabled) {
+ logger.debug(messageProvider())
+ }
+ }
+
+ fun debug(t: Throwable, messageProvider: () -> String) {
+ if (logger.isDebugEnabled) {
+ logger.debug(messageProvider(), t)
+ }
+ }
+
+ //
+ // INFO
+ //
+ fun info(message: String) {
+ logger.info(message)
+ }
+
+ fun info(messageProvider: () -> String) {
+ if (logger.isInfoEnabled) {
+ logger.info(messageProvider())
+ }
+ }
+
+ fun info(message: String, t: Throwable) {
+ logger.info(message, t)
+ }
+
+ fun info(t: Throwable, messageProvider: () -> String) {
+ if (logger.isInfoEnabled) {
+ logger.info(messageProvider(), t)
+ }
+ }
+
+ //
+ // WARN
+ //
+
+ fun warn(message: String) {
+ logger.warn(message)
+ }
+
+ fun warn(message: String, t: Throwable) {
+ logger.warn(message, t)
+ }
+
+ fun warn(messageProvider: () -> String) {
+ if (logger.isWarnEnabled) {
+ logger.warn(messageProvider())
+ }
+ }
+
+ fun warn(t: Throwable, messageProvider: () -> String) {
+ if (logger.isWarnEnabled) {
+ logger.warn(messageProvider(), t)
+ }
+ }
+
+ //
+ // ERROR
+ //
+
+ fun error(message: String) {
+ logger.error(message)
+ }
+
+ fun error(message: String, t: Throwable) {
+ logger.error(message, t)
+ }
+
+ fun error(messageProvider: () -> String) {
+ if (logger.isErrorEnabled) {
+ logger.error(messageProvider())
+ }
+ }
+
+ fun error(t: Throwable, messageProvider: () -> String) {
+ if (logger.isErrorEnabled) {
+ logger.error(messageProvider(), t)
+ }
+ }
+}
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/reactive_logging.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/reactive_logging.kt
new file mode 100644
index 00000000..714702d3
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/logging/reactive_logging.kt
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.logging
+
+import reactor.core.publisher.Flux
+
+fun <T> Logger.handleReactiveStreamError(ex: Throwable, returnFlux: Flux<T> = Flux.empty()): Flux<T> {
+ logger.warn("Error while handling message stream: ${ex::class.qualifiedName} (${ex.message})")
+ logger.debug("Detailed stack trace", ex)
+ return returnFlux
+}
diff --git a/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/server_handle.kt b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/server_handle.kt
new file mode 100644
index 00000000..bdb63b68
--- /dev/null
+++ b/sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/server_handle.kt
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils
+
+import arrow.effects.IO
+import reactor.netty.DisposableServer
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since August 2018
+ */
+abstract class ServerHandle(val host: String, val port: Int) {
+ abstract fun shutdown(): IO<Unit>
+ abstract fun await(): IO<Unit>
+}
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since August 2018
+ */
+class NettyServerHandle(private val ctx: DisposableServer) : ServerHandle(ctx.host(), ctx.port()) {
+ override fun shutdown() = IO {
+ ctx.disposeNow()
+ }
+
+ override fun await() = IO<Unit> {
+ ctx.channel().closeFuture().sync()
+ }
+}
diff --git a/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/CoreKtTest.kt b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/CoreKtTest.kt
new file mode 100644
index 00000000..2eb11b27
--- /dev/null
+++ b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/CoreKtTest.kt
@@ -0,0 +1,141 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.arrow
+
+import arrow.core.None
+import arrow.core.Option
+import arrow.core.Some
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.given
+import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.on
+import java.util.concurrent.atomic.AtomicReference
+
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk></piotr.jaszczyk>@nokia.com>
+ * @since August 2018
+ */
+internal class CoreKtTest : Spek({
+ describe("AtomicReference.getOption") {
+ given("empty atomic reference") {
+ val atomicReference = AtomicReference<String>()
+
+ on("getOption") {
+ val result = atomicReference.getOption()
+
+ it("should be None") {
+ assertThat(result).isEqualTo(None)
+ }
+ }
+ }
+ given("non-empty atomic reference") {
+ val initialValue = "reksio"
+ val atomicReference = AtomicReference(initialValue)
+
+ on("getOption") {
+ val result = atomicReference.getOption()
+
+ it("should be Some($initialValue)") {
+ assertThat(result).isEqualTo(Some(initialValue))
+ }
+ }
+ }
+ }
+
+ describe("Option.fromNullablesChain") {
+ given("one non-null element") {
+ val just = "some text"
+ on("calling factory") {
+ val result = Option.fromNullablesChain(just)
+
+ it("should return Some($just)") {
+ assertThat(result).isEqualTo(Some(just))
+ }
+ }
+ }
+
+ given("one null element") {
+ val just: String? = null
+ on("calling factory") {
+ val result = Option.fromNullablesChain(just)
+
+ it("should return None") {
+ assertThat(result).isEqualTo(None)
+ }
+ }
+ }
+
+ given("first non-null element") {
+ val first = "some text"
+ val second: String? = null
+ var secondAskedForValue = false
+ on("calling factory") {
+ val result = Option.fromNullablesChain(first, { secondAskedForValue = true; second })
+
+ it("should return Some($first)") {
+ assertThat(result).isEqualTo(Some(first))
+ }
+
+ it("should have not called second provider (should be lazy)") {
+ assertThat(secondAskedForValue).isFalse()
+ }
+ }
+ }
+
+ given("two non-null elements") {
+ val first = "some text"
+ val second = "another text"
+ on("calling factory") {
+ val result = Option.fromNullablesChain(first, { second })
+
+ it("should return Some($first)") {
+ assertThat(result).isEqualTo(Some(first))
+ }
+ }
+ }
+
+ given("two null elements") {
+ val first: String? = null
+ val second: String? = null
+ on("calling factory") {
+ val result = Option.fromNullablesChain(first, { second })
+
+ it("should return None") {
+ assertThat(result).isEqualTo(None)
+ }
+ }
+ }
+
+ given("second non-null element") {
+ val first: String? = null
+ val second = "another text"
+ on("calling factory") {
+ val result = Option.fromNullablesChain(first, { second })
+
+ it("should return Some($second)") {
+ assertThat(result).isEqualTo(Some(second))
+ }
+ }
+ }
+ }
+})
diff --git a/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOptionTest.kt b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOptionTest.kt
new file mode 100644
index 00000000..f36df043
--- /dev/null
+++ b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOptionTest.kt
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.commandline
+
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.given
+import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.on
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since September 2018
+ */
+class CommandLineOptionTest : Spek({
+ describe("command line options enum") {
+ describe("environment variables") {
+ given("sample option and prefix") {
+ val opt = CommandLineOption.KAFKA_SERVERS
+ val prefix = "CONFIG"
+
+ on("calling environmentVariableName") {
+ val result = opt.environmentVariableName(prefix)
+
+ it("should return prefixed upper snake cased long option name") {
+ assertThat(result).isEqualTo("CONFIG_KAFKA_BOOTSTRAP_SERVERS")
+ }
+ }
+ }
+
+ given("sample option without prefix") {
+ val opt = CommandLineOption.DUMMY_MODE
+
+ on("calling environmentVariableName") {
+ val result = opt.environmentVariableName()
+
+ it("should return prefixed upper snake cased long option name") {
+ assertThat(result).isEqualTo("VESHV_DUMMY")
+ }
+ }
+ }
+ }
+ }
+})
diff --git a/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentErrorTest.kt b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentErrorTest.kt
new file mode 100644
index 00000000..63d9eb82
--- /dev/null
+++ b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/WrongArgumentErrorTest.kt
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.commandline
+
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.given
+import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.on
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.HEALTH_CHECK_API_PORT
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.LISTEN_PORT
+
+class WrongArgumentErrorTest : Spek ({
+
+ describe("help message logic test") {
+
+ given("at least one required option") {
+ val filledOptionList = listOf(
+ HEALTH_CHECK_API_PORT,
+ LISTEN_PORT)
+ on("help message preparation") {
+ val requiredParameters = WrongArgumentError.generateRequiredParametersNote(filledOptionList)
+
+ it("should print out required fields") {
+ assertThat(requiredParameters).isEqualTo("Required parameters: p")
+ }
+ }
+ }
+
+ given("no required option") {
+ val filledOptionList = listOf(HEALTH_CHECK_API_PORT)
+
+ on("help message preparation") {
+ val requiredParameters = WrongArgumentError.generateRequiredParametersNote(filledOptionList)
+
+ it("should not print required fields") {
+ assertThat(requiredParameters).isEqualTo("")
+ }
+ }
+ }
+ }
+
+}) \ No newline at end of file
diff --git a/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/http/ResponsesTest.kt b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/http/ResponsesTest.kt
new file mode 100644
index 00000000..f9f716a1
--- /dev/null
+++ b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/http/ResponsesTest.kt
@@ -0,0 +1,101 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.http
+
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.given
+import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.on
+import java.util.*
+import javax.json.JsonObject
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since September 2018
+ */
+internal class ResponsesTest : Spek({
+ describe("response factory") {
+ describe("accepted response") {
+ given("uuid") {
+ val uuid = UUID.randomUUID()
+
+ on("calling acceptedResponse") {
+ val result = Responses.acceptedResponse(uuid)
+
+ it ("should have ACCEPTED status") {
+ assertThat(result.status).isEqualTo(HttpStatus.ACCEPTED)
+ }
+
+ it ("should have text body") {
+ assertThat(result.content.type).isEqualTo(ContentType.TEXT)
+ }
+
+ it ("should contain UUID text in the body") {
+ val serialized = result.content.serializer.run { result.content.value.show() }
+ assertThat(serialized).isEqualTo(uuid.toString())
+ }
+ }
+ }
+ }
+ describe("status response") {
+ given("all params are specified") {
+ val status = "ok"
+ val message = "good job"
+ val httpStatus = HttpStatus.OK
+
+ on("calling statusResponse") {
+ val result = Responses.statusResponse(status, message, httpStatus)
+ val json = result.content.value as JsonObject
+
+ it ("should have OK status") {
+ assertThat(result.status).isEqualTo(HttpStatus.OK)
+ }
+
+ it ("should have json body") {
+ assertThat(result.content.type).isEqualTo(ContentType.JSON)
+ }
+
+ it ("should contain status as string") {
+ assertThat(json.getString("status")).isEqualTo(status)
+ }
+
+ it ("should contain message") {
+ assertThat(json.getString("message")).isEqualTo(message)
+ }
+ }
+ }
+
+ given("default params are omitted") {
+ val status = "ok"
+ val message = "good job"
+
+ on("calling statusResponse") {
+ val result = Responses.statusResponse(status, message)
+
+ it ("should have OK status") {
+ assertThat(result.status).isEqualTo(HttpStatus.OK)
+ }
+ }
+ }
+ }
+ }
+})
diff --git a/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/logging/LoggerTest.kt b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/logging/LoggerTest.kt
new file mode 100644
index 00000000..c27fb8c8
--- /dev/null
+++ b/sources/hv-collector-utils/src/test/kotlin/org/onap/dcae/collectors/veshv/utils/logging/LoggerTest.kt
@@ -0,0 +1,230 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.utils.logging
+
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.verify
+import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions
+import com.nhaarman.mockitokotlin2.whenever
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.describe
+import org.jetbrains.spek.api.dsl.it
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since May 2018
+ */
+object LoggerTest : Spek({
+
+ lateinit var slf4jLogger: org.slf4j.Logger
+ lateinit var cut: Logger
+
+ beforeEachTest {
+ slf4jLogger = mock()
+ cut = Logger(slf4jLogger)
+ }
+
+ afterEachTest {
+ verifyNoMoreInteractions(slf4jLogger)
+ }
+
+ describe("Thin Kotlin logging facade for Slf4j") {
+ val message = "sample message"
+ val exception = Exception("fail")
+
+ describe("debug levels") {
+ it("should log message") {
+ cut.debug(message)
+ verify(slf4jLogger).debug(message)
+ }
+
+ it("should log message with exception") {
+ cut.debug(message, exception)
+ verify(slf4jLogger).debug(message, exception)
+ }
+
+ describe("lazy logging message") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isDebugEnabled).thenReturn(true)
+ cut.debug { message }
+ verify(slf4jLogger).isDebugEnabled
+ verify(slf4jLogger).debug(message)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isDebugEnabled).thenReturn(false)
+ cut.debug { message }
+ verify(slf4jLogger).isDebugEnabled
+ }
+ }
+
+ describe("lazy logging message with exception") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isDebugEnabled).thenReturn(true)
+ cut.debug(exception) { message }
+ verify(slf4jLogger).isDebugEnabled
+ verify(slf4jLogger).debug(message, exception)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isDebugEnabled).thenReturn(false)
+ cut.debug(exception) { message }
+ verify(slf4jLogger).isDebugEnabled
+ }
+ }
+ }
+
+ describe("info levels") {
+ it("should log message") {
+ cut.info(message)
+ verify(slf4jLogger).info(message)
+ }
+
+ it("should log message with exception") {
+ cut.info(message, exception)
+ verify(slf4jLogger).info(message, exception)
+ }
+
+ describe("lazy logging message") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isInfoEnabled).thenReturn(true)
+ cut.info { message }
+ verify(slf4jLogger).isInfoEnabled
+ verify(slf4jLogger).info(message)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isInfoEnabled).thenReturn(false)
+ cut.info { message }
+ verify(slf4jLogger).isInfoEnabled
+ }
+ }
+
+ describe("lazy logging message with exception") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isInfoEnabled).thenReturn(true)
+ cut.info(exception) { message }
+ verify(slf4jLogger).isInfoEnabled
+ verify(slf4jLogger).info(message, exception)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isInfoEnabled).thenReturn(false)
+ cut.info(exception) { message }
+ verify(slf4jLogger).isInfoEnabled
+ }
+ }
+ }
+
+ describe("warning levels") {
+ it("should log message") {
+ cut.warn(message)
+ verify(slf4jLogger).warn(message)
+ }
+
+ it("should log message with exception") {
+ cut.warn(message, exception)
+ verify(slf4jLogger).warn(message, exception)
+ }
+
+ describe("lazy logging message") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isWarnEnabled).thenReturn(true)
+ cut.warn { message }
+ verify(slf4jLogger).isWarnEnabled
+ verify(slf4jLogger).warn(message)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isWarnEnabled).thenReturn(false)
+ cut.warn { message }
+ verify(slf4jLogger).isWarnEnabled
+ }
+ }
+
+ describe("lazy logging message with exception") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isWarnEnabled).thenReturn(true)
+ cut.warn(exception) { message }
+ verify(slf4jLogger).isWarnEnabled
+ verify(slf4jLogger).warn(message, exception)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isWarnEnabled).thenReturn(false)
+ cut.warn(exception) { message }
+ verify(slf4jLogger).isWarnEnabled
+ }
+ }
+ }
+
+ describe("error levels") {
+ it("should log message") {
+ cut.error(message)
+ verify(slf4jLogger).error(message)
+ }
+
+ it("should log message with exception") {
+ cut.error(message, exception)
+ verify(slf4jLogger).error(message, exception)
+ }
+
+ describe("lazy logging message") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isErrorEnabled).thenReturn(true)
+ cut.error { message }
+ verify(slf4jLogger).isErrorEnabled
+ verify(slf4jLogger).error(message)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isErrorEnabled).thenReturn(false)
+ cut.error { message }
+ verify(slf4jLogger).isErrorEnabled
+ }
+ }
+
+ describe("lazy logging message with exception") {
+
+ it("should log when debug is ON") {
+ whenever(slf4jLogger.isErrorEnabled).thenReturn(true)
+ cut.error(exception) { message }
+ verify(slf4jLogger).isErrorEnabled
+ verify(slf4jLogger).error(message, exception)
+ }
+
+ it("should not log when debug is OFF") {
+ whenever(slf4jLogger.isErrorEnabled).thenReturn(false)
+ cut.error(exception) { message }
+ verify(slf4jLogger).isErrorEnabled
+ }
+ }
+ }
+
+
+ }
+})