From 291be473ce28648c1dab4914e4a31e2b45042cda Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Sat, 25 Sep 2021 18:18:57 +0200 Subject: [PATCH 01/35] Created LogViewerWidget --- .../cognifide/cogboard/CogboardConstants.kt | 2 ++ .../cogboard/widget/type/LogViewerWidget.kt | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt index b781386a..1f9433f2 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt @@ -39,6 +39,8 @@ class CogboardConstants { const val SCHEDULE_PERIOD_DEFAULT = 120L // 120 seconds const val SCHEDULE_DELAY_DEFAULT = 10L // 10 seconds const val URL = "url" + + const val LOG_LINES = "logLines" const val REQUEST_ID = "requestId" const val PUBLIC_URL = "publicUrl" const val USER = "user" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt new file mode 100644 index 00000000..bc8e2bb4 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -0,0 +1,31 @@ +package com.cognifide.cogboard.widget.type + +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.config.service.BoardsConfigService +import com.cognifide.cogboard.widget.AsyncWidget +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject + +class LogViewerWidget( + vertx: Vertx, + config: JsonObject, + serv: BoardsConfigService +): AsyncWidget(vertx, config, serv) { + private val lines = config.getInteger(Props.LOG_LINES) + + override fun updateState() { + if (url.isNotBlank()) { + httpGet("$url?lines=$lines") + } else { + sendConfigurationError("Endpoint URL is blank") + } + } + + override fun handleResponse(responseBody: JsonObject) { + if (checkAuthorized(responseBody)) { + val logs = responseBody.getString(Props.LOG_LINES) + + send(logs) + } + } +} \ No newline at end of file From af06dd9bba205af7b8d340fcc53221b77a931b65 Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Sat, 25 Sep 2021 18:57:32 +0200 Subject: [PATCH 02/35] Added LogViewer to WidgetIndex --- .../cognifide/cogboard/widget/WidgetIndex.kt | 18 +++--------------- .../cogboard/widget/type/LogViewerWidget.kt | 10 +++++----- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt index 70e8e799..519e9d53 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt @@ -3,20 +3,7 @@ package com.cognifide.cogboard.widget import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.storage.VolumeStorageFactory.appConfig -import com.cognifide.cogboard.widget.type.AemBundleInfoWidget -import com.cognifide.cogboard.widget.type.AemHealthcheckWidget -import com.cognifide.cogboard.widget.type.BambooDeploymentWidget -import com.cognifide.cogboard.widget.type.BambooPlanWidget -import com.cognifide.cogboard.widget.type.CheckboxWidget -import com.cognifide.cogboard.widget.type.IframeEmbedWidget -import com.cognifide.cogboard.widget.type.JenkinsJobWidget -import com.cognifide.cogboard.widget.type.JiraBucketsWidget -import com.cognifide.cogboard.widget.type.LinkListWidget -import com.cognifide.cogboard.widget.type.WhiteSpaceWidget -import com.cognifide.cogboard.widget.type.ServiceCheckWidget -import com.cognifide.cogboard.widget.type.TextWidget -import com.cognifide.cogboard.widget.type.ToDoListWidget -import com.cognifide.cogboard.widget.type.WorldClockWidget +import com.cognifide.cogboard.widget.type.* import com.cognifide.cogboard.widget.type.randompicker.RandomPickerWidget import com.cognifide.cogboard.widget.type.sonarqube.SonarQubeWidget import com.cognifide.cogboard.widget.type.zabbix.ZabbixWidget @@ -48,7 +35,8 @@ class WidgetIndex { "Jira Buckets" to JiraBucketsWidget::class.java, "Service Check" to ServiceCheckWidget::class.java, "SonarQube" to SonarQubeWidget::class.java, - "White Space" to WhiteSpaceWidget::class.java + "White Space" to WhiteSpaceWidget::class.java, + "Log Viewer" to LogViewerWidget::class.java ) fun availableWidgets(): JsonArray { diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index bc8e2bb4..20745f32 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -7,10 +7,10 @@ import io.vertx.core.Vertx import io.vertx.core.json.JsonObject class LogViewerWidget( - vertx: Vertx, - config: JsonObject, - serv: BoardsConfigService -): AsyncWidget(vertx, config, serv) { + vertx: Vertx, + config: JsonObject, + serv: BoardsConfigService +) : AsyncWidget(vertx, config, serv) { private val lines = config.getInteger(Props.LOG_LINES) override fun updateState() { @@ -28,4 +28,4 @@ class LogViewerWidget( send(logs) } } -} \ No newline at end of file +} From cd3a269f689d22350682488577c5429870604dc0 Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Sat, 25 Sep 2021 18:58:03 +0200 Subject: [PATCH 03/35] Added WireMock for LogViewer --- api-mocks/__files/logViewer/logs.json | 3 +++ api-mocks/mappings/endpoints-mapping.json | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 api-mocks/__files/logViewer/logs.json diff --git a/api-mocks/__files/logViewer/logs.json b/api-mocks/__files/logViewer/logs.json new file mode 100644 index 00000000..b4211a0e --- /dev/null +++ b/api-mocks/__files/logViewer/logs.json @@ -0,0 +1,3 @@ +{ + "logLines": "02:49:12 127.0.0.1 GET / 200\n02:49:35 127.0.0.1 GET /index.html 200\n03:01:06 127.0.0.1 GET /images/sponsered.gif 304\n03:52:36 127.0.0.1 GET /search.php 200\n04:17:03 127.0.0.1 GET /admin/style.css 200\n05:04:54 127.0.0.1 GET /favicon.ico 404\n05:38:07 127.0.0.1 GET /js/ads.js 200\n" +} \ No newline at end of file diff --git a/api-mocks/mappings/endpoints-mapping.json b/api-mocks/mappings/endpoints-mapping.json index 5a3ade40..8dc85fa6 100644 --- a/api-mocks/mappings/endpoints-mapping.json +++ b/api-mocks/mappings/endpoints-mapping.json @@ -1,5 +1,23 @@ { "mappings": [ + { + "request": { + "method": "GET", + "url": "/logviewer", + "queryParameters": { + "lines": { + "matches": "^[0-9]+$" + } + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "bodyFileName": "logViewer/logs.json" + } + }, { "request": { "method": "GET", From ba65c41a00d5b13bc23d2bdb8fb215361db8de92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Sat, 16 Oct 2021 17:53:44 +0200 Subject: [PATCH 04/35] Remove ALL log level, use INFO as default --- .../types/LogViewerWidget/Toolbar/FilterPicker/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js index 1e6551d1..c999852c 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js @@ -17,7 +17,7 @@ const FilterPicker = () => { }; const [filters, setFilters] = useState([]); - const [logLevel, setLogLevel] = useState(''); + const [logLevel, setLogLevel] = useState('info'); return ( @@ -48,7 +48,6 @@ const FilterPicker = () => { )} > - ALL DEBUG INFO WARN @@ -65,7 +64,6 @@ const FilterPicker = () => { value={logLevel} onChange={e => setLogLevel(e.target.value)} > - ALL DEBUG INFO WARN From 954f9afd8a46226af449c5ef4d02d014023f21e9 Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Sun, 17 Oct 2021 19:16:38 +0200 Subject: [PATCH 05/35] Added placeholder method for processing logs before sending to front-end --- .../com/cognifide/cogboard/widget/type/LogViewerWidget.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 20745f32..7ee6078d 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -25,7 +25,12 @@ class LogViewerWidget( if (checkAuthorized(responseBody)) { val logs = responseBody.getString(Props.LOG_LINES) - send(logs) + send(prepareLogs(logs)) } } + + private fun prepareLogs(logs: String): String { + // TODO + return logs + } } From 783fb34bf4dace84a0d7ee016aed9d5041b1a444 Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Fri, 22 Oct 2021 13:23:48 +0200 Subject: [PATCH 06/35] Changed to using strategies [#381] --- .../cognifide/cogboard/CogboardConstants.kt | 9 +++++ .../connectionStrategy/ConnectionStrategy.kt | 5 +++ .../ConnectionStrategyFactory.kt | 16 +++++++++ .../HTTPConnectionStrategy.kt | 7 ++++ .../SSHConnectionStrategy.kt | 7 ++++ .../cogboard/widget/type/LogViewerWidget.kt | 35 ++++++++++++++++--- 6 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt index 1f9433f2..c67aa805 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt @@ -40,6 +40,8 @@ class CogboardConstants { const val SCHEDULE_DELAY_DEFAULT = 10L // 10 seconds const val URL = "url" + const val LOG_SOURCE = "logSource" + const val LOG_SOURCE_TYPE = "logSourceType" const val LOG_LINES = "logLines" const val REQUEST_ID = "requestId" const val PUBLIC_URL = "publicUrl" @@ -80,6 +82,13 @@ class CogboardConstants { } } + class ConnectionType { + companion object { + const val SSH = "SSH" + const val HTTP = "HTTP" + } + } + class RequestMethod { companion object { const val GET = "get" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt new file mode 100644 index 00000000..84080055 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -0,0 +1,5 @@ +package com.cognifide.cogboard.widget.connectionStrategy + +abstract class ConnectionStrategy { + abstract fun connectAndGetResources(address: String, vararg arguments: String) +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt new file mode 100644 index 00000000..b7f6eb81 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -0,0 +1,16 @@ +package com.cognifide.cogboard.widget.connectionStrategy + +import com.cognifide.cogboard.CogboardConstants.ConnectionType +import java.lang.Exception + +class ConnectionStrategyFactory { + class ConnectionTypeException : Exception("Unknown strategy type") + + fun build(type: String): ConnectionStrategy { + return when (type) { + ConnectionType.HTTP -> HTTPConnectionStrategy() + ConnectionType.SSH -> SSHConnectionStrategy() + else -> throw ConnectionTypeException() + } + } +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt new file mode 100644 index 00000000..093a5569 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt @@ -0,0 +1,7 @@ +package com.cognifide.cogboard.widget.connectionStrategy + +class HTTPConnectionStrategy : ConnectionStrategy() { + override fun connectAndGetResources(address: String, vararg arguments: String) { + TODO("Not yet implemented") + } +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt new file mode 100644 index 00000000..cf063a0d --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -0,0 +1,7 @@ +package com.cognifide.cogboard.widget.connectionStrategy + +class SSHConnectionStrategy : ConnectionStrategy() { + override fun connectAndGetResources(address: String, vararg arguments: String) { + TODO("Not yet implemented") + } +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 7ee6078d..0c629a63 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -2,26 +2,42 @@ package com.cognifide.cogboard.widget.type import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService -import com.cognifide.cogboard.widget.AsyncWidget +import com.cognifide.cogboard.widget.BaseWidget +import com.cognifide.cogboard.widget.Widget +import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy import io.vertx.core.Vertx +import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject class LogViewerWidget( vertx: Vertx, config: JsonObject, serv: BoardsConfigService -) : AsyncWidget(vertx, config, serv) { +) : BaseWidget(vertx, config, serv) { + private val address = config.getString(Props.LOG_SOURCE) private val lines = config.getInteger(Props.LOG_LINES) + private lateinit var consumer: MessageConsumer + private var connectionStrategy: ConnectionStrategy = determineConnectionStrategy(config) + + override fun start(): Widget { + consumer = vertx.eventBus() + .consumer(eventBusAddress) + .handler { + handleResponse(it.body()) + } + return super.start() + } + override fun updateState() { - if (url.isNotBlank()) { - httpGet("$url?lines=$lines") + if (address.isNotBlank()) { + connectionStrategy.connectAndGetResources(address = address, lines.toString()) } else { sendConfigurationError("Endpoint URL is blank") } } - override fun handleResponse(responseBody: JsonObject) { + private fun handleResponse(responseBody: JsonObject) { if (checkAuthorized(responseBody)) { val logs = responseBody.getString(Props.LOG_LINES) @@ -33,4 +49,13 @@ class LogViewerWidget( // TODO return logs } + + private fun determineConnectionStrategy(config: JsonObject): ConnectionStrategy { + // Placeholder + return object : ConnectionStrategy() { + override fun connectAndGetResources(address: String, vararg arguments: String) { + TODO("Not yet implemented") + } + } + } } From 75fff1fa2c58c80b7be662aeb2b673bac02b8987 Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Fri, 22 Oct 2021 14:21:34 +0200 Subject: [PATCH 07/35] Strategy adjustments [#381] --- .../connectionStrategy/ConnectionStrategy.kt | 8 ++++++-- .../ConnectionStrategyFactory.kt | 18 ++++++++++++++++-- .../HTTPConnectionStrategy.kt | 7 +++++-- .../SSHConnectionStrategy.kt | 7 +++++-- .../cogboard/widget/type/LogViewerWidget.kt | 14 +++++++------- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt index 84080055..df672652 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -1,5 +1,9 @@ package com.cognifide.cogboard.widget.connectionStrategy -abstract class ConnectionStrategy { - abstract fun connectAndGetResources(address: String, vararg arguments: String) +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject + +abstract class ConnectionStrategy(protected val vertx: Vertx) { + + abstract fun connectAndGetResources(address: String, arguments: JsonObject) } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index b7f6eb81..9fd11187 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -1,15 +1,29 @@ package com.cognifide.cogboard.widget.connectionStrategy import com.cognifide.cogboard.CogboardConstants.ConnectionType +import io.vertx.core.Vertx import java.lang.Exception class ConnectionStrategyFactory { class ConnectionTypeException : Exception("Unknown strategy type") + class MissingVertxException : Exception("Vertx hasn't been added to factory instance") + + private lateinit var vertx: Vertx + + fun addVertxInstance(vertx: Vertx): ConnectionStrategyFactory { + this.vertx = vertx + + return this + } fun build(type: String): ConnectionStrategy { + if (!::vertx.isInitialized) { + throw MissingVertxException() + } + return when (type) { - ConnectionType.HTTP -> HTTPConnectionStrategy() - ConnectionType.SSH -> SSHConnectionStrategy() + ConnectionType.HTTP -> HTTPConnectionStrategy(vertx) + ConnectionType.SSH -> SSHConnectionStrategy(vertx) else -> throw ConnectionTypeException() } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt index 093a5569..3d942305 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt @@ -1,7 +1,10 @@ package com.cognifide.cogboard.widget.connectionStrategy -class HTTPConnectionStrategy : ConnectionStrategy() { - override fun connectAndGetResources(address: String, vararg arguments: String) { +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject + +class HTTPConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { TODO("Not yet implemented") } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index cf063a0d..2d250c35 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -1,7 +1,10 @@ package com.cognifide.cogboard.widget.connectionStrategy -class SSHConnectionStrategy : ConnectionStrategy() { - override fun connectAndGetResources(address: String, vararg arguments: String) { +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject + +class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { TODO("Not yet implemented") } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 0c629a63..67117b02 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -5,6 +5,7 @@ import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.widget.BaseWidget import com.cognifide.cogboard.widget.Widget import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy +import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject @@ -31,7 +32,7 @@ class LogViewerWidget( override fun updateState() { if (address.isNotBlank()) { - connectionStrategy.connectAndGetResources(address = address, lines.toString()) + connectionStrategy.connectAndGetResources(address, config) } else { sendConfigurationError("Endpoint URL is blank") } @@ -51,11 +52,10 @@ class LogViewerWidget( } private fun determineConnectionStrategy(config: JsonObject): ConnectionStrategy { - // Placeholder - return object : ConnectionStrategy() { - override fun connectAndGetResources(address: String, vararg arguments: String) { - TODO("Not yet implemented") - } - } + val type = config.getString(Props.LOG_SOURCE_TYPE) + + return ConnectionStrategyFactory() + .addVertxInstance(vertx) + .build(type) } } From de0aea0be2e07f8bae0cbe76cc71317f2fdece5d Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Fri, 22 Oct 2021 23:03:23 +0200 Subject: [PATCH 08/35] Added tests and Strategies implementations [#381] --- .../cognifide/cogboard/CogboardConstants.kt | 1 + .../com/cognifide/cogboard/ssh/SSHClient.kt | 7 +- .../connectionStrategy/ConnectionStrategy.kt | 10 ++ .../ConnectionStrategyFactory.kt | 27 ++-- .../HTTPConnectionStrategy.kt | 10 -- .../SSHConnectionStrategy.kt | 21 ++- .../http/HttpConnectionStrategy.kt | 19 +++ .../http/HttpConnectionStrategyImpl.kt | 62 +++++++++ .../cogboard/widget/type/LogViewerWidget.kt | 54 ++++++-- .../cognifide/cogboard/ssh/SSHClientTest.kt | 125 ++++++++++++++++++ .../cogboard/widget/type/LogViewerTest.kt | 51 +++++++ .../com/cognifide/cogboard/ssh/id_rsa | 39 ++++++ 12 files changed, 388 insertions(+), 38 deletions(-) delete mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt create mode 100644 cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt create mode 100644 cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt create mode 100644 cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt index 25c07c99..bba3d923 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt @@ -46,6 +46,7 @@ class CogboardConstants { const val LOG_SOURCE = "logSource" const val LOG_SOURCE_TYPE = "logSourceType" + const val LOG_REQUEST_TYPE = "logRequestType" const val LOG_LINES = "logLines" const val LOG_FILE_PATH = "logFilePath" const val REQUEST_ID = "requestId" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt index f25b0e32..46e8467a 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt @@ -41,7 +41,7 @@ class SSHClient : AbstractVerticle() { } } - private fun tryToConnect(config: JsonObject) { + fun tryToConnect(config: JsonObject) { val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) try { connect(config) @@ -68,8 +68,9 @@ class SSHClient : AbstractVerticle() { private fun initSSHSession(authData: SSHAuthData) { jsch = JSch() - jsch.setKnownHosts("~/.ssh/known_hosts") - val session = SessionStrategyFactory(jsch).create(authData).initSession() + // jsch.setKnownHosts("~/.ssh/known_hosts") for security reasons this should be used + session = SessionStrategyFactory(jsch).create(authData).initSession() + session.setConfig("StrictHostKeyChecking", "no") // not secure session.connect(CogboardConstants.Props.SSH_TIMEOUT) } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt index df672652..ae0aa640 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -1,9 +1,19 @@ package com.cognifide.cogboard.widget.connectionStrategy +import com.cognifide.cogboard.CogboardConstants +import com.cognifide.cogboard.http.auth.AuthenticationType import io.vertx.core.Vertx import io.vertx.core.json.JsonObject abstract class ConnectionStrategy(protected val vertx: Vertx) { + protected fun JsonObject.endpointProp(prop: String): String { + return this.getJsonObject(CogboardConstants.Props.ENDPOINT_LOADED)?.getString(prop) ?: "" + } + + protected open fun authenticationTypes(): Set { + return setOf(AuthenticationType.BASIC) + } + abstract fun connectAndGetResources(address: String, arguments: JsonObject) } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index 9fd11187..fdc33db8 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -1,14 +1,18 @@ package com.cognifide.cogboard.widget.connectionStrategy import com.cognifide.cogboard.CogboardConstants.ConnectionType +import com.cognifide.cogboard.widget.connectionStrategy.http.* +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.RequestMethod import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject import java.lang.Exception -class ConnectionStrategyFactory { +class ConnectionStrategyFactory(private var vertx: Vertx, props: JsonObject) { class ConnectionTypeException : Exception("Unknown strategy type") - class MissingVertxException : Exception("Vertx hasn't been added to factory instance") - private lateinit var vertx: Vertx + private val connectionType = props.getString(Props.LOG_SOURCE_TYPE) + private val requestType = props.getString(Props.LOG_REQUEST_TYPE, "") fun addVertxInstance(vertx: Vertx): ConnectionStrategyFactory { this.vertx = vertx @@ -16,13 +20,18 @@ class ConnectionStrategyFactory { return this } - fun build(type: String): ConnectionStrategy { - if (!::vertx.isInitialized) { - throw MissingVertxException() - } + fun build(): ConnectionStrategy { - return when (type) { - ConnectionType.HTTP -> HTTPConnectionStrategy(vertx) + return when (connectionType) { + ConnectionType.HTTP -> { + when (requestType) { + RequestMethod.GET -> HttpGetConnectionStrategy(vertx) + RequestMethod.PUT -> HttpPutConnectionStrategy(vertx) + RequestMethod.POST -> HttpPostConnectionStrategy(vertx) + RequestMethod.DELETE -> HttpDeleteConnectionStrategy(vertx) + else -> throw ConnectionTypeException() + } + } ConnectionType.SSH -> SSHConnectionStrategy(vertx) else -> throw ConnectionTypeException() } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt deleted file mode 100644 index 3d942305..00000000 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.cognifide.cogboard.widget.connectionStrategy - -import io.vertx.core.Vertx -import io.vertx.core.json.JsonObject - -class HTTPConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - TODO("Not yet implemented") - } -} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index 2d250c35..e4b3a1d0 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -1,10 +1,27 @@ package com.cognifide.cogboard.widget.connectionStrategy +import com.cognifide.cogboard.CogboardConstants +import com.cognifide.cogboard.CogboardConstants.Props import io.vertx.core.Vertx +import io.vertx.core.json.Json import io.vertx.core.json.JsonObject -class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { +open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { override fun connectAndGetResources(address: String, arguments: JsonObject) { - TODO("Not yet implemented") + val config = ensureConfigIsPrepared(arguments) + vertx.eventBus().send(CogboardConstants.Event.SSH_COMMAND, config) + } + + private fun ensureConfigIsPrepared(config: JsonObject): JsonObject { + config.getString(Props.USER) ?: config.put(Props.USER, config.endpointProp(Props.USER)) + config.getString(Props.PASSWORD) ?: config.put(Props.PASSWORD, config.endpointProp(Props.PASSWORD)) + config.getString(Props.TOKEN) ?: config.put(Props.TOKEN, config.endpointProp(Props.TOKEN)) + config.getString(Props.SSH_KEY) ?: config.put(Props.SSH_KEY, config.endpointProp(Props.SSH_KEY)) + config.getString(Props.SSH_HOST) ?: config.put(Props.SSH_HOST, config.endpointProp(Props.SSH_HOST)) + config.getString(Props.LOG_FILE_PATH) ?: config.put(Props.LOG_FILE_PATH, config.endpointProp(Props.LOG_FILE_PATH)) + config.getString(Props.LOG_LINES) ?: config.put(Props.LOG_LINES, config.endpointProp(Props.LOG_LINES)) + config.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + + return config } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt new file mode 100644 index 00000000..e5a568a2 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt @@ -0,0 +1,19 @@ +package com.cognifide.cogboard.widget.connectionStrategy.http + +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy +import io.vertx.core.Vertx +import io.vertx.core.json.Json +import io.vertx.core.json.JsonObject + +abstract class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { + protected open fun basicProps(props: JsonObject): JsonObject { + return JsonObject() + .put(Props.URL, props.endpointProp(Props.URL)) + .put(Props.EVENT_ADDRESS, props.endpointProp(Props.EVENT_ADDRESS)) + .put(Props.USER, props.endpointProp(Props.USER)) + .put(Props.PASSWORD, props.endpointProp(Props.PASSWORD)) + .put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + .put(Props.CONTENT_TYPE, props.endpointProp(Props.CONTENT_TYPE)) + } +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt new file mode 100644 index 00000000..3cfca396 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt @@ -0,0 +1,62 @@ +package com.cognifide.cogboard.widget.connectionStrategy.http + +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.Event +import io.vertx.core.Vertx +import io.vertx.core.json.JsonObject + +class HttpGetConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + vertx.eventBus().send(Event.HTTP_GET, + basicProps(arguments) + ) + } + + override fun basicProps(props: JsonObject): JsonObject { + return super.basicProps(props) + .put(Props.REQUEST_ID, props.getValue(Props.REQUEST_ID, "")) + .put(Props.TOKEN, props.endpointProp(Props.TOKEN)) + } +} + +class HttpGetStatusConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + vertx.eventBus().send(Event.HTTP_CHECK, + basicProps(arguments) + ) + } +} + +class HttpPutConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + vertx.eventBus().send(Event.HTTP_PUT, + basicProps(arguments) + ) + } + + override fun basicProps(props: JsonObject): JsonObject { + return super.basicProps(props) + .put(Props.BODY, props.getJsonObject(Props.BODY)) + } +} + +class HttpPostConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + vertx.eventBus().send(Event.HTTP_POST, + basicProps(arguments) + ) + } + + override fun basicProps(props: JsonObject): JsonObject { + return super.basicProps(props) + .put(Props.BODY, props.getJsonObject(Props.BODY)) + } +} + +class HttpDeleteConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + vertx.eventBus().send(Event.HTTP_DELETE, + basicProps(arguments) + ) + } +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 67117b02..acf22e5b 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -1,14 +1,17 @@ package com.cognifide.cogboard.widget.type import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.ConnectionType import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.widget.BaseWidget import com.cognifide.cogboard.widget.Widget import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject +import java.nio.charset.Charset class LogViewerWidget( vertx: Vertx, @@ -16,20 +19,38 @@ class LogViewerWidget( serv: BoardsConfigService ) : BaseWidget(vertx, config, serv) { private val address = config.getString(Props.LOG_SOURCE) - private val lines = config.getInteger(Props.LOG_LINES) + private val lines = config.getString(Props.LOG_LINES) + private val connectionType = config.getString(Props.LOG_SOURCE_TYPE) - private lateinit var consumer: MessageConsumer - private var connectionStrategy: ConnectionStrategy = determineConnectionStrategy(config) + private var consumer: MessageConsumer<*>? = null + var connectionStrategy: ConnectionStrategy = determineConnectionStrategy() override fun start(): Widget { - consumer = vertx.eventBus() - .consumer(eventBusAddress) - .handler { - handleResponse(it.body()) - } + when (connectionType) { + ConnectionType.SSH -> { + consumer = vertx.eventBus() + .consumer(eventBusAddress) { + handleResponse(it.body()) + } + } + ConnectionType.HTTP -> { + consumer = vertx.eventBus() + .consumer(eventBusAddress) { + handleResponse(it.body()) + } + } + else -> { + sendConfigurationError("No type of connection chosen") + } + } return super.start() } + override fun stop(): Widget { + consumer?.unregister() + return super.stop() + } + override fun updateState() { if (address.isNotBlank()) { connectionStrategy.connectAndGetResources(address, config) @@ -46,16 +67,21 @@ class LogViewerWidget( } } + private fun handleResponse(responseBody: Buffer) { + val logs = prepareLogs( + responseBody.toString(Charset.defaultCharset()) + ) + + send(logs) + } + private fun prepareLogs(logs: String): String { // TODO return logs } - private fun determineConnectionStrategy(config: JsonObject): ConnectionStrategy { - val type = config.getString(Props.LOG_SOURCE_TYPE) - - return ConnectionStrategyFactory() + private fun determineConnectionStrategy() = + ConnectionStrategyFactory(vertx, config) .addVertxInstance(vertx) - .build(type) - } + .build() } diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt new file mode 100644 index 00000000..2c260557 --- /dev/null +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt @@ -0,0 +1,125 @@ +package com.cognifide.cogboard.ssh + +import com.cognifide.cogboard.CogboardConstants +import com.cognifide.cogboard.ssh.auth.AuthenticationType +import com.jcraft.jsch.JSchException +import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.EventBus +import io.vertx.core.json.Json +import io.vertx.core.json.JsonObject +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.* +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.MockitoAnnotations.initMocks +import org.mockito.junit.jupiter.MockitoExtension + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@ExtendWith(MockitoExtension::class) +class SSHClientTest { + private lateinit var sshClient: SSHClient + + @Captor + private lateinit var bufferCaptor: ArgumentCaptor + + @Captor + private lateinit var exceptionCaptor: ArgumentCaptor + + private lateinit var config: JsonObject + + @Mock + lateinit var vertx: Vertx + + @Mock + lateinit var eventBus: EventBus + + @BeforeEach + fun init() { + sshClient = SSHClient() + initMocks(this) + `when`(vertx.eventBus()).thenReturn(eventBus) + sshClient.init(vertx, null) + } + + private fun generateConfig(authTypes: Set) { + config = JsonObject() + .put(CogboardConstants.Props.USER, "mock") + .put(CogboardConstants.Props.PASSWORD, "TLQuoLMn*T89&Y*r*YqHviSFH6MkR!4E") + .put(CogboardConstants.Props.TOKEN, "TLQuoLMn*T89&Y*r*YqHviSFH6MkR!4E") + .put(CogboardConstants.Props.SSH_KEY, SSHClientTest::class.java.getResource( + "/com/cognifide/cogboard/ssh/id_rsa").path) + .put(CogboardConstants.Props.SSH_HOST, "150.254.30.120") + .put(CogboardConstants.Props.LOG_FILE_PATH, "/home/mock/example.txt") + .put(CogboardConstants.Props.LOG_LINES, "1") + .put(CogboardConstants.Props.AUTHENTICATION_TYPES, Json.encode(authTypes)) + .put(CogboardConstants.Props.EVENT_ADDRESS, "ssh.test.address") + } + + @Test + fun `Executing commands with user+password authentication succeeds`() { + generateConfig(setOf(AuthenticationType.BASIC)) + + sshClient.tryToConnect(config) + val (result, exception) = captureWhatIsSent(eventBus, bufferCaptor, exceptionCaptor) + + result?.let { + assertEquals("19:28:11.445 [vert.x-eventloop-thread-2] " + + "ERROR c.cognifide.cogboard.http.HttpClient - Connection was closed\n", + it.getString(0, it.length()) + ) + } + assert(exception == null) + } + + @Test + fun `Executing commands using key authentication succeeds`() { + generateConfig(setOf(AuthenticationType.SSH_KEY)) + + sshClient.tryToConnect(config) + val (result, exception) = captureWhatIsSent(eventBus, bufferCaptor, exceptionCaptor) + + result?.let { + assertEquals("19:28:11.445 [vert.x-eventloop-thread-2] " + + "ERROR c.cognifide.cogboard.http.HttpClient - Connection was closed\n", + it.getString(0, it.length()) + ) + } + assert(exception == null) + } + + @Test + fun `Executing commands with wrong credentials fails`() { + generateConfig(setOf(AuthenticationType.BASIC)) + config.remove(CogboardConstants.Props.PASSWORD) + config.put(CogboardConstants.Props.PASSWORD, "wrong") + + sshClient.tryToConnect(config) + + val (result, exception) = captureWhatIsSent(eventBus, bufferCaptor, exceptionCaptor) + + assert(result == null) + assert(exception is JSchException) + } + + private fun captureWhatIsSent(eventBus: EventBus, + bufferCaptor: ArgumentCaptor, + exceptionCaptor: ArgumentCaptor + ): Pair{ + return try { + verify(eventBus).send(eq("ssh.test.address"), bufferCaptor.capture()) + verify(eventBus, times(0)).send(eq("ssh.test.address"), any(Exception::class.java)) + Pair(bufferCaptor.value, null) + } catch (e: Throwable) { + verify(eventBus, times(0)).send(eq("ssh.test.address"), any(Buffer::class.java)) + verify(eventBus).send(eq("ssh.test.address"), exceptionCaptor.capture()) + Pair(null, exceptionCaptor.value) + } + } +} \ No newline at end of file diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt new file mode 100644 index 00000000..8d875706 --- /dev/null +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt @@ -0,0 +1,51 @@ +package com.cognifide.cogboard.widget.type + +import com.cognifide.cogboard.CogboardConstants.ConnectionType +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.RequestMethod +import io.vertx.core.buffer.Buffer +import io.vertx.core.json.JsonObject +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.Mockito.* + +class LogViewerTest: WidgetTestBase() { + + private lateinit var widget: LogViewerWidget + + override fun widgetName(): String { + return "LogViewerWidget" + } + + @BeforeEach + fun initForTest() { + super.init() + } + + @Test + fun `Expect Buffer consumer to be used when type is SSH`() { + val config = initWidget() + .put(Props.LOG_SOURCE_TYPE, ConnectionType.SSH) + .put(Props.LOG_SOURCE, "192.168.0.1") + .put(Props.LOG_LINES, "5") + widget = LogViewerWidget(vertx, config, initService()) + + widget.start() + + verify(eventBus).consumer(eq(widget.eventBusAddress), any()) + } + + @Test + fun `Expect JsonObject consumer to be used when type is HTTP`() { + val config = initWidget() + .put(Props.LOG_SOURCE_TYPE, ConnectionType.HTTP) + .put(Props.LOG_REQUEST_TYPE, RequestMethod.GET) + .put(Props.LOG_SOURCE, "192.168.0.1") + .put(Props.LOG_LINES, "5") + widget = LogViewerWidget(vertx, config, initService()) + + widget.start() + + verify(eventBus).consumer(eq(widget.eventBusAddress), any()) + } +} \ No newline at end of file diff --git a/cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa b/cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa new file mode 100644 index 00000000..2d77f8a1 --- /dev/null +++ b/cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEApphpbfnbEh4ZFdnloNqz0P3IDnADldRaD9ATzskGdcdRebJX +7mRJ+f174wyfee8WUl5W74TNIMHOo2oHFLD+/qtSg8m+w5JttmTS02wVCw/vBgC/ +3WSrR71jScBTQkm34ZQW9cZvuB0iJO3OtnGS2PJSxe1E8UNsey7EP/oXWjomCCgx +50hgWWDdj4PNHyMQoOcq9bZWT1yjWppSuBgaVYKwZhZeUPrObbixKOxMKqxEqjul +ayepln3DyI2Mq+/darE2cKD3FBA9MI6rbyA6nf0ncWCrrPsv1TpLFzqP9q1T+zPP +igpI778BuVJUYEEOWWmPmquti1tkiiAwJzKTaDILDObfifgcd9eyyr4FzZoArwep +Un6+yECthy2VMhxbGsJXVAnYmC3/06MFVjNXLgTvQG/h2YsknkSKaBgVdqI5ireK +l1rxkmIBzjdqJ8QuJjR1TbSxjmsDNeNCxrskLfAL3ATRJGmdXQHv6GU1g3Lt8qjr +TF/MMdV//oM/NwxfAgMBAAECggGAS/PaxVgPh8APIcY5CdAMATFi3yo0iD/LW8A6 +96DxAAuCWuBzdG1myMHHlKlxn87gN2dpbUP3nYKeqiQx3D4h04vaT9lPzqxYtrpa +4Cc7pNJ74BnBX7eA23E97ibwDp27Zu30VdNFpgQqR/nfr5AyKhS4piJZt0FNGRAm +SyDDOtCd/EQPFGoL+1PNT5wAjbyX3TPngyTBTudmVm1bXzEl+Gxf7fsuvu7J5H46 +zvSEeUQW/iG5dhQcHk9yTmIyi0UMyipOv+e+K4ujPQYDTaGL1y2czUlnCGZkztql +DWVRI54YBfNDX0tawaPrIuL7BT1yZVGaT3w89FIckJqRNBCy9LeaSz3qphpuLtZ6 +jZLGByEIurQCGJHhcJfU/mm25uCc3FFiSWeCIQcIMgF0zlQtlKFBsLzIZrHBFY6Q +XL4sxS6/QpotQ4p2tF1RbG2e6RjnJzammk79U5hs7/9nb4IbSQcn0SDz9UpNQzOD +WENMMQbUtyz4JEWrQPfNpgGdyOlxAoHBANVgiUrX27l6f9yUYdET4LCA6yINVQM5 +628+78Ho1GrnZqs3F+bO+9+jjGgW1ousLsnbmeaLNvbm2tZJhKCy4SfwypYCZDpO +8QY1Pscg6Wd8gsrjyjq6j/FoVp9TrWs4tUHjbIv9YEtBXdeto2CCSb/uhlc6jUDj +tmY0OLf5fWKFrKmfIZSFT/mz8ZO5KFXILuO395ZG/tMLxsRVm1Rsj2xFzUOnt6hg +NEJxI8Qx/7MC69SNrdkt34Kj7JdfkXeJmQKBwQDH35kbAMExA+Gznm/eE89TyDLc +P5qbsP62rc9BqU8aTnwwsd2QGhU3qwGx/0TEL+mR77j7cyXs8Z8bhqoqjr/5IvkJ +Bk8D18bNmu+QCeRs+kDUf1XdUzCF5uH6QezpnntD7KnUf+aJ+Byf6qp0WdLTyi/m +eJq2OqMqeDJnapY7wC9FpycD2Qw3eh47CFfIPFb+cRjsmIPaG28PHSmcU+uvZy9Z +t5wo7z+AmkBvcBBlPGORmH/4EUbAzNitCLEPMLcCgcAYngeY6+h8sKZZw4C5h2qP +0n/OMO2S7ra74e31WDBRmRreO//08AJdHdhQFfpwqM/JGB3cXEleGOo8eMTlaV3S +ptQolGQN2heymKgCf0iOWO4aDEfDmMyMlHYR8ax7R1KaJGvchsH6TLNP88d6le1+ +SD2ViLrNNrhPeEzm5NDTcgqmkyZjpTHB5EHFwkHmC69lNE9LNiumG6C1/A5sog21 +9yOkX5Avy9GbrMPsmbwfYgHlRuc8vC8iOllMaYk12lkCgcEAnrqVznoE8rYQciLq +2ESHLBQbQApK8EXZop3ZsF2S8mNOASXfvObZ3sGxsPf2Vo9uQHVORHKntcoU/zks +vmtrTaFWgLI/4d9khDf89DjG7Ty4a4lMWV4NdOlsoN/mE4nGfqTeImIIZZ1iriUg +hRIoegVhkPhKdVmP5tRZwwNEl+MCJ6CdPVMLfqs+gscXX2977slGb+6XF4kd47TX +LM0AqOWbFvbXzzJhDfJyJY2rl5ojwKaJSin+NHL5yEDUzCl1AoHBAK85ZTR0CmlE +jV4OrsBk937oDysYMYH6IYAUQ4xX4jCu5nbHi6xIpAuha2Xh0vWCr7xoguxDE67j +z6NeE2s3wsjK5I9tvAxwvpnSUvMPFVojlxrPQLHcRh3VmAq3kYtF2HrmJx+lsmDD +mLZLHgj4lqcWlhME4ZsENrLBoUtwx9NEvTjJoNGdeU1TsDSUx/a5DGleeqLHjejS +SoGobi0iGwCCe/gfAyJ4zgtYe3ie6yJRcsESHuCfrk6ET0vodep/nA== +-----END RSA PRIVATE KEY----- From 1dbb996503b8f6d048a62c6ae0218957f4b09102 Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Fri, 22 Oct 2021 23:08:33 +0200 Subject: [PATCH 09/35] Deleted SSHWidget - replaced by strategies [#381] --- .../cognifide/cogboard/widget/SSHWidget.kt | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt deleted file mode 100644 index 43939a69..00000000 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.cognifide.cogboard.widget - -import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.CogboardConstants.Event -import com.cognifide.cogboard.config.service.BoardsConfigService -import io.vertx.core.Vertx -import io.vertx.core.eventbus.MessageConsumer -import io.vertx.core.json.JsonObject -import java.nio.Buffer - -abstract class SSHWidget( - vertx: Vertx, - config: JsonObject, - serv: BoardsConfigService -) : AsyncWidget(vertx, config, serv) { - val sshKey: String = config.endpointProp(Props.SSH_KEY) - val host: String = config.endpointProp(Props.SSH_HOST) - val logPath: String = config.endpointProp(Props.LOG_FILE_PATH) - val logLines: String = config.endpointProp(Props.LOG_LINES) - private lateinit var sshConsumer: MessageConsumer - - fun registerForSSH(eventBusAddress: String) { - sshConsumer = vertx.eventBus() - .consumer(eventBusAddress) - .handler { - handleSSHResponse(it.body()) - } - } - - abstract fun handleSSHResponse(body: Buffer?) - - fun unregisterFromSSH() { - if (::sshConsumer.isInitialized) { - sshConsumer.unregister() - } - } - - fun sendRequestForLogs(config: JsonObject) { - ensureConfigIsPrepared(config) - vertx.eventBus().send(Event.SSH_COMMAND, config) - } - - private fun ensureConfigIsPrepared(config: JsonObject) { - config.getString(Props.USER) ?: config.put(Props.USER, user) - config.getString(Props.PASSWORD) ?: config.put(Props.PASSWORD, password) - config.getString(Props.TOKEN) ?: config.put(Props.TOKEN, token) - config.getString(Props.SSH_KEY) ?: config.put(Props.SSH_KEY, sshKey) - config.getString(Props.SSH_HOST) ?: config.put(Props.SSH_HOST, host) - config.getString(Props.LOG_FILE_PATH) ?: config.put(Props.LOG_FILE_PATH, logPath) - config.getString(Props.LOG_LINES) ?: config.put(Props.LOG_LINES, logLines) - } -} From 23a2b6b8bc2fac0885559d77717617cf6f6596dc Mon Sep 17 00:00:00 2001 From: Borrubasz Date: Sat, 23 Oct 2021 20:33:17 +0200 Subject: [PATCH 10/35] Changes after code review - problem with tests to solve --- api-mocks/__files/logViewer/logs.json | 10 ++- api-mocks/mappings/endpoints-mapping.json | 2 +- .../cognifide/cogboard/widget/WidgetIndex.kt | 15 ++++- .../connectionStrategy/ConnectionStrategy.kt | 6 +- .../ConnectionStrategyFactory.kt | 28 +++------ .../HttpConnectionStrategy.kt | 51 +++++++++++++++ .../SSHConnectionStrategy.kt | 10 ++- .../http/HttpConnectionStrategy.kt | 19 ------ .../http/HttpConnectionStrategyImpl.kt | 62 ------------------- .../cogboard/widget/type/LogViewerWidget.kt | 39 +++++------- 10 files changed, 115 insertions(+), 127 deletions(-) create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt delete mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt delete mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt diff --git a/api-mocks/__files/logViewer/logs.json b/api-mocks/__files/logViewer/logs.json index b4211a0e..e5c4e740 100644 --- a/api-mocks/__files/logViewer/logs.json +++ b/api-mocks/__files/logViewer/logs.json @@ -1,3 +1,11 @@ { - "logLines": "02:49:12 127.0.0.1 GET / 200\n02:49:35 127.0.0.1 GET /index.html 200\n03:01:06 127.0.0.1 GET /images/sponsered.gif 304\n03:52:36 127.0.0.1 GET /search.php 200\n04:17:03 127.0.0.1 GET /admin/style.css 200\n05:04:54 127.0.0.1 GET /favicon.ico 404\n05:38:07 127.0.0.1 GET /js/ads.js 200\n" + "logLines": [ + "02:49:12 127.0.0.1 GET / 200", + "02:49:35 127.0.0.1 GET /index.html 200", + "03:01:06 127.0.0.1 GET /images/sponsered.gif 304", + "03:52:36 127.0.0.1 GET /search.php 200", + "04:17:03 127.0.0.1 GET /admin/style.css 200", + "05:04:54 127.0.0.1 GET /favicon.ico 404", + "05:38:07 127.0.0.1 GET /js/ads.js 200" + ] } \ No newline at end of file diff --git a/api-mocks/mappings/endpoints-mapping.json b/api-mocks/mappings/endpoints-mapping.json index 8dc85fa6..d98b991d 100644 --- a/api-mocks/mappings/endpoints-mapping.json +++ b/api-mocks/mappings/endpoints-mapping.json @@ -3,7 +3,7 @@ { "request": { "method": "GET", - "url": "/logviewer", + "url": "/log-viewer", "queryParameters": { "lines": { "matches": "^[0-9]+$" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt index a73e9feb..e057a29b 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt @@ -3,7 +3,20 @@ package com.cognifide.cogboard.widget import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.storage.VolumeStorageFactory.appConfig -import com.cognifide.cogboard.widget.type.* +import com.cognifide.cogboard.widget.type.AemBundleInfoWidget +import com.cognifide.cogboard.widget.type.AemHealthcheckWidget +import com.cognifide.cogboard.widget.type.BambooDeploymentWidget +import com.cognifide.cogboard.widget.type.BambooPlanWidget +import com.cognifide.cogboard.widget.type.CheckboxWidget +import com.cognifide.cogboard.widget.type.IframeEmbedWidget +import com.cognifide.cogboard.widget.type.JenkinsJobWidget +import com.cognifide.cogboard.widget.type.JiraBucketsWidget +import com.cognifide.cogboard.widget.type.LinkListWidget +import com.cognifide.cogboard.widget.type.WhiteSpaceWidget +import com.cognifide.cogboard.widget.type.ServiceCheckWidget +import com.cognifide.cogboard.widget.type.TextWidget +import com.cognifide.cogboard.widget.type.ToDoListWidget +import com.cognifide.cogboard.widget.type.WorldClockWidget import com.cognifide.cogboard.widget.type.randompicker.RandomPickerWidget import com.cognifide.cogboard.widget.type.sonarqube.SonarQubeWidget import com.cognifide.cogboard.widget.type.zabbix.ZabbixWidget diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt index ae0aa640..74f1025e 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -3,10 +3,10 @@ package com.cognifide.cogboard.widget.connectionStrategy import com.cognifide.cogboard.CogboardConstants import com.cognifide.cogboard.http.auth.AuthenticationType import io.vertx.core.Vertx +import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject abstract class ConnectionStrategy(protected val vertx: Vertx) { - protected fun JsonObject.endpointProp(prop: String): String { return this.getJsonObject(CogboardConstants.Props.ENDPOINT_LOADED)?.getString(prop) ?: "" } @@ -16,4 +16,8 @@ abstract class ConnectionStrategy(protected val vertx: Vertx) { } abstract fun connectAndGetResources(address: String, arguments: JsonObject) + + abstract fun getConsumer(eventBusAddress: String): MessageConsumer<*> + + abstract fun handleResponse(response: Any): String } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index fdc33db8..d728ff15 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -1,39 +1,31 @@ package com.cognifide.cogboard.widget.connectionStrategy import com.cognifide.cogboard.CogboardConstants.ConnectionType -import com.cognifide.cogboard.widget.connectionStrategy.http.* import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.CogboardConstants.RequestMethod import io.vertx.core.Vertx import io.vertx.core.json.JsonObject -import java.lang.Exception -class ConnectionStrategyFactory(private var vertx: Vertx, props: JsonObject) { - class ConnectionTypeException : Exception("Unknown strategy type") +class UnknownConnectionTypeException( + message: String? +) : RuntimeException(message) + +class ConnectionStrategyFactory( + private var vertx: Vertx, + props: JsonObject +) { private val connectionType = props.getString(Props.LOG_SOURCE_TYPE) - private val requestType = props.getString(Props.LOG_REQUEST_TYPE, "") fun addVertxInstance(vertx: Vertx): ConnectionStrategyFactory { this.vertx = vertx - return this } fun build(): ConnectionStrategy { - return when (connectionType) { - ConnectionType.HTTP -> { - when (requestType) { - RequestMethod.GET -> HttpGetConnectionStrategy(vertx) - RequestMethod.PUT -> HttpPutConnectionStrategy(vertx) - RequestMethod.POST -> HttpPostConnectionStrategy(vertx) - RequestMethod.DELETE -> HttpDeleteConnectionStrategy(vertx) - else -> throw ConnectionTypeException() - } - } + ConnectionType.HTTP -> HttpConnectionStrategy(vertx) ConnectionType.SSH -> SSHConnectionStrategy(vertx) - else -> throw ConnectionTypeException() + else -> throw UnknownConnectionTypeException("Unknown strategy type") } } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt new file mode 100644 index 00000000..a5728fe4 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt @@ -0,0 +1,51 @@ +package com.cognifide.cogboard.widget.connectionStrategy + +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.Event +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.GET +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.PUT +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.POST +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.DELETE +import io.vertx.core.Vertx +import io.vertx.core.eventbus.MessageConsumer +import io.vertx.core.json.Json +import io.vertx.core.json.JsonObject + +class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + when (arguments.getString(Props.LOG_REQUEST_TYPE, "")) { + GET -> vertx.eventBus().send(Event.HTTP_GET, getProps(arguments)) + PUT -> vertx.eventBus().send(Event.HTTP_PUT, putProps(arguments)) + POST -> vertx.eventBus().send(Event.HTTP_POST, postProps(arguments)) + DELETE -> vertx.eventBus().send(Event.HTTP_DELETE, basicProps(arguments)) + } + } + + override fun getConsumer(eventBusAddress: String): MessageConsumer<*> = + vertx.eventBus().consumer(eventBusAddress) + + override fun handleResponse(response: Any): String = + (response as JsonObject).getString(Props.LOG_LINES) + + private fun basicProps(props: JsonObject): JsonObject = + JsonObject() + .put(Props.URL, props.endpointProp(Props.URL)) + .put(Props.EVENT_ADDRESS, props.endpointProp(Props.EVENT_ADDRESS)) + .put(Props.USER, props.endpointProp(Props.USER)) + .put(Props.PASSWORD, props.endpointProp(Props.PASSWORD)) + .put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + .put(Props.CONTENT_TYPE, props.endpointProp(Props.CONTENT_TYPE)) + + private fun getProps(props: JsonObject): JsonObject = + basicProps(props) + .put(Props.REQUEST_ID, props.getValue(Props.REQUEST_ID, "")) + .put(Props.TOKEN, props.endpointProp(Props.TOKEN)) + + private fun putProps(props: JsonObject): JsonObject = + basicProps(props) + .put(Props.BODY, props.getJsonObject(Props.BODY)) + + private fun postProps(props: JsonObject): JsonObject = + basicProps(props) + .put(Props.BODY, props.getJsonObject(Props.BODY)) +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index e4b3a1d0..13f59c16 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -3,8 +3,11 @@ package com.cognifide.cogboard.widget.connectionStrategy import com.cognifide.cogboard.CogboardConstants import com.cognifide.cogboard.CogboardConstants.Props import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.Json import io.vertx.core.json.JsonObject +import java.nio.charset.Charset open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { override fun connectAndGetResources(address: String, arguments: JsonObject) { @@ -12,6 +15,12 @@ open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { vertx.eventBus().send(CogboardConstants.Event.SSH_COMMAND, config) } + override fun getConsumer(eventBusAddress: String): MessageConsumer<*> = + vertx.eventBus().consumer(eventBusAddress) + + override fun handleResponse(response: Any): String = + (response as Buffer).toString(Charset.defaultCharset()) + private fun ensureConfigIsPrepared(config: JsonObject): JsonObject { config.getString(Props.USER) ?: config.put(Props.USER, config.endpointProp(Props.USER)) config.getString(Props.PASSWORD) ?: config.put(Props.PASSWORD, config.endpointProp(Props.PASSWORD)) @@ -21,7 +30,6 @@ open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { config.getString(Props.LOG_FILE_PATH) ?: config.put(Props.LOG_FILE_PATH, config.endpointProp(Props.LOG_FILE_PATH)) config.getString(Props.LOG_LINES) ?: config.put(Props.LOG_LINES, config.endpointProp(Props.LOG_LINES)) config.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) - return config } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt deleted file mode 100644 index e5a568a2..00000000 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategy.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.cognifide.cogboard.widget.connectionStrategy.http - -import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy -import io.vertx.core.Vertx -import io.vertx.core.json.Json -import io.vertx.core.json.JsonObject - -abstract class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { - protected open fun basicProps(props: JsonObject): JsonObject { - return JsonObject() - .put(Props.URL, props.endpointProp(Props.URL)) - .put(Props.EVENT_ADDRESS, props.endpointProp(Props.EVENT_ADDRESS)) - .put(Props.USER, props.endpointProp(Props.USER)) - .put(Props.PASSWORD, props.endpointProp(Props.PASSWORD)) - .put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) - .put(Props.CONTENT_TYPE, props.endpointProp(Props.CONTENT_TYPE)) - } -} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt deleted file mode 100644 index 3cfca396..00000000 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/http/HttpConnectionStrategyImpl.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.cognifide.cogboard.widget.connectionStrategy.http - -import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.CogboardConstants.Event -import io.vertx.core.Vertx -import io.vertx.core.json.JsonObject - -class HttpGetConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - vertx.eventBus().send(Event.HTTP_GET, - basicProps(arguments) - ) - } - - override fun basicProps(props: JsonObject): JsonObject { - return super.basicProps(props) - .put(Props.REQUEST_ID, props.getValue(Props.REQUEST_ID, "")) - .put(Props.TOKEN, props.endpointProp(Props.TOKEN)) - } -} - -class HttpGetStatusConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - vertx.eventBus().send(Event.HTTP_CHECK, - basicProps(arguments) - ) - } -} - -class HttpPutConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - vertx.eventBus().send(Event.HTTP_PUT, - basicProps(arguments) - ) - } - - override fun basicProps(props: JsonObject): JsonObject { - return super.basicProps(props) - .put(Props.BODY, props.getJsonObject(Props.BODY)) - } -} - -class HttpPostConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - vertx.eventBus().send(Event.HTTP_POST, - basicProps(arguments) - ) - } - - override fun basicProps(props: JsonObject): JsonObject { - return super.basicProps(props) - .put(Props.BODY, props.getJsonObject(Props.BODY)) - } -} - -class HttpDeleteConnectionStrategy(vertx: Vertx) : HttpConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - vertx.eventBus().send(Event.HTTP_DELETE, - basicProps(arguments) - ) - } -} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index acf22e5b..9b08fd40 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -1,7 +1,6 @@ package com.cognifide.cogboard.widget.type import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.CogboardConstants.ConnectionType import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.widget.BaseWidget import com.cognifide.cogboard.widget.Widget @@ -9,6 +8,7 @@ import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject import java.nio.charset.Charset @@ -23,25 +23,12 @@ class LogViewerWidget( private val connectionType = config.getString(Props.LOG_SOURCE_TYPE) private var consumer: MessageConsumer<*>? = null - var connectionStrategy: ConnectionStrategy = determineConnectionStrategy() + private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() override fun start(): Widget { - when (connectionType) { - ConnectionType.SSH -> { - consumer = vertx.eventBus() - .consumer(eventBusAddress) { - handleResponse(it.body()) - } - } - ConnectionType.HTTP -> { - consumer = vertx.eventBus() - .consumer(eventBusAddress) { - handleResponse(it.body()) - } - } - else -> { - sendConfigurationError("No type of connection chosen") - } + consumer = connectionStrategy.getConsumer(eventBusAddress) + consumer!!.handler { + handleResponse(it) } return super.start() } @@ -59,19 +46,25 @@ class LogViewerWidget( } } + private fun handleResponse(response: Message<*>) { + val responseBody = response.body() + if (responseBody is JsonObject) { + if (checkAuthorized(responseBody)) { + send(prepareLogs(connectionStrategy.handleResponse(responseBody))) + } + } else { + send(prepareLogs(connectionStrategy.handleResponse(responseBody))) + } + } private fun handleResponse(responseBody: JsonObject) { if (checkAuthorized(responseBody)) { val logs = responseBody.getString(Props.LOG_LINES) - send(prepareLogs(logs)) } } private fun handleResponse(responseBody: Buffer) { - val logs = prepareLogs( - responseBody.toString(Charset.defaultCharset()) - ) - + val logs = prepareLogs(responseBody.toString(Charset.defaultCharset())) send(logs) } From 32391535f6a7042fee220cf2d3a1171a650246cc Mon Sep 17 00:00:00 2001 From: clmrv Date: Sat, 23 Oct 2021 21:31:25 +0200 Subject: [PATCH 11/35] Add ssh to endpoints dialog fields #412 --- cogboard-webapp/src/components/widgets/dialogFields/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogboard-webapp/src/components/widgets/dialogFields/index.js b/cogboard-webapp/src/components/widgets/dialogFields/index.js index 2ec23c53..33cad510 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/index.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/index.js @@ -105,7 +105,7 @@ const dialogFields = { name: 'publicUrl', label: 'Public URL', validator: () => - string().matches(/^(http|https|ws|ftp):\/\/.*([:.]).*/, { + string().matches(/^(http|https|ws|ftp|ssh):\/\/.*([:.]).*/, { message: vm.INVALID_PUBLIC_URL(), excludeEmptyString: true }) @@ -251,7 +251,7 @@ const dialogFields = { name: 'url', label: 'URL', validator: () => - string().matches(/^(http|https|ws|ftp):\/\/.*([:.]).*/, { + string().matches(/^(http|https|ws|ftp|ssh):\/\/.*([:.]).*/, { message: vm.INVALID_URL(), excludeEmptyString: true }) From 26a173e657ab5296e4b29bb9ec2baf0b8fc027ed Mon Sep 17 00:00:00 2001 From: Michal Przypasniak Date: Sat, 23 Oct 2021 23:18:22 +0200 Subject: [PATCH 12/35] Tests fixed --- .../cognifide/cogboard/widget/type/LogViewerTest.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt index 8d875706..896b60b2 100644 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt @@ -4,6 +4,7 @@ import com.cognifide.cogboard.CogboardConstants.ConnectionType import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.CogboardConstants.RequestMethod import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -24,6 +25,9 @@ class LogViewerTest: WidgetTestBase() { @Test fun `Expect Buffer consumer to be used when type is SSH`() { + val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer + `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + val config = initWidget() .put(Props.LOG_SOURCE_TYPE, ConnectionType.SSH) .put(Props.LOG_SOURCE, "192.168.0.1") @@ -32,11 +36,14 @@ class LogViewerTest: WidgetTestBase() { widget.start() - verify(eventBus).consumer(eq(widget.eventBusAddress), any()) + verify(eventBus).consumer(eq(widget.eventBusAddress)) } @Test fun `Expect JsonObject consumer to be used when type is HTTP`() { + val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer + `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + val config = initWidget() .put(Props.LOG_SOURCE_TYPE, ConnectionType.HTTP) .put(Props.LOG_REQUEST_TYPE, RequestMethod.GET) @@ -46,6 +53,6 @@ class LogViewerTest: WidgetTestBase() { widget.start() - verify(eventBus).consumer(eq(widget.eventBusAddress), any()) + verify(eventBus).consumer(eq(widget.eventBusAddress)) } } \ No newline at end of file From 737c288e373d5c9d0c1c2b15cec683704ed1ceb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Sun, 24 Oct 2021 16:27:19 +0200 Subject: [PATCH 13/35] Add SSH Key field to Credentials --- .../config/controller/CredentialsController.kt | 1 + .../cognifide/cogboard/config/model/Credential.kt | 3 ++- .../src/components/CredentialForm/index.js | 6 ++++-- .../src/components/widgets/dialogFields/index.js | 15 +++++++++++++++ cogboard-webapp/src/constants/index.js | 5 ++++- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt index b417d92b..d2cdc379 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt @@ -37,6 +37,7 @@ class CredentialsController : AbstractVerticle() { private fun JsonObject.filterSensitiveData(): JsonObject { this.remove(Props.PASSWORD) + this.remove(Props.SSH_KEY) return this } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt index 19cb0471..ddb05261 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt @@ -5,5 +5,6 @@ data class Credential( val label: String, val user: String, val password: String?, - val token: String? + val token: String?, + val sshKey: String? ) diff --git a/cogboard-webapp/src/components/CredentialForm/index.js b/cogboard-webapp/src/components/CredentialForm/index.js index 8cc72821..9c80150b 100644 --- a/cogboard-webapp/src/components/CredentialForm/index.js +++ b/cogboard-webapp/src/components/CredentialForm/index.js @@ -22,7 +22,8 @@ const CredentialsForm = ({ 'UsernameField', 'PasswordField', 'PasswordConfirmationField', - 'TokenField' + 'TokenField', + 'SSHKeyField' ]; const constraints = { @@ -82,7 +83,8 @@ CredentialsForm.defaultProps = { user: '', password: '', confirmationPassword: '', - token: '' + token: '', + sshKey: '' }; export default CredentialsForm; diff --git a/cogboard-webapp/src/components/widgets/dialogFields/index.js b/cogboard-webapp/src/components/widgets/dialogFields/index.js index 33cad510..f68c87a0 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/index.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/index.js @@ -100,6 +100,21 @@ const dialogFields = { label: 'Token', validator: () => string() }, + SSHKeyField: { + component: MultilineTextInput, + name: 'sshKey', + label: 'SSH Private Key', + validator: () => + string() + .matches('^-----BEGIN OPENSSH PRIVATE KEY-----\n', { + message: vm.SSH_KEY_BEGIN, + excludeEmptyString: true + }) + .matches('\n-----END OPENSSH PRIVATE KEY-----$', { + message: vm.SSH_KEY_END, + excludeEmptyString: true + }) + }, PublicURL: { component: TextInput, name: 'publicUrl', diff --git a/cogboard-webapp/src/constants/index.js b/cogboard-webapp/src/constants/index.js index 3b83785d..ca434023 100644 --- a/cogboard-webapp/src/constants/index.js +++ b/cogboard-webapp/src/constants/index.js @@ -305,7 +305,10 @@ export const validationMessages = { INVALID_PUBLIC_URL: () => 'Invalid Public URL', FIELD_MIN_ITEMS: () => 'This field must have at least 1 item.', UNIQUE_FIELD: () => 'This field must be unique.', - PASSWORD_MATCH: () => 'Password must match.' + PASSWORD_MATCH: () => 'Password must match.', + SSH_KEY_BEGIN: () => + 'The key must begin with "-----BEGIN OPENSSH PRIVATE KEY-----"', + SSH_KEY_END: () => 'The key must end with "-----END OPENSSH PRIVATE KEY-----"' }; export const NOTIFICATIONS = { From 7d2f0b2b9ee5d085b7eee0a663c2ebf0c1e26b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Sun, 24 Oct 2021 17:42:05 +0200 Subject: [PATCH 14/35] Modify credential test --- .../cypress/fixtures/credentialsEndpoints.js | 3 ++- .../cypress/integration/credentials.js | 9 +++++++++ .../cypress-tests/cypress/support/credential.js | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js b/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js index 03e0430b..b4f05860 100644 --- a/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js +++ b/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js @@ -4,7 +4,8 @@ export const badCredentials = () => { password: 'xxxxxxxxxxx', passwordConf: 'zzz', user: 'xxxxxxxxxxxxxxxxxxxxxxxxxx', - label: ' ' + label: ' ', + sshKey: 'xxx', }; }; diff --git a/functional/cypress-tests/cypress/integration/credentials.js b/functional/cypress-tests/cypress/integration/credentials.js index 572afbbf..37a0b787 100644 --- a/functional/cypress-tests/cypress/integration/credentials.js +++ b/functional/cypress-tests/cypress/integration/credentials.js @@ -25,6 +25,7 @@ describe('Credentials', () => { .applyPassword() .assertErrorMessageVisible('Password must match.', 'credential-form-auth') .applyToken() + .applySSHKey() .assertErrorMessageVisible( 'This field is required', 'credential-form-auth-label-input-error' @@ -32,6 +33,14 @@ describe('Credentials', () => { .assertErrorMessageVisible( 'Label length must be less or equal to 25.', 'credential-form-auth-user-input-error' + ) + .assertErrorMessageVisible( + 'The key must begin with "-----BEGIN OPENSSH PRIVATE KEY-----"', + 'credential-form-auth-ssh-key-input-error' + ) + .assertErrorMessageVisible( + 'The key must end with "-----END OPENSSH PRIVATE KEY-----"', + 'credential-form-auth-ssh-key-input-error' ); }); diff --git a/functional/cypress-tests/cypress/support/credential.js b/functional/cypress-tests/cypress/support/credential.js index 9ee77c41..a757c8f9 100644 --- a/functional/cypress-tests/cypress/support/credential.js +++ b/functional/cypress-tests/cypress/support/credential.js @@ -58,6 +58,17 @@ class Credentials { return this; } + applySSHKey(config) { + if (config !== undefined) { + this.config = config; + } + cy.get('[data-cy="credential-form-auth-ssh-key-input"]') + .clear() + .type(this.config.sshKey) + .blur(); + return this; + } + save() { cy.get('[data-cy="credential-form-submit-button"]').click(); return this; @@ -77,7 +88,10 @@ class Credentials { } assertErrorMessageVisible(message, dataCYName) { - cy.contains(`[data-cy^="${dataCYName}"]`, message).should('is.visible'); + cy + .contains(`[data-cy^="${dataCYName}"]`, message) + .scrollIntoView() + .should('is.visible'); return this; } } From 5729dae71a4ec3830e8bea90b337293d12c88278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Sun, 24 Oct 2021 18:03:08 +0200 Subject: [PATCH 15/35] Change SSH Key regex --- cogboard-webapp/src/components/widgets/dialogFields/index.js | 4 ++-- cogboard-webapp/src/constants/index.js | 5 ++--- functional/cypress-tests/cypress/integration/credentials.js | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cogboard-webapp/src/components/widgets/dialogFields/index.js b/cogboard-webapp/src/components/widgets/dialogFields/index.js index f68c87a0..08351814 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/index.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/index.js @@ -106,11 +106,11 @@ const dialogFields = { label: 'SSH Private Key', validator: () => string() - .matches('^-----BEGIN OPENSSH PRIVATE KEY-----\n', { + .matches('^-----BEGIN ([A-Z]{1,} )*PRIVATE KEY-----\n', { message: vm.SSH_KEY_BEGIN, excludeEmptyString: true }) - .matches('\n-----END OPENSSH PRIVATE KEY-----$', { + .matches('\n-----END ([A-Z]{1,} )*PRIVATE KEY-----$', { message: vm.SSH_KEY_END, excludeEmptyString: true }) diff --git a/cogboard-webapp/src/constants/index.js b/cogboard-webapp/src/constants/index.js index ca434023..07da5544 100644 --- a/cogboard-webapp/src/constants/index.js +++ b/cogboard-webapp/src/constants/index.js @@ -306,9 +306,8 @@ export const validationMessages = { FIELD_MIN_ITEMS: () => 'This field must have at least 1 item.', UNIQUE_FIELD: () => 'This field must be unique.', PASSWORD_MATCH: () => 'Password must match.', - SSH_KEY_BEGIN: () => - 'The key must begin with "-----BEGIN OPENSSH PRIVATE KEY-----"', - SSH_KEY_END: () => 'The key must end with "-----END OPENSSH PRIVATE KEY-----"' + SSH_KEY_BEGIN: () => 'The key must begin with "-----BEGIN PRIVATE KEY-----"', + SSH_KEY_END: () => 'The key must end with "-----END PRIVATE KEY-----"' }; export const NOTIFICATIONS = { diff --git a/functional/cypress-tests/cypress/integration/credentials.js b/functional/cypress-tests/cypress/integration/credentials.js index 37a0b787..878fe006 100644 --- a/functional/cypress-tests/cypress/integration/credentials.js +++ b/functional/cypress-tests/cypress/integration/credentials.js @@ -35,11 +35,11 @@ describe('Credentials', () => { 'credential-form-auth-user-input-error' ) .assertErrorMessageVisible( - 'The key must begin with "-----BEGIN OPENSSH PRIVATE KEY-----"', + 'The key must begin with "-----BEGIN PRIVATE KEY-----"', 'credential-form-auth-ssh-key-input-error' ) .assertErrorMessageVisible( - 'The key must end with "-----END OPENSSH PRIVATE KEY-----"', + 'The key must end with "-----END PRIVATE KEY-----"', 'credential-form-auth-ssh-key-input-error' ); }); From b5a967ec3e17839c939414ee602d6794afa6ff26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Wed, 27 Oct 2021 14:57:12 +0200 Subject: [PATCH 16/35] Add OpenSSH docker image --- build.gradle.kts | 2 +- cogboard-local-compose.yml | 6 ++++++ settings.gradle.kts | 1 + ssh/Dockerfile | 9 +++++++++ ssh/build.gradle.kts | 14 ++++++++++++++ ssh/gen.sh | 20 ++++++++++++++++++++ 6 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 ssh/Dockerfile create mode 100644 ssh/build.gradle.kts create mode 100755 ssh/gen.sh diff --git a/build.gradle.kts b/build.gradle.kts index 4451a9a0..61c3cb24 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -55,7 +55,7 @@ allprojects { tasks { named("build") { - dependsOn(":cogboard-app:test", ":cogboard-webapp:buildImage") + dependsOn(":cogboard-app:test", ":cogboard-webapp:buildImage", ":ssh:buildImage") } register("cypressInit", Exec::class) { setWorkingDir("./functional/cypress-tests") diff --git a/cogboard-local-compose.yml b/cogboard-local-compose.yml index 327aeb6f..f9b6fa54 100644 --- a/cogboard-local-compose.yml +++ b/cogboard-local-compose.yml @@ -16,6 +16,12 @@ services: - cognet command: ["--no-request-journal", "--global-response-templating"] + ssh-server: + image: ssh-server + hostname: ssh-server + networks: + - cognet + backend: image: "cogboard/cogboard-app:${COGBOARD_VERSION}" environment: diff --git a/settings.gradle.kts b/settings.gradle.kts index 0700e243..dd77ec50 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,3 +17,4 @@ rootProject.name = "cogboard" include("cogboard-app") include("cogboard-webapp") +include("ssh") \ No newline at end of file diff --git a/ssh/Dockerfile b/ssh/Dockerfile new file mode 100644 index 00000000..34debc3e --- /dev/null +++ b/ssh/Dockerfile @@ -0,0 +1,9 @@ +FROM lscr.io/linuxserver/openssh-server + +ENV PUBLIC_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICLzgU4PuqFGnQCd5A5Gl30ssE3b9fW7gcyvES4xHHUo mock@openssh-server" +ENV PASSWORD_ACCESS=true +ENV USER_NAME=mock +ENV USER_PASSWORD=TLQuoLMn*T89&Y*r*YqHviSFH6MkR!4E + +ADD gen.sh /home/mock/gen.sh +RUN /home/mock/gen.sh 50 > /home/mock/example.txt \ No newline at end of file diff --git a/ssh/build.gradle.kts b/ssh/build.gradle.kts new file mode 100644 index 00000000..13232d3c --- /dev/null +++ b/ssh/build.gradle.kts @@ -0,0 +1,14 @@ +import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage + +plugins { + id("base") + id("com.bmuschko.docker-remote-api") +} + +tasks { + register("buildImage") { + group = "docker" + inputDir.set(file(projectDir)) + images.add("ssh-server") + } +} \ No newline at end of file diff --git a/ssh/gen.sh b/ssh/gen.sh new file mode 100755 index 00000000..b4b511bf --- /dev/null +++ b/ssh/gen.sh @@ -0,0 +1,20 @@ +#!/bin/bash +labels=(DEBUG INFO WARNING ERROR) +words=(Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sit amet massa sit amet mi feugiat lobortis. Morbi ultrices hendrerit luctus. Donec fermentum viverra viverra. Integer convallis sapien sit amet facilisis pretium. Ut quis commodo odio, ac bibendum urna. Ut imperdiet ante sed ex sollicitudin auctor. Nulla vel eros sit amet velit vulputate suscipit a malesuada felis. Curabitur commodo, erat eget condimentum tristique, ante diam porttitor nulla, condimentum vulputate nibh ex sit amet velit. Vestibulum vel lectus bibendum, pellentesque nisl id, vehicula tellus. Suspendisse sem turpis, dignissim quis aliquet nec, laoreet sit amet urna. Nulla non euismod tellus, id varius) + +COUNT=5 +if ! [ -z "$1" ]; then + COUNT=$1 +fi + +for run in $( seq 1 $COUNT ); do + d=$(date +%Y-%m-%d:%H:%M:%S) + l=${labels[$(($RANDOM%4))]} + w=() + wCount=$(($RANDOM%5+5)) + for (( i=0; i<$wCount; i++ )) + do + w[i]=${words[$(($RANDOM%${#words[@]}))]} + done + echo $d "*"${l}"* [FelixStartLevel] " ${w[*]} +done \ No newline at end of file From 8acac9610c6b2f3d43bfd0f58f1f3c5dbebc8e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Przypa=C5=9Bniak?= Date: Wed, 27 Oct 2021 22:12:19 +0200 Subject: [PATCH 17/35] Deleted SSH tests to move them to different branch --- api-mocks/__files/logViewer/logs.json | 10 +++- api-mocks/mappings/endpoints-mapping.json | 2 +- .../cognifide/cogboard/CogboardConstants.kt | 2 + .../com/cognifide/cogboard/ssh/SSHClient.kt | 7 ++- .../cogboard/ssh/auth/SSHAuthData.kt | 1 + .../strategy/BasicAuthSessionStrategy.kt | 2 +- .../strategy/SSHKeyAuthSessionStrategy.kt | 2 +- .../cognifide/cogboard/widget/SSHWidget.kt | 52 ----------------- .../cognifide/cogboard/widget/WidgetIndex.kt | 15 ++++- .../connectionStrategy/ConnectionStrategy.kt | 14 +++++ .../ConnectionStrategyFactory.kt | 29 +++++----- .../HTTPConnectionStrategy.kt | 10 ---- .../HttpConnectionStrategy.kt | 51 ++++++++++++++++ .../SSHConnectionStrategy.kt | 29 +++++++++- .../cogboard/widget/type/LogViewerWidget.kt | 49 +++++++++++----- .../cogboard/widget/type/LogViewerTest.kt | 58 +++++++++++++++++++ 16 files changed, 232 insertions(+), 101 deletions(-) delete mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt delete mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt create mode 100644 cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt diff --git a/api-mocks/__files/logViewer/logs.json b/api-mocks/__files/logViewer/logs.json index b4211a0e..e5c4e740 100644 --- a/api-mocks/__files/logViewer/logs.json +++ b/api-mocks/__files/logViewer/logs.json @@ -1,3 +1,11 @@ { - "logLines": "02:49:12 127.0.0.1 GET / 200\n02:49:35 127.0.0.1 GET /index.html 200\n03:01:06 127.0.0.1 GET /images/sponsered.gif 304\n03:52:36 127.0.0.1 GET /search.php 200\n04:17:03 127.0.0.1 GET /admin/style.css 200\n05:04:54 127.0.0.1 GET /favicon.ico 404\n05:38:07 127.0.0.1 GET /js/ads.js 200\n" + "logLines": [ + "02:49:12 127.0.0.1 GET / 200", + "02:49:35 127.0.0.1 GET /index.html 200", + "03:01:06 127.0.0.1 GET /images/sponsered.gif 304", + "03:52:36 127.0.0.1 GET /search.php 200", + "04:17:03 127.0.0.1 GET /admin/style.css 200", + "05:04:54 127.0.0.1 GET /favicon.ico 404", + "05:38:07 127.0.0.1 GET /js/ads.js 200" + ] } \ No newline at end of file diff --git a/api-mocks/mappings/endpoints-mapping.json b/api-mocks/mappings/endpoints-mapping.json index 8dc85fa6..d98b991d 100644 --- a/api-mocks/mappings/endpoints-mapping.json +++ b/api-mocks/mappings/endpoints-mapping.json @@ -3,7 +3,7 @@ { "request": { "method": "GET", - "url": "/logviewer", + "url": "/log-viewer", "queryParameters": { "lines": { "matches": "^[0-9]+$" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt index 25c07c99..c7ed2383 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt @@ -40,12 +40,14 @@ class CogboardConstants { const val SCHEDULE_DELAY_DEFAULT = 10L // 10 seconds const val SSH_TIMEOUT = 5000 // 5000ms -> 5s const val SSH_HOST = "sshAddress" + const val SSH_PORT = "sshPort" const val SSH_KEY = "sshKey" const val SSH_KEY_PASSPHRASE = "sshKeyPassphrase" const val URL = "url" const val LOG_SOURCE = "logSource" const val LOG_SOURCE_TYPE = "logSourceType" + const val LOG_REQUEST_TYPE = "logRequestType" const val LOG_LINES = "logLines" const val LOG_FILE_PATH = "logFilePath" const val REQUEST_ID = "requestId" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt index f25b0e32..46e8467a 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt @@ -41,7 +41,7 @@ class SSHClient : AbstractVerticle() { } } - private fun tryToConnect(config: JsonObject) { + fun tryToConnect(config: JsonObject) { val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) try { connect(config) @@ -68,8 +68,9 @@ class SSHClient : AbstractVerticle() { private fun initSSHSession(authData: SSHAuthData) { jsch = JSch() - jsch.setKnownHosts("~/.ssh/known_hosts") - val session = SessionStrategyFactory(jsch).create(authData).initSession() + // jsch.setKnownHosts("~/.ssh/known_hosts") for security reasons this should be used + session = SessionStrategyFactory(jsch).create(authData).initSession() + session.setConfig("StrictHostKeyChecking", "no") // not secure session.connect(CogboardConstants.Props.SSH_TIMEOUT) } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt index b2f6690f..446b679f 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt @@ -14,6 +14,7 @@ class SSHAuthData(private val config: JsonObject) { val token = config.getString(CogboardConstants.Props.TOKEN) ?: "" val key = config.getString(CogboardConstants.Props.SSH_KEY) ?: "" val host = config.getString(CogboardConstants.Props.SSH_HOST) ?: "" + val port = config.getInteger(CogboardConstants.Props.SSH_PORT) ?: 22 val authenticationType = fromConfigAuthenticationType() private fun fromConfigAuthenticationType(): AuthenticationType { diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/BasicAuthSessionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/BasicAuthSessionStrategy.kt index 96920b28..119d0293 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/BasicAuthSessionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/BasicAuthSessionStrategy.kt @@ -7,7 +7,7 @@ import com.jcraft.jsch.Session class BasicAuthSessionStrategy(jsch: JSch, authData: SSHAuthData) : SessionStrategy(jsch, authData) { override fun initSession(): Session { - val session = jsch.getSession(authData.user, authData.host) + val session = jsch.getSession(authData.user, authData.host, authData.port) session.setPassword(securityString) return session diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/SSHKeyAuthSessionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/SSHKeyAuthSessionStrategy.kt index 65e7c5b7..07978dae 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/SSHKeyAuthSessionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/strategy/SSHKeyAuthSessionStrategy.kt @@ -11,7 +11,7 @@ class SSHKeyAuthSessionStrategy(jSch: JSch, authData: SSHAuthData) : SessionStra } else { jsch.addIdentity(securityString, authData.password) } - val session = jsch.getSession(authData.user, authData.host) + val session = jsch.getSession(authData.user, authData.host, authData.port) session.setConfig("PreferredAuthentications", "publickey") return session diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt deleted file mode 100644 index 43939a69..00000000 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/SSHWidget.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.cognifide.cogboard.widget - -import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.CogboardConstants.Event -import com.cognifide.cogboard.config.service.BoardsConfigService -import io.vertx.core.Vertx -import io.vertx.core.eventbus.MessageConsumer -import io.vertx.core.json.JsonObject -import java.nio.Buffer - -abstract class SSHWidget( - vertx: Vertx, - config: JsonObject, - serv: BoardsConfigService -) : AsyncWidget(vertx, config, serv) { - val sshKey: String = config.endpointProp(Props.SSH_KEY) - val host: String = config.endpointProp(Props.SSH_HOST) - val logPath: String = config.endpointProp(Props.LOG_FILE_PATH) - val logLines: String = config.endpointProp(Props.LOG_LINES) - private lateinit var sshConsumer: MessageConsumer - - fun registerForSSH(eventBusAddress: String) { - sshConsumer = vertx.eventBus() - .consumer(eventBusAddress) - .handler { - handleSSHResponse(it.body()) - } - } - - abstract fun handleSSHResponse(body: Buffer?) - - fun unregisterFromSSH() { - if (::sshConsumer.isInitialized) { - sshConsumer.unregister() - } - } - - fun sendRequestForLogs(config: JsonObject) { - ensureConfigIsPrepared(config) - vertx.eventBus().send(Event.SSH_COMMAND, config) - } - - private fun ensureConfigIsPrepared(config: JsonObject) { - config.getString(Props.USER) ?: config.put(Props.USER, user) - config.getString(Props.PASSWORD) ?: config.put(Props.PASSWORD, password) - config.getString(Props.TOKEN) ?: config.put(Props.TOKEN, token) - config.getString(Props.SSH_KEY) ?: config.put(Props.SSH_KEY, sshKey) - config.getString(Props.SSH_HOST) ?: config.put(Props.SSH_HOST, host) - config.getString(Props.LOG_FILE_PATH) ?: config.put(Props.LOG_FILE_PATH, logPath) - config.getString(Props.LOG_LINES) ?: config.put(Props.LOG_LINES, logLines) - } -} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt index a73e9feb..e057a29b 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt @@ -3,7 +3,20 @@ package com.cognifide.cogboard.widget import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.storage.VolumeStorageFactory.appConfig -import com.cognifide.cogboard.widget.type.* +import com.cognifide.cogboard.widget.type.AemBundleInfoWidget +import com.cognifide.cogboard.widget.type.AemHealthcheckWidget +import com.cognifide.cogboard.widget.type.BambooDeploymentWidget +import com.cognifide.cogboard.widget.type.BambooPlanWidget +import com.cognifide.cogboard.widget.type.CheckboxWidget +import com.cognifide.cogboard.widget.type.IframeEmbedWidget +import com.cognifide.cogboard.widget.type.JenkinsJobWidget +import com.cognifide.cogboard.widget.type.JiraBucketsWidget +import com.cognifide.cogboard.widget.type.LinkListWidget +import com.cognifide.cogboard.widget.type.WhiteSpaceWidget +import com.cognifide.cogboard.widget.type.ServiceCheckWidget +import com.cognifide.cogboard.widget.type.TextWidget +import com.cognifide.cogboard.widget.type.ToDoListWidget +import com.cognifide.cogboard.widget.type.WorldClockWidget import com.cognifide.cogboard.widget.type.randompicker.RandomPickerWidget import com.cognifide.cogboard.widget.type.sonarqube.SonarQubeWidget import com.cognifide.cogboard.widget.type.zabbix.ZabbixWidget diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt index df672652..74f1025e 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -1,9 +1,23 @@ package com.cognifide.cogboard.widget.connectionStrategy +import com.cognifide.cogboard.CogboardConstants +import com.cognifide.cogboard.http.auth.AuthenticationType import io.vertx.core.Vertx +import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject abstract class ConnectionStrategy(protected val vertx: Vertx) { + protected fun JsonObject.endpointProp(prop: String): String { + return this.getJsonObject(CogboardConstants.Props.ENDPOINT_LOADED)?.getString(prop) ?: "" + } + + protected open fun authenticationTypes(): Set { + return setOf(AuthenticationType.BASIC) + } abstract fun connectAndGetResources(address: String, arguments: JsonObject) + + abstract fun getConsumer(eventBusAddress: String): MessageConsumer<*> + + abstract fun handleResponse(response: Any): String } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index 9fd11187..d728ff15 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -1,30 +1,31 @@ package com.cognifide.cogboard.widget.connectionStrategy import com.cognifide.cogboard.CogboardConstants.ConnectionType +import com.cognifide.cogboard.CogboardConstants.Props import io.vertx.core.Vertx -import java.lang.Exception +import io.vertx.core.json.JsonObject -class ConnectionStrategyFactory { - class ConnectionTypeException : Exception("Unknown strategy type") - class MissingVertxException : Exception("Vertx hasn't been added to factory instance") +class UnknownConnectionTypeException( + message: String? +) : RuntimeException(message) - private lateinit var vertx: Vertx +class ConnectionStrategyFactory( + private var vertx: Vertx, + props: JsonObject +) { + + private val connectionType = props.getString(Props.LOG_SOURCE_TYPE) fun addVertxInstance(vertx: Vertx): ConnectionStrategyFactory { this.vertx = vertx - return this } - fun build(type: String): ConnectionStrategy { - if (!::vertx.isInitialized) { - throw MissingVertxException() - } - - return when (type) { - ConnectionType.HTTP -> HTTPConnectionStrategy(vertx) + fun build(): ConnectionStrategy { + return when (connectionType) { + ConnectionType.HTTP -> HttpConnectionStrategy(vertx) ConnectionType.SSH -> SSHConnectionStrategy(vertx) - else -> throw ConnectionTypeException() + else -> throw UnknownConnectionTypeException("Unknown strategy type") } } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt deleted file mode 100644 index 3d942305..00000000 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HTTPConnectionStrategy.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.cognifide.cogboard.widget.connectionStrategy - -import io.vertx.core.Vertx -import io.vertx.core.json.JsonObject - -class HTTPConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - TODO("Not yet implemented") - } -} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt new file mode 100644 index 00000000..a5728fe4 --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt @@ -0,0 +1,51 @@ +package com.cognifide.cogboard.widget.connectionStrategy + +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.Event +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.GET +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.PUT +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.POST +import com.cognifide.cogboard.CogboardConstants.RequestMethod.Companion.DELETE +import io.vertx.core.Vertx +import io.vertx.core.eventbus.MessageConsumer +import io.vertx.core.json.Json +import io.vertx.core.json.JsonObject + +class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { + override fun connectAndGetResources(address: String, arguments: JsonObject) { + when (arguments.getString(Props.LOG_REQUEST_TYPE, "")) { + GET -> vertx.eventBus().send(Event.HTTP_GET, getProps(arguments)) + PUT -> vertx.eventBus().send(Event.HTTP_PUT, putProps(arguments)) + POST -> vertx.eventBus().send(Event.HTTP_POST, postProps(arguments)) + DELETE -> vertx.eventBus().send(Event.HTTP_DELETE, basicProps(arguments)) + } + } + + override fun getConsumer(eventBusAddress: String): MessageConsumer<*> = + vertx.eventBus().consumer(eventBusAddress) + + override fun handleResponse(response: Any): String = + (response as JsonObject).getString(Props.LOG_LINES) + + private fun basicProps(props: JsonObject): JsonObject = + JsonObject() + .put(Props.URL, props.endpointProp(Props.URL)) + .put(Props.EVENT_ADDRESS, props.endpointProp(Props.EVENT_ADDRESS)) + .put(Props.USER, props.endpointProp(Props.USER)) + .put(Props.PASSWORD, props.endpointProp(Props.PASSWORD)) + .put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + .put(Props.CONTENT_TYPE, props.endpointProp(Props.CONTENT_TYPE)) + + private fun getProps(props: JsonObject): JsonObject = + basicProps(props) + .put(Props.REQUEST_ID, props.getValue(Props.REQUEST_ID, "")) + .put(Props.TOKEN, props.endpointProp(Props.TOKEN)) + + private fun putProps(props: JsonObject): JsonObject = + basicProps(props) + .put(Props.BODY, props.getJsonObject(Props.BODY)) + + private fun postProps(props: JsonObject): JsonObject = + basicProps(props) + .put(Props.BODY, props.getJsonObject(Props.BODY)) +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index 2d250c35..13f59c16 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -1,10 +1,35 @@ package com.cognifide.cogboard.widget.connectionStrategy +import com.cognifide.cogboard.CogboardConstants +import com.cognifide.cogboard.CogboardConstants.Props import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.MessageConsumer +import io.vertx.core.json.Json import io.vertx.core.json.JsonObject +import java.nio.charset.Charset -class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { +open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { override fun connectAndGetResources(address: String, arguments: JsonObject) { - TODO("Not yet implemented") + val config = ensureConfigIsPrepared(arguments) + vertx.eventBus().send(CogboardConstants.Event.SSH_COMMAND, config) + } + + override fun getConsumer(eventBusAddress: String): MessageConsumer<*> = + vertx.eventBus().consumer(eventBusAddress) + + override fun handleResponse(response: Any): String = + (response as Buffer).toString(Charset.defaultCharset()) + + private fun ensureConfigIsPrepared(config: JsonObject): JsonObject { + config.getString(Props.USER) ?: config.put(Props.USER, config.endpointProp(Props.USER)) + config.getString(Props.PASSWORD) ?: config.put(Props.PASSWORD, config.endpointProp(Props.PASSWORD)) + config.getString(Props.TOKEN) ?: config.put(Props.TOKEN, config.endpointProp(Props.TOKEN)) + config.getString(Props.SSH_KEY) ?: config.put(Props.SSH_KEY, config.endpointProp(Props.SSH_KEY)) + config.getString(Props.SSH_HOST) ?: config.put(Props.SSH_HOST, config.endpointProp(Props.SSH_HOST)) + config.getString(Props.LOG_FILE_PATH) ?: config.put(Props.LOG_FILE_PATH, config.endpointProp(Props.LOG_FILE_PATH)) + config.getString(Props.LOG_LINES) ?: config.put(Props.LOG_LINES, config.endpointProp(Props.LOG_LINES)) + config.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + return config } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 67117b02..9b08fd40 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -7,8 +7,11 @@ import com.cognifide.cogboard.widget.Widget import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx +import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject +import java.nio.charset.Charset class LogViewerWidget( vertx: Vertx, @@ -16,20 +19,25 @@ class LogViewerWidget( serv: BoardsConfigService ) : BaseWidget(vertx, config, serv) { private val address = config.getString(Props.LOG_SOURCE) - private val lines = config.getInteger(Props.LOG_LINES) + private val lines = config.getString(Props.LOG_LINES) + private val connectionType = config.getString(Props.LOG_SOURCE_TYPE) - private lateinit var consumer: MessageConsumer - private var connectionStrategy: ConnectionStrategy = determineConnectionStrategy(config) + private var consumer: MessageConsumer<*>? = null + private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() override fun start(): Widget { - consumer = vertx.eventBus() - .consumer(eventBusAddress) - .handler { - handleResponse(it.body()) - } + consumer = connectionStrategy.getConsumer(eventBusAddress) + consumer!!.handler { + handleResponse(it) + } return super.start() } + override fun stop(): Widget { + consumer?.unregister() + return super.stop() + } + override fun updateState() { if (address.isNotBlank()) { connectionStrategy.connectAndGetResources(address, config) @@ -38,24 +46,35 @@ class LogViewerWidget( } } + private fun handleResponse(response: Message<*>) { + val responseBody = response.body() + if (responseBody is JsonObject) { + if (checkAuthorized(responseBody)) { + send(prepareLogs(connectionStrategy.handleResponse(responseBody))) + } + } else { + send(prepareLogs(connectionStrategy.handleResponse(responseBody))) + } + } private fun handleResponse(responseBody: JsonObject) { if (checkAuthorized(responseBody)) { val logs = responseBody.getString(Props.LOG_LINES) - send(prepareLogs(logs)) } } + private fun handleResponse(responseBody: Buffer) { + val logs = prepareLogs(responseBody.toString(Charset.defaultCharset())) + send(logs) + } + private fun prepareLogs(logs: String): String { // TODO return logs } - private fun determineConnectionStrategy(config: JsonObject): ConnectionStrategy { - val type = config.getString(Props.LOG_SOURCE_TYPE) - - return ConnectionStrategyFactory() + private fun determineConnectionStrategy() = + ConnectionStrategyFactory(vertx, config) .addVertxInstance(vertx) - .build(type) - } + .build() } diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt new file mode 100644 index 00000000..896b60b2 --- /dev/null +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt @@ -0,0 +1,58 @@ +package com.cognifide.cogboard.widget.type + +import com.cognifide.cogboard.CogboardConstants.ConnectionType +import com.cognifide.cogboard.CogboardConstants.Props +import com.cognifide.cogboard.CogboardConstants.RequestMethod +import io.vertx.core.buffer.Buffer +import io.vertx.core.eventbus.MessageConsumer +import io.vertx.core.json.JsonObject +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.Mockito.* + +class LogViewerTest: WidgetTestBase() { + + private lateinit var widget: LogViewerWidget + + override fun widgetName(): String { + return "LogViewerWidget" + } + + @BeforeEach + fun initForTest() { + super.init() + } + + @Test + fun `Expect Buffer consumer to be used when type is SSH`() { + val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer + `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + + val config = initWidget() + .put(Props.LOG_SOURCE_TYPE, ConnectionType.SSH) + .put(Props.LOG_SOURCE, "192.168.0.1") + .put(Props.LOG_LINES, "5") + widget = LogViewerWidget(vertx, config, initService()) + + widget.start() + + verify(eventBus).consumer(eq(widget.eventBusAddress)) + } + + @Test + fun `Expect JsonObject consumer to be used when type is HTTP`() { + val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer + `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + + val config = initWidget() + .put(Props.LOG_SOURCE_TYPE, ConnectionType.HTTP) + .put(Props.LOG_REQUEST_TYPE, RequestMethod.GET) + .put(Props.LOG_SOURCE, "192.168.0.1") + .put(Props.LOG_LINES, "5") + widget = LogViewerWidget(vertx, config, initService()) + + widget.start() + + verify(eventBus).consumer(eq(widget.eventBusAddress)) + } +} \ No newline at end of file From 9b2ffcf69b15df907d1fd1e8902ac9fd87e8a478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Przypa=C5=9Bniak?= Date: Wed, 27 Oct 2021 23:26:06 +0200 Subject: [PATCH 18/35] Code review changes [#381] --- .../cogboard/ssh/auth/AuthenticationType.kt | 1 - .../cogboard/ssh/auth/SSHAuthData.kt | 3 --- .../ssh/session/SessionStrategyFactory.kt | 3 +-- .../connectionStrategy/ConnectionStrategy.kt | 2 +- .../ConnectionStrategyFactory.kt | 15 ++++++----- .../HttpConnectionStrategy.kt | 2 +- .../SSHConnectionStrategy.kt | 27 +++++++++++-------- .../cogboard/widget/type/LogViewerWidget.kt | 19 ++++--------- 8 files changed, 32 insertions(+), 40 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/AuthenticationType.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/AuthenticationType.kt index abca29a4..1dfa6410 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/AuthenticationType.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/AuthenticationType.kt @@ -2,6 +2,5 @@ package com.cognifide.cogboard.ssh.auth enum class AuthenticationType { BASIC, - TOKEN, SSH_KEY } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt index 446b679f..ee0d41ea 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt @@ -2,7 +2,6 @@ package com.cognifide.cogboard.ssh.auth import com.cognifide.cogboard.CogboardConstants import com.cognifide.cogboard.ssh.auth.AuthenticationType.BASIC -import com.cognifide.cogboard.ssh.auth.AuthenticationType.TOKEN import com.cognifide.cogboard.ssh.auth.AuthenticationType.SSH_KEY import io.vertx.core.json.Json import io.vertx.core.json.JsonArray @@ -29,7 +28,6 @@ class SSHAuthData(private val config: JsonObject) { private fun hasAuthTypeCorrectCredentials(authType: AuthenticationType): Boolean = when { - authType == TOKEN && user.isNotBlank() && token.isNotBlank() -> true authType == SSH_KEY && key.isNotBlank() -> true else -> authType == BASIC && user.isNotBlank() && password.isNotBlank() } @@ -37,7 +35,6 @@ class SSHAuthData(private val config: JsonObject) { fun getAuthenticationString(): String = when (authenticationType) { BASIC -> config.getString(CogboardConstants.Props.PASSWORD) - TOKEN -> config.getString(CogboardConstants.Props.TOKEN) SSH_KEY -> config.getString(CogboardConstants.Props.SSH_KEY) } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/SessionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/SessionStrategyFactory.kt index 88b54dd2..cc7df076 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/SessionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/session/SessionStrategyFactory.kt @@ -1,7 +1,6 @@ package com.cognifide.cogboard.ssh.session import com.cognifide.cogboard.ssh.auth.AuthenticationType.BASIC -import com.cognifide.cogboard.ssh.auth.AuthenticationType.TOKEN import com.cognifide.cogboard.ssh.auth.AuthenticationType.SSH_KEY import com.cognifide.cogboard.ssh.auth.SSHAuthData import com.cognifide.cogboard.ssh.session.strategy.BasicAuthSessionStrategy @@ -12,7 +11,7 @@ import com.jcraft.jsch.JSch class SessionStrategyFactory(private val jsch: JSch) { fun create(authData: SSHAuthData): SessionStrategy = when (authData.authenticationType) { - BASIC, TOKEN -> { + BASIC -> { BasicAuthSessionStrategy(jsch, authData) } SSH_KEY -> { diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt index 74f1025e..fcf425be 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -15,7 +15,7 @@ abstract class ConnectionStrategy(protected val vertx: Vertx) { return setOf(AuthenticationType.BASIC) } - abstract fun connectAndGetResources(address: String, arguments: JsonObject) + abstract fun sendRequest(address: String, arguments: JsonObject) abstract fun getConsumer(eventBusAddress: String): MessageConsumer<*> diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index d728ff15..2e91d756 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -1,14 +1,11 @@ package com.cognifide.cogboard.widget.connectionStrategy -import com.cognifide.cogboard.CogboardConstants.ConnectionType +import com.cognifide.cogboard.CogboardConstants.ConnectionType.Companion.HTTP +import com.cognifide.cogboard.CogboardConstants.ConnectionType.Companion.SSH import com.cognifide.cogboard.CogboardConstants.Props import io.vertx.core.Vertx import io.vertx.core.json.JsonObject -class UnknownConnectionTypeException( - message: String? -) : RuntimeException(message) - class ConnectionStrategyFactory( private var vertx: Vertx, props: JsonObject @@ -23,9 +20,13 @@ class ConnectionStrategyFactory( fun build(): ConnectionStrategy { return when (connectionType) { - ConnectionType.HTTP -> HttpConnectionStrategy(vertx) - ConnectionType.SSH -> SSHConnectionStrategy(vertx) + HTTP -> HttpConnectionStrategy(vertx) + SSH -> SSHConnectionStrategy(vertx) else -> throw UnknownConnectionTypeException("Unknown strategy type") } } } + +class UnknownConnectionTypeException( + message: String? +) : RuntimeException(message) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt index a5728fe4..f7cff289 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt @@ -12,7 +12,7 @@ import io.vertx.core.json.Json import io.vertx.core.json.JsonObject class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { + override fun sendRequest(address: String, arguments: JsonObject) { when (arguments.getString(Props.LOG_REQUEST_TYPE, "")) { GET -> vertx.eventBus().send(Event.HTTP_GET, getProps(arguments)) PUT -> vertx.eventBus().send(Event.HTTP_PUT, putProps(arguments)) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index 13f59c16..c8831679 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -10,8 +10,8 @@ import io.vertx.core.json.JsonObject import java.nio.charset.Charset open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { - override fun connectAndGetResources(address: String, arguments: JsonObject) { - val config = ensureConfigIsPrepared(arguments) + override fun sendRequest(address: String, arguments: JsonObject) { + val config = prepareConfig(arguments) vertx.eventBus().send(CogboardConstants.Event.SSH_COMMAND, config) } @@ -21,15 +21,20 @@ open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { override fun handleResponse(response: Any): String = (response as Buffer).toString(Charset.defaultCharset()) - private fun ensureConfigIsPrepared(config: JsonObject): JsonObject { - config.getString(Props.USER) ?: config.put(Props.USER, config.endpointProp(Props.USER)) - config.getString(Props.PASSWORD) ?: config.put(Props.PASSWORD, config.endpointProp(Props.PASSWORD)) - config.getString(Props.TOKEN) ?: config.put(Props.TOKEN, config.endpointProp(Props.TOKEN)) - config.getString(Props.SSH_KEY) ?: config.put(Props.SSH_KEY, config.endpointProp(Props.SSH_KEY)) - config.getString(Props.SSH_HOST) ?: config.put(Props.SSH_HOST, config.endpointProp(Props.SSH_HOST)) - config.getString(Props.LOG_FILE_PATH) ?: config.put(Props.LOG_FILE_PATH, config.endpointProp(Props.LOG_FILE_PATH)) - config.getString(Props.LOG_LINES) ?: config.put(Props.LOG_LINES, config.endpointProp(Props.LOG_LINES)) - config.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + private fun prepareConfig(config: JsonObject): JsonObject { + val tmpConfig = prepareConfigLines(config = config, + Props.USER, Props.PASSWORD, Props.TOKEN, Props.SSH_HOST, Props.SSH_KEY, Props.SSH_PORT, + Props.LOG_FILE_PATH, Props.LOG_LINES, Props.SSH_KEY_PASSPHRASE + ) + + tmpConfig.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + return tmpConfig + } + + private fun prepareConfigLines(config: JsonObject, vararg fields: String): JsonObject { + for (field in fields) { + config.getString(field) ?: config.put(field, config.endpointProp(field)) + } return config } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 9b08fd40..438e3e29 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -7,11 +7,9 @@ import com.cognifide.cogboard.widget.Widget import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx -import io.vertx.core.buffer.Buffer import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject -import java.nio.charset.Charset class LogViewerWidget( vertx: Vertx, @@ -40,7 +38,7 @@ class LogViewerWidget( override fun updateState() { if (address.isNotBlank()) { - connectionStrategy.connectAndGetResources(address, config) + connectionStrategy.sendRequest(address, config) } else { sendConfigurationError("Endpoint URL is blank") } @@ -49,25 +47,18 @@ class LogViewerWidget( private fun handleResponse(response: Message<*>) { val responseBody = response.body() if (responseBody is JsonObject) { - if (checkAuthorized(responseBody)) { - send(prepareLogs(connectionStrategy.handleResponse(responseBody))) - } + handleHttpResponse(responseBody) } else { send(prepareLogs(connectionStrategy.handleResponse(responseBody))) } } - private fun handleResponse(responseBody: JsonObject) { + + private fun handleHttpResponse(responseBody: JsonObject) { if (checkAuthorized(responseBody)) { - val logs = responseBody.getString(Props.LOG_LINES) - send(prepareLogs(logs)) + send(prepareLogs(connectionStrategy.handleResponse(responseBody))) } } - private fun handleResponse(responseBody: Buffer) { - val logs = prepareLogs(responseBody.toString(Charset.defaultCharset())) - send(logs) - } - private fun prepareLogs(logs: String): String { // TODO return logs From 82945f29f7f05407ad09e3169387124bed1a39ca Mon Sep 17 00:00:00 2001 From: clmrv Date: Tue, 2 Nov 2021 20:04:38 +0100 Subject: [PATCH 19/35] Add ssh to credentials tests, Turn off LogViewer backend --- .../cogboard/config/EndpointLoader.kt | 1 + .../cogboard/widget/type/LogViewerWidget.kt | 87 ++++++------- .../main/resources/initData/credentials.json | 3 +- .../cognifide/cogboard/config/EndpointTest.kt | 10 +- .../cogboard/widget/type/LogViewerTest.kt | 116 +++++++++--------- .../cogboard/config/credentials-test.json | 6 +- 6 files changed, 118 insertions(+), 105 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt index 97609a8c..0165b1c7 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt @@ -31,6 +31,7 @@ class EndpointLoader( this.put(Props.USER, credentials.getString(Props.USER) ?: "") this.put(Props.PASSWORD, credentials.getString(Props.PASSWORD) ?: "") this.put(Props.TOKEN, credentials.getString(Props.TOKEN) ?: "") + this.put(Props.SSH_KEY, credentials.getString(Props.SSH_KEY) ?: "") } } return this diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 438e3e29..82c7d1cf 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -3,11 +3,7 @@ package com.cognifide.cogboard.widget.type import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.widget.BaseWidget -import com.cognifide.cogboard.widget.Widget -import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy -import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx -import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject @@ -20,52 +16,59 @@ class LogViewerWidget( private val lines = config.getString(Props.LOG_LINES) private val connectionType = config.getString(Props.LOG_SOURCE_TYPE) + private val user: String = config.endpointProp(Props.USER) + private val password: String = config.endpointProp(Props.PASSWORD) + private val token: String = config.endpointProp(Props.TOKEN) + private val sshKey: String = config.endpointProp(Props.SSH_KEY) + private val url: String = config.endpointProp(Props.URL) + private val publicUrl: String = config.endpointProp(Props.PUBLIC_URL).ifBlank { url } + private var consumer: MessageConsumer<*>? = null - private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() + // private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() - override fun start(): Widget { - consumer = connectionStrategy.getConsumer(eventBusAddress) - consumer!!.handler { - handleResponse(it) - } - return super.start() - } + // override fun start(): Widget { + // consumer = connectionStrategy.getConsumer(eventBusAddress) + // consumer!!.handler { + // handleResponse(it) + // } + // return super.start() + // } - override fun stop(): Widget { - consumer?.unregister() - return super.stop() - } + // override fun stop(): Widget { + // consumer?.unregister() + // return super.stop() + // } override fun updateState() { - if (address.isNotBlank()) { - connectionStrategy.sendRequest(address, config) - } else { - sendConfigurationError("Endpoint URL is blank") - } + // if (address.isNotBlank()) { + // connectionStrategy.sendRequest(address, config) + // } else { + // sendConfigurationError("Endpoint URL is blank") + // } } - private fun handleResponse(response: Message<*>) { - val responseBody = response.body() - if (responseBody is JsonObject) { - handleHttpResponse(responseBody) - } else { - send(prepareLogs(connectionStrategy.handleResponse(responseBody))) - } - } + // private fun handleResponse(response: Message<*>) { + // val responseBody = response.body() + // if (responseBody is JsonObject) { + // handleHttpResponse(responseBody) + // } else { + // send(prepareLogs(connectionStrategy.handleResponse(responseBody))) + // } + // } - private fun handleHttpResponse(responseBody: JsonObject) { - if (checkAuthorized(responseBody)) { - send(prepareLogs(connectionStrategy.handleResponse(responseBody))) - } - } + // private fun handleHttpResponse(responseBody: JsonObject) { + // if (checkAuthorized(responseBody)) { + // send(prepareLogs(connectionStrategy.handleResponse(responseBody))) + // } + // } - private fun prepareLogs(logs: String): String { - // TODO - return logs - } + // private fun prepareLogs(logs: String): String { + // // TODO + // return logs + // } - private fun determineConnectionStrategy() = - ConnectionStrategyFactory(vertx, config) - .addVertxInstance(vertx) - .build() + // private fun determineConnectionStrategy() = + // ConnectionStrategyFactory(vertx, config) + // .addVertxInstance(vertx) + // .build() } diff --git a/cogboard-app/src/main/resources/initData/credentials.json b/cogboard-app/src/main/resources/initData/credentials.json index db175e83..b3e4b8e7 100644 --- a/cogboard-app/src/main/resources/initData/credentials.json +++ b/cogboard-app/src/main/resources/initData/credentials.json @@ -2,10 +2,11 @@ "credentials": [ { "token": "", + "sshKey": "", "password": "admin", "user": "admin", "label": "Zabbix", "id": "credential1" } ] -} \ No newline at end of file +} diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt index 2705faf5..fbfa08da 100644 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt @@ -37,10 +37,12 @@ internal class EndpointTest { assert(validEndpoint.containsKey("user")) assert(validEndpoint.containsKey("password")) assert(validEndpoint.containsKey("token")) + assert(validEndpoint.containsKey("sshKey")) assert(invalidEndpoint.containsKey("user")) assert(invalidEndpoint.containsKey("password")) assert(invalidEndpoint.containsKey("token")) + assert(invalidEndpoint.containsKey("sshKey")) } @Test @@ -48,6 +50,7 @@ internal class EndpointTest { assertEquals("user1", validEndpoint.getString("user")) assertEquals("password1", validEndpoint.getString("password")) assertEquals("token1", validEndpoint.getString("token")) + assertEquals("key1", validEndpoint.getString("sshKey")) } @Test @@ -55,6 +58,7 @@ internal class EndpointTest { assertEquals("", invalidEndpoint.getString("user")) assertEquals("", invalidEndpoint.getString("password")) assertEquals("", invalidEndpoint.getString("token")) + assertEquals("", invalidEndpoint.getString("sshKey")) } @Test @@ -67,7 +71,8 @@ internal class EndpointTest { "publicUrl" : "Public Url", "user" : "user1", "password" : "password1", - "token" : "token1" + "token" : "token1", + "sshKey": "key1" } """) @@ -83,7 +88,8 @@ internal class EndpointTest { "url" : "url", "user" : "", "password" : "", - "token" : "" + "token" : "", + "sshKey" : "" } """) diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt index 896b60b2..afbee65b 100644 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt @@ -1,58 +1,58 @@ -package com.cognifide.cogboard.widget.type - -import com.cognifide.cogboard.CogboardConstants.ConnectionType -import com.cognifide.cogboard.CogboardConstants.Props -import com.cognifide.cogboard.CogboardConstants.RequestMethod -import io.vertx.core.buffer.Buffer -import io.vertx.core.eventbus.MessageConsumer -import io.vertx.core.json.JsonObject -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.mockito.Mockito.* - -class LogViewerTest: WidgetTestBase() { - - private lateinit var widget: LogViewerWidget - - override fun widgetName(): String { - return "LogViewerWidget" - } - - @BeforeEach - fun initForTest() { - super.init() - } - - @Test - fun `Expect Buffer consumer to be used when type is SSH`() { - val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer - `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) - - val config = initWidget() - .put(Props.LOG_SOURCE_TYPE, ConnectionType.SSH) - .put(Props.LOG_SOURCE, "192.168.0.1") - .put(Props.LOG_LINES, "5") - widget = LogViewerWidget(vertx, config, initService()) - - widget.start() - - verify(eventBus).consumer(eq(widget.eventBusAddress)) - } - - @Test - fun `Expect JsonObject consumer to be used when type is HTTP`() { - val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer - `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) - - val config = initWidget() - .put(Props.LOG_SOURCE_TYPE, ConnectionType.HTTP) - .put(Props.LOG_REQUEST_TYPE, RequestMethod.GET) - .put(Props.LOG_SOURCE, "192.168.0.1") - .put(Props.LOG_LINES, "5") - widget = LogViewerWidget(vertx, config, initService()) - - widget.start() - - verify(eventBus).consumer(eq(widget.eventBusAddress)) - } -} \ No newline at end of file +// package com.cognifide.cogboard.widget.type + +// import com.cognifide.cogboard.CogboardConstants.ConnectionType +// import com.cognifide.cogboard.CogboardConstants.Props +// import com.cognifide.cogboard.CogboardConstants.RequestMethod +// import io.vertx.core.buffer.Buffer +// import io.vertx.core.eventbus.MessageConsumer +// import io.vertx.core.json.JsonObject +// import org.junit.jupiter.api.BeforeEach +// import org.junit.jupiter.api.Test +// import org.mockito.Mockito.* + +// class LogViewerTest: WidgetTestBase() { + +// private lateinit var widget: LogViewerWidget + +// override fun widgetName(): String { +// return "LogViewerWidget" +// } + +// @BeforeEach +// fun initForTest() { +// super.init() +// } + +// @Test +// fun `Expect Buffer consumer to be used when type is SSH`() { +// val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer +// `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + +// val config = initWidget() +// .put(Props.LOG_SOURCE_TYPE, ConnectionType.SSH) +// .put(Props.LOG_SOURCE, "192.168.0.1") +// .put(Props.LOG_LINES, "5") +// widget = LogViewerWidget(vertx, config, initService()) + +// widget.start() + +// verify(eventBus).consumer(eq(widget.eventBusAddress)) +// } + +// @Test +// fun `Expect JsonObject consumer to be used when type is HTTP`() { +// val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer +// `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + +// val config = initWidget() +// .put(Props.LOG_SOURCE_TYPE, ConnectionType.HTTP) +// .put(Props.LOG_REQUEST_TYPE, RequestMethod.GET) +// .put(Props.LOG_SOURCE, "192.168.0.1") +// .put(Props.LOG_LINES, "5") +// widget = LogViewerWidget(vertx, config, initService()) + +// widget.start() + +// verify(eventBus).consumer(eq(widget.eventBusAddress)) +// } +// } \ No newline at end of file diff --git a/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json b/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json index 9cdcfe54..87cb0991 100644 --- a/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json +++ b/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json @@ -5,14 +5,16 @@ "label": "My Credentials 1", "user": "user1", "password": "password1", - "token": "token1" + "token": "token1", + "sshKey": "key1" }, { "id": "credentials2", "label": "My Credentials 2", "user": "user2", "password": "password2", - "token": "token2" + "token": "token2", + "sshKey": "key2" } ] } From 7178432254c4d11022571af67f86875f6e049bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Tue, 2 Nov 2021 20:38:03 +0100 Subject: [PATCH 20/35] Change text fo file --- .../widgets/dialogFields/FileTextInput.js | 72 +++++++++++++++++++ .../components/widgets/dialogFields/index.js | 3 +- .../components/widgets/dialogFields/styled.js | 33 ++++++++- 3 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js diff --git a/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js b/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js new file mode 100644 index 00000000..da018a07 --- /dev/null +++ b/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js @@ -0,0 +1,72 @@ +import React, { useState } from 'react'; + +import { Button, InputLabel } from '@material-ui/core'; +import { StyledValidationMessages } from '../../WidgetForm/styled'; +import { + DeleteButton, + StyledHorizontalStack, + StyledLabel, + StyledVerticalStack +} from './styled'; + +const FileTextInput = ({ + error, + dataCy, + values, + label, + value, + onChange, + ...other +}) => { + const [filename, setFilename] = useState(''); + + const getFileContents = async e => { + e.preventDefault(); + const file = e.target.files[0]; + const reader = new FileReader(); + reader.onload = async e => { + const text = e.target.result; + let event = e; + event.target.value = text; + onChange(event); + alert(text); + console.log(text); + }; + reader.readAsText(file); + setFilename(file.name); + }; + + const deleteFile = e => { + e.preventDefault(); + setFilename(''); + let event = e; + event.target.value = ''; + onChange(event); + }; + + const fileInfo = + filename === '' ? null : ( + +

{filename}

+ deleteFile(e)}> + Delete + +
+ ); + + return ( + + SSH Key + + + {fileInfo} + + + + ); +}; + +export default FileTextInput; diff --git a/cogboard-webapp/src/components/widgets/dialogFields/index.js b/cogboard-webapp/src/components/widgets/dialogFields/index.js index 08351814..52a8f313 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/index.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/index.js @@ -37,6 +37,7 @@ import RangeSlider from './RangeSlider'; import LinkListInput from './LinkListInput'; import ToDoListInput from './ToDoListinput'; import WidgetTypeField from './WidgetTypeField'; +import FileTextInput from './FileTextInput'; const dialogFields = { LabelField: { @@ -101,7 +102,7 @@ const dialogFields = { validator: () => string() }, SSHKeyField: { - component: MultilineTextInput, + component: FileTextInput, name: 'sshKey', label: 'SSH Private Key', validator: () => diff --git a/cogboard-webapp/src/components/widgets/dialogFields/styled.js b/cogboard-webapp/src/components/widgets/dialogFields/styled.js index 4d56781d..593893e8 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/styled.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/styled.js @@ -2,7 +2,7 @@ import styled from '@emotion/styled/macro'; import NumberInput from './NumberInput'; import IntegerInput from './IntegerInput'; import { COLORS } from '../../../constants'; -import { Box, Input, Fab, List, FormControl } from '@material-ui/core'; +import { Box, Input, Fab, List, FormControl, Button } from '@material-ui/core'; export const StyledNumberInput = styled(NumberInput)` flex-basis: calc(50% - 18px); @@ -152,3 +152,34 @@ export const StyledMultiLineWrapper = styled.div` flex: 1 0 auto; } `; + +export const StyledHorizontalStack = styled.div` + display: flex; + flex-direction: row; + gap: 12px; +`; + +export const StyledVerticalStack = styled.div` + display: flex; + flex-direction: column; + gap: 12px; +`; + +export const StyledLabel = styled.p` + font-size: 1rem; + margin: 0; + color: rgba(255, 255, 255, 0.7); + transform: translate(0, 1.5px) scale(0.75); + transform-origin: top left; + font-weight: 400; + line-height: 1; + letter-spacing: 0.00938em; +`; + +export const DeleteButton = styled(Button)` + background-color: ${COLORS.RED}; + + &:hover { + background-color: ${COLORS.DARK_RED}; + } +`; From 622953c9231c6c5c27d61037b1f729a9f0ddc6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ambroz=CC=87y?= Date: Tue, 2 Nov 2021 21:52:48 +0100 Subject: [PATCH 21/35] Add SSH Key passphrase --- .../config/controller/CredentialsController.kt | 1 + .../cognifide/cogboard/config/model/Credential.kt | 3 ++- .../src/components/CredentialForm/index.js | 6 ++++-- .../widgets/dialogFields/FileTextInput.js | 14 ++------------ .../src/components/widgets/dialogFields/index.js | 8 +++++++- .../cypress/fixtures/credentialsEndpoints.js | 1 + .../cypress-tests/cypress/support/credential.js | 14 ++++++++++++-- 7 files changed, 29 insertions(+), 18 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt index d2cdc379..e9288c04 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/controller/CredentialsController.kt @@ -38,6 +38,7 @@ class CredentialsController : AbstractVerticle() { private fun JsonObject.filterSensitiveData(): JsonObject { this.remove(Props.PASSWORD) this.remove(Props.SSH_KEY) + this.remove(Props.SSH_KEY_PASSPHRASE) return this } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt index ddb05261..6727bf40 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/model/Credential.kt @@ -6,5 +6,6 @@ data class Credential( val user: String, val password: String?, val token: String?, - val sshKey: String? + val sshKey: String?, + val sshKeyPassphrase: String? ) diff --git a/cogboard-webapp/src/components/CredentialForm/index.js b/cogboard-webapp/src/components/CredentialForm/index.js index 9c80150b..bd8757fb 100644 --- a/cogboard-webapp/src/components/CredentialForm/index.js +++ b/cogboard-webapp/src/components/CredentialForm/index.js @@ -23,7 +23,8 @@ const CredentialsForm = ({ 'PasswordField', 'PasswordConfirmationField', 'TokenField', - 'SSHKeyField' + 'SSHKeyField', + 'SSHKeyPassphraseField' ]; const constraints = { @@ -84,7 +85,8 @@ CredentialsForm.defaultProps = { password: '', confirmationPassword: '', token: '', - sshKey: '' + sshKey: '', + sshKeyPassphrase: '' }; export default CredentialsForm; diff --git a/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js b/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js index da018a07..0124f09a 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/FileTextInput.js @@ -1,6 +1,6 @@ import React, { useState } from 'react'; -import { Button, InputLabel } from '@material-ui/core'; +import { Button } from '@material-ui/core'; import { StyledValidationMessages } from '../../WidgetForm/styled'; import { DeleteButton, @@ -9,15 +9,7 @@ import { StyledVerticalStack } from './styled'; -const FileTextInput = ({ - error, - dataCy, - values, - label, - value, - onChange, - ...other -}) => { +const FileTextInput = ({ error, dataCy, onChange }) => { const [filename, setFilename] = useState(''); const getFileContents = async e => { @@ -29,8 +21,6 @@ const FileTextInput = ({ let event = e; event.target.value = text; onChange(event); - alert(text); - console.log(text); }; reader.readAsText(file); setFilename(file.name); diff --git a/cogboard-webapp/src/components/widgets/dialogFields/index.js b/cogboard-webapp/src/components/widgets/dialogFields/index.js index 52a8f313..c5891e03 100644 --- a/cogboard-webapp/src/components/widgets/dialogFields/index.js +++ b/cogboard-webapp/src/components/widgets/dialogFields/index.js @@ -111,11 +111,17 @@ const dialogFields = { message: vm.SSH_KEY_BEGIN, excludeEmptyString: true }) - .matches('\n-----END ([A-Z]{1,} )*PRIVATE KEY-----$', { + .matches('\n-----END ([A-Z]{1,} )*PRIVATE KEY-----\n$', { message: vm.SSH_KEY_END, excludeEmptyString: true }) }, + SSHKeyPassphraseField: { + component: PasswordInput, + name: 'sshKeyPassphrase', + label: 'SSH Private Key Passphrase', + validator: () => string() + }, PublicURL: { component: TextInput, name: 'publicUrl', diff --git a/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js b/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js index b4f05860..0f1194d8 100644 --- a/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js +++ b/functional/cypress-tests/cypress/fixtures/credentialsEndpoints.js @@ -6,6 +6,7 @@ export const badCredentials = () => { user: 'xxxxxxxxxxxxxxxxxxxxxxxxxx', label: ' ', sshKey: 'xxx', + sshKeyPassphrase: '' }; }; diff --git a/functional/cypress-tests/cypress/support/credential.js b/functional/cypress-tests/cypress/support/credential.js index a757c8f9..e2db01bf 100644 --- a/functional/cypress-tests/cypress/support/credential.js +++ b/functional/cypress-tests/cypress/support/credential.js @@ -69,6 +69,17 @@ class Credentials { return this; } + applySSHKeyPassphrase(config) { + if (config !== undefined) { + this.config = config; + } + cy.get('[data-cy="credential-form-auth-ssh-key-passphrase-input"]') + .clear() + .type(this.config.sshKeyPassphrase) + .blur(); + return this; + } + save() { cy.get('[data-cy="credential-form-submit-button"]').click(); return this; @@ -88,8 +99,7 @@ class Credentials { } assertErrorMessageVisible(message, dataCYName) { - cy - .contains(`[data-cy^="${dataCYName}"]`, message) + cy.contains(`[data-cy^="${dataCYName}"]`, message) .scrollIntoView() .should('is.visible'); return this; From c46718272fc4b75ecd13af75fbceed76540a60df Mon Sep 17 00:00:00 2001 From: clmrv Date: Tue, 2 Nov 2021 22:46:39 +0100 Subject: [PATCH 22/35] Move template logs to backend --- .../cogboard/widget/type/LogViewerWidget.kt | 40 +++++++++ .../types/LogViewerWidget/LogList/index.js | 85 ++----------------- .../widgets/types/LogViewerWidget/index.js | 22 +++-- 3 files changed, 64 insertions(+), 83 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 82c7d1cf..0888998b 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -6,6 +6,7 @@ import com.cognifide.cogboard.widget.BaseWidget import io.vertx.core.Vertx import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject +import io.vertx.core.json.JsonArray class LogViewerWidget( vertx: Vertx, @@ -39,12 +40,51 @@ class LogViewerWidget( // return super.stop() // } + private val logs = createTemplateLogs(20) override fun updateState() { // if (address.isNotBlank()) { // connectionStrategy.sendRequest(address, config) // } else { // sendConfigurationError("Endpoint URL is blank") // } + + send(JsonObject().put("logs", logs)) + } + + private fun createTemplateLogs(n: Int): JsonArray { + val types = arrayOf("info", "error", "debug", "success", "warn") + val logs = JsonArray() + + for (i in 1..n) { + logs.add(createTemplateLog(types[i % types.size])) + } + return logs + } + + private fun createTemplateLog(type: String): JsonObject { + return JsonObject(""" + { + "type": "$type", + "date": "2021-04-22 14:08:37", + "additionalData": { + "ID": "123456", + "Type": "sys", + "IP address": "127.0.0.1", + "Port": "27017" + }, + "variableData": { + "template": ["Provider", "Message"], + "header": [ + "mongodb.log", + "Expected corresponding JSX closing tag for ." + ], + "description": [ + "provider desc", + "SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6)" + ] + } + } + """) } // private fun handleResponse(response: Message<*>) { diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js index 5ff41576..16654925 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js @@ -12,28 +12,8 @@ import { import getGridTemplate from './helpers'; const testLogTemplate = ['Provider', 'Message']; -const testData = { - date: '2021-04-22 14:08:37', - additionalData: { - ID: '123456', - Type: 'sys', - 'IP address': '127.0.0.1', - Port: '27017' - }, - variableData: { - template: testLogTemplate, - header: [ - 'mongodb.log', - 'Expected corresponding JSX closing tag for .' - ], - description: [ - 'provider desc', - 'SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6)' - ] - } -}; -export default function LogList() { +export default function LogList({ children }) { const theme = useTheme(); const VariableLogListHeader = () => ( @@ -54,61 +34,14 @@ export default function LogList() { - {/* static presentation */} - - - - - - - - - - + {children.map(log => ( + + ))} ); diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js index 512f3328..4a54c049 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js @@ -1,15 +1,23 @@ -import React from 'react'; +import React, { useEffect } from 'react'; +import { shallowEqual, useSelector } from 'react-redux'; import { number, string } from 'prop-types'; import Toolbar from './Toolbar'; import LogList from './LogList'; import { Container } from './styled'; -const LogViewerWidget = () => ( - - - - -); +const LogViewerWidget = ({ id }) => { + const widgetData = useSelector( + ({ widgets }) => widgets.widgetsById[id], + shallowEqual + ); + useEffect(() => console.log(widgetData), [widgetData]); + return ( + + + {widgetData.content.logs} + + ); +}; LogViewerWidget.propTypes = { endpoint: string, From 7a341e74b16a780db612c80a4fd4d1457632f1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Przypa=C5=9Bniak?= Date: Wed, 3 Nov 2021 00:30:44 +0100 Subject: [PATCH 23/35] Adjustments for communication with front-end --- .../com/cognifide/cogboard/ssh/SSHClient.kt | 3 +- .../ConnectionStrategyFactory.kt | 35 ++++- .../SSHConnectionStrategy.kt | 3 +- .../cogboard/widget/type/LogViewerWidget.kt | 6 +- .../cognifide/cogboard/ssh/SSHClientTest.kt | 125 ------------------ .../cogboard/widget/type/LogViewerTest.kt | 13 +- .../com/cognifide/cogboard/ssh/id_rsa | 39 ------ 7 files changed, 46 insertions(+), 178 deletions(-) delete mode 100644 cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt delete mode 100644 cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt index 46e8467a..433a6a09 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt @@ -42,11 +42,12 @@ class SSHClient : AbstractVerticle() { } fun tryToConnect(config: JsonObject) { - val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) + try { connect(config) } catch (e: JSchException) { LOGGER.error(e.message) + val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) vertx.eventBus().send(eventBusAddress, e) } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index 2e91d756..cc92d9a8 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -5,20 +5,49 @@ import com.cognifide.cogboard.CogboardConstants.ConnectionType.Companion.SSH import com.cognifide.cogboard.CogboardConstants.Props import io.vertx.core.Vertx import io.vertx.core.json.JsonObject +import java.net.URI class ConnectionStrategyFactory( - private var vertx: Vertx, - props: JsonObject + config: JsonObject, + uri: String ) { + private val connectionType: String + private lateinit var vertx: Vertx - private val connectionType = props.getString(Props.LOG_SOURCE_TYPE) + init { + connectionType = determineConnectionType(uri, config) + } fun addVertxInstance(vertx: Vertx): ConnectionStrategyFactory { this.vertx = vertx return this } + private fun determineConnectionType(uri: String, config: JsonObject): String { + val url = URI.create(uri) + return when (url.scheme) { + "http", "https" -> HTTP + "ssh" -> { + prepareSshConfig(url, config) + SSH + } + else -> { + throw UnknownConnectionTypeException("Unknown strategy type") + } + } + } + + private fun prepareSshConfig(uri: URI, config: JsonObject) { + config.put(Props.SSH_HOST, uri.host) + uri.port.let { + if (it != -1) config.put(Props.SSH_PORT, uri.port) + } + } + fun build(): ConnectionStrategy { + if (!::vertx.isInitialized) { + throw RuntimeException("Vertx instance not passed to builder") + } return when (connectionType) { HTTP -> HttpConnectionStrategy(vertx) SSH -> SSHConnectionStrategy(vertx) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index c8831679..1be55656 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -23,8 +23,7 @@ open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { private fun prepareConfig(config: JsonObject): JsonObject { val tmpConfig = prepareConfigLines(config = config, - Props.USER, Props.PASSWORD, Props.TOKEN, Props.SSH_HOST, Props.SSH_KEY, Props.SSH_PORT, - Props.LOG_FILE_PATH, Props.LOG_LINES, Props.SSH_KEY_PASSPHRASE + Props.USER, Props.PASSWORD, Props.TOKEN, Props.SSH_KEY, Props.SSH_KEY_PASSPHRASE ) tmpConfig.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 438e3e29..16392012 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -16,9 +16,7 @@ class LogViewerWidget( config: JsonObject, serv: BoardsConfigService ) : BaseWidget(vertx, config, serv) { - private val address = config.getString(Props.LOG_SOURCE) - private val lines = config.getString(Props.LOG_LINES) - private val connectionType = config.getString(Props.LOG_SOURCE_TYPE) + private val address = config.endpointProp(Props.URL) private var consumer: MessageConsumer<*>? = null private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() @@ -65,7 +63,7 @@ class LogViewerWidget( } private fun determineConnectionStrategy() = - ConnectionStrategyFactory(vertx, config) + ConnectionStrategyFactory(config, address) .addVertxInstance(vertx) .build() } diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt deleted file mode 100644 index 2c260557..00000000 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/ssh/SSHClientTest.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.cognifide.cogboard.ssh - -import com.cognifide.cogboard.CogboardConstants -import com.cognifide.cogboard.ssh.auth.AuthenticationType -import com.jcraft.jsch.JSchException -import io.vertx.core.Vertx -import io.vertx.core.buffer.Buffer -import io.vertx.core.eventbus.EventBus -import io.vertx.core.json.Json -import io.vertx.core.json.JsonObject -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.ArgumentCaptor -import org.mockito.ArgumentMatchers.* -import org.mockito.Captor -import org.mockito.Mock -import org.mockito.Mockito.* -import org.mockito.MockitoAnnotations.initMocks -import org.mockito.junit.jupiter.MockitoExtension - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@ExtendWith(MockitoExtension::class) -class SSHClientTest { - private lateinit var sshClient: SSHClient - - @Captor - private lateinit var bufferCaptor: ArgumentCaptor - - @Captor - private lateinit var exceptionCaptor: ArgumentCaptor - - private lateinit var config: JsonObject - - @Mock - lateinit var vertx: Vertx - - @Mock - lateinit var eventBus: EventBus - - @BeforeEach - fun init() { - sshClient = SSHClient() - initMocks(this) - `when`(vertx.eventBus()).thenReturn(eventBus) - sshClient.init(vertx, null) - } - - private fun generateConfig(authTypes: Set) { - config = JsonObject() - .put(CogboardConstants.Props.USER, "mock") - .put(CogboardConstants.Props.PASSWORD, "TLQuoLMn*T89&Y*r*YqHviSFH6MkR!4E") - .put(CogboardConstants.Props.TOKEN, "TLQuoLMn*T89&Y*r*YqHviSFH6MkR!4E") - .put(CogboardConstants.Props.SSH_KEY, SSHClientTest::class.java.getResource( - "/com/cognifide/cogboard/ssh/id_rsa").path) - .put(CogboardConstants.Props.SSH_HOST, "150.254.30.120") - .put(CogboardConstants.Props.LOG_FILE_PATH, "/home/mock/example.txt") - .put(CogboardConstants.Props.LOG_LINES, "1") - .put(CogboardConstants.Props.AUTHENTICATION_TYPES, Json.encode(authTypes)) - .put(CogboardConstants.Props.EVENT_ADDRESS, "ssh.test.address") - } - - @Test - fun `Executing commands with user+password authentication succeeds`() { - generateConfig(setOf(AuthenticationType.BASIC)) - - sshClient.tryToConnect(config) - val (result, exception) = captureWhatIsSent(eventBus, bufferCaptor, exceptionCaptor) - - result?.let { - assertEquals("19:28:11.445 [vert.x-eventloop-thread-2] " + - "ERROR c.cognifide.cogboard.http.HttpClient - Connection was closed\n", - it.getString(0, it.length()) - ) - } - assert(exception == null) - } - - @Test - fun `Executing commands using key authentication succeeds`() { - generateConfig(setOf(AuthenticationType.SSH_KEY)) - - sshClient.tryToConnect(config) - val (result, exception) = captureWhatIsSent(eventBus, bufferCaptor, exceptionCaptor) - - result?.let { - assertEquals("19:28:11.445 [vert.x-eventloop-thread-2] " + - "ERROR c.cognifide.cogboard.http.HttpClient - Connection was closed\n", - it.getString(0, it.length()) - ) - } - assert(exception == null) - } - - @Test - fun `Executing commands with wrong credentials fails`() { - generateConfig(setOf(AuthenticationType.BASIC)) - config.remove(CogboardConstants.Props.PASSWORD) - config.put(CogboardConstants.Props.PASSWORD, "wrong") - - sshClient.tryToConnect(config) - - val (result, exception) = captureWhatIsSent(eventBus, bufferCaptor, exceptionCaptor) - - assert(result == null) - assert(exception is JSchException) - } - - private fun captureWhatIsSent(eventBus: EventBus, - bufferCaptor: ArgumentCaptor, - exceptionCaptor: ArgumentCaptor - ): Pair{ - return try { - verify(eventBus).send(eq("ssh.test.address"), bufferCaptor.capture()) - verify(eventBus, times(0)).send(eq("ssh.test.address"), any(Exception::class.java)) - Pair(bufferCaptor.value, null) - } catch (e: Throwable) { - verify(eventBus, times(0)).send(eq("ssh.test.address"), any(Buffer::class.java)) - verify(eventBus).send(eq("ssh.test.address"), exceptionCaptor.capture()) - Pair(null, exceptionCaptor.value) - } - } -} \ No newline at end of file diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt index 896b60b2..8afc13e8 100644 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt @@ -28,9 +28,10 @@ class LogViewerTest: WidgetTestBase() { val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + val endpoint = mockEndpointData("ssh") + val config = initWidget() - .put(Props.LOG_SOURCE_TYPE, ConnectionType.SSH) - .put(Props.LOG_SOURCE, "192.168.0.1") + .put(Props.ENDPOINT_LOADED, endpoint) .put(Props.LOG_LINES, "5") widget = LogViewerWidget(vertx, config, initService()) @@ -43,11 +44,12 @@ class LogViewerTest: WidgetTestBase() { fun `Expect JsonObject consumer to be used when type is HTTP`() { val consumerMock = mock(MessageConsumer::class.java) as MessageConsumer `when`(eventBus.consumer(anyString())).thenReturn(consumerMock) + + val endpoint = mockEndpointData("http") val config = initWidget() - .put(Props.LOG_SOURCE_TYPE, ConnectionType.HTTP) .put(Props.LOG_REQUEST_TYPE, RequestMethod.GET) - .put(Props.LOG_SOURCE, "192.168.0.1") + .put(Props.ENDPOINT_LOADED, endpoint) .put(Props.LOG_LINES, "5") widget = LogViewerWidget(vertx, config, initService()) @@ -55,4 +57,7 @@ class LogViewerTest: WidgetTestBase() { verify(eventBus).consumer(eq(widget.eventBusAddress)) } + + private fun mockEndpointData(protocol: String): JsonObject = + JsonObject(mapOf(Pair(Props.URL, "$protocol://192.168.0.1"))) } \ No newline at end of file diff --git a/cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa b/cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa deleted file mode 100644 index 2d77f8a1..00000000 --- a/cogboard-app/src/test/resources/com/cognifide/cogboard/ssh/id_rsa +++ /dev/null @@ -1,39 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIG5AIBAAKCAYEApphpbfnbEh4ZFdnloNqz0P3IDnADldRaD9ATzskGdcdRebJX -7mRJ+f174wyfee8WUl5W74TNIMHOo2oHFLD+/qtSg8m+w5JttmTS02wVCw/vBgC/ -3WSrR71jScBTQkm34ZQW9cZvuB0iJO3OtnGS2PJSxe1E8UNsey7EP/oXWjomCCgx -50hgWWDdj4PNHyMQoOcq9bZWT1yjWppSuBgaVYKwZhZeUPrObbixKOxMKqxEqjul -ayepln3DyI2Mq+/darE2cKD3FBA9MI6rbyA6nf0ncWCrrPsv1TpLFzqP9q1T+zPP -igpI778BuVJUYEEOWWmPmquti1tkiiAwJzKTaDILDObfifgcd9eyyr4FzZoArwep -Un6+yECthy2VMhxbGsJXVAnYmC3/06MFVjNXLgTvQG/h2YsknkSKaBgVdqI5ireK -l1rxkmIBzjdqJ8QuJjR1TbSxjmsDNeNCxrskLfAL3ATRJGmdXQHv6GU1g3Lt8qjr -TF/MMdV//oM/NwxfAgMBAAECggGAS/PaxVgPh8APIcY5CdAMATFi3yo0iD/LW8A6 -96DxAAuCWuBzdG1myMHHlKlxn87gN2dpbUP3nYKeqiQx3D4h04vaT9lPzqxYtrpa -4Cc7pNJ74BnBX7eA23E97ibwDp27Zu30VdNFpgQqR/nfr5AyKhS4piJZt0FNGRAm -SyDDOtCd/EQPFGoL+1PNT5wAjbyX3TPngyTBTudmVm1bXzEl+Gxf7fsuvu7J5H46 -zvSEeUQW/iG5dhQcHk9yTmIyi0UMyipOv+e+K4ujPQYDTaGL1y2czUlnCGZkztql -DWVRI54YBfNDX0tawaPrIuL7BT1yZVGaT3w89FIckJqRNBCy9LeaSz3qphpuLtZ6 -jZLGByEIurQCGJHhcJfU/mm25uCc3FFiSWeCIQcIMgF0zlQtlKFBsLzIZrHBFY6Q -XL4sxS6/QpotQ4p2tF1RbG2e6RjnJzammk79U5hs7/9nb4IbSQcn0SDz9UpNQzOD -WENMMQbUtyz4JEWrQPfNpgGdyOlxAoHBANVgiUrX27l6f9yUYdET4LCA6yINVQM5 -628+78Ho1GrnZqs3F+bO+9+jjGgW1ousLsnbmeaLNvbm2tZJhKCy4SfwypYCZDpO -8QY1Pscg6Wd8gsrjyjq6j/FoVp9TrWs4tUHjbIv9YEtBXdeto2CCSb/uhlc6jUDj -tmY0OLf5fWKFrKmfIZSFT/mz8ZO5KFXILuO395ZG/tMLxsRVm1Rsj2xFzUOnt6hg -NEJxI8Qx/7MC69SNrdkt34Kj7JdfkXeJmQKBwQDH35kbAMExA+Gznm/eE89TyDLc -P5qbsP62rc9BqU8aTnwwsd2QGhU3qwGx/0TEL+mR77j7cyXs8Z8bhqoqjr/5IvkJ -Bk8D18bNmu+QCeRs+kDUf1XdUzCF5uH6QezpnntD7KnUf+aJ+Byf6qp0WdLTyi/m -eJq2OqMqeDJnapY7wC9FpycD2Qw3eh47CFfIPFb+cRjsmIPaG28PHSmcU+uvZy9Z -t5wo7z+AmkBvcBBlPGORmH/4EUbAzNitCLEPMLcCgcAYngeY6+h8sKZZw4C5h2qP -0n/OMO2S7ra74e31WDBRmRreO//08AJdHdhQFfpwqM/JGB3cXEleGOo8eMTlaV3S -ptQolGQN2heymKgCf0iOWO4aDEfDmMyMlHYR8ax7R1KaJGvchsH6TLNP88d6le1+ -SD2ViLrNNrhPeEzm5NDTcgqmkyZjpTHB5EHFwkHmC69lNE9LNiumG6C1/A5sog21 -9yOkX5Avy9GbrMPsmbwfYgHlRuc8vC8iOllMaYk12lkCgcEAnrqVznoE8rYQciLq -2ESHLBQbQApK8EXZop3ZsF2S8mNOASXfvObZ3sGxsPf2Vo9uQHVORHKntcoU/zks -vmtrTaFWgLI/4d9khDf89DjG7Ty4a4lMWV4NdOlsoN/mE4nGfqTeImIIZZ1iriUg -hRIoegVhkPhKdVmP5tRZwwNEl+MCJ6CdPVMLfqs+gscXX2977slGb+6XF4kd47TX -LM0AqOWbFvbXzzJhDfJyJY2rl5ojwKaJSin+NHL5yEDUzCl1AoHBAK85ZTR0CmlE -jV4OrsBk937oDysYMYH6IYAUQ4xX4jCu5nbHi6xIpAuha2Xh0vWCr7xoguxDE67j -z6NeE2s3wsjK5I9tvAxwvpnSUvMPFVojlxrPQLHcRh3VmAq3kYtF2HrmJx+lsmDD -mLZLHgj4lqcWlhME4ZsENrLBoUtwx9NEvTjJoNGdeU1TsDSUx/a5DGleeqLHjejS -SoGobi0iGwCCe/gfAyJ4zgtYe3ie6yJRcsESHuCfrk6ET0vodep/nA== ------END RSA PRIVATE KEY----- From a1c7982daabb4484131a11ce3c596b5d7ee7de56 Mon Sep 17 00:00:00 2001 From: clmrv Date: Wed, 3 Nov 2021 12:43:37 +0100 Subject: [PATCH 24/35] Merge fixes --- .../cogboard/widget/type/LogViewerWidget.kt | 12 ++++-------- .../widgets/types/LogViewerWidget/LogList/index.js | 4 ++-- .../widgets/types/LogViewerWidget/index.js | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 7f7c160d..40c4b5fd 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -3,7 +3,11 @@ package com.cognifide.cogboard.widget.type import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService import com.cognifide.cogboard.widget.BaseWidget +import com.cognifide.cogboard.widget.Widget +import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy +import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory import io.vertx.core.Vertx +import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject import io.vertx.core.json.JsonArray @@ -14,14 +18,6 @@ class LogViewerWidget( serv: BoardsConfigService ) : BaseWidget(vertx, config, serv) { private val address = config.endpointProp(Props.URL) - - // private val user: String = config.endpointProp(Props.USER) - // private val password: String = config.endpointProp(Props.PASSWORD) - // private val token: String = config.endpointProp(Props.TOKEN) - private val sshKey: String = config.endpointProp(Props.SSH_KEY) - private val url: String = config.endpointProp(Props.URL) - private val publicUrl: String = config.endpointProp(Props.PUBLIC_URL).ifBlank { url } - private var consumer: MessageConsumer<*>? = null private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js index 16654925..d1a3514f 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js @@ -13,7 +13,7 @@ import getGridTemplate from './helpers'; const testLogTemplate = ['Provider', 'Message']; -export default function LogList({ children }) { +export default function LogList({ logs }) { const theme = useTheme(); const VariableLogListHeader = () => ( @@ -34,7 +34,7 @@ export default function LogList({ children }) { - {children.map(log => ( + {logs?.map(log => ( { return ( - {widgetData.content.logs} + ); }; From 7eae0b5867459494e531a09229d65ec48d6b62f1 Mon Sep 17 00:00:00 2001 From: clmrv Date: Wed, 3 Nov 2021 13:19:04 +0100 Subject: [PATCH 25/35] Attempt to load logs from server --- .../cogboard/config/EndpointLoader.kt | 1 + .../com/cognifide/cogboard/ssh/SSHClient.kt | 5 +- .../cogboard/widget/type/LogViewerWidget.kt | 75 +++++++++---------- .../cognifide/cogboard/config/EndpointTest.kt | 12 ++- .../cogboard/config/credentials-test.json | 6 +- .../widgets/types/LogViewerWidget/index.js | 2 +- 6 files changed, 57 insertions(+), 44 deletions(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt index 0165b1c7..bf4712cb 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/config/EndpointLoader.kt @@ -32,6 +32,7 @@ class EndpointLoader( this.put(Props.PASSWORD, credentials.getString(Props.PASSWORD) ?: "") this.put(Props.TOKEN, credentials.getString(Props.TOKEN) ?: "") this.put(Props.SSH_KEY, credentials.getString(Props.SSH_KEY) ?: "") + this.put(Props.SSH_KEY_PASSPHRASE, credentials.getString(Props.SSH_KEY_PASSPHRASE) ?: "") } } return this diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt index 433a6a09..a98b80ba 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt @@ -86,7 +86,10 @@ class SSHClient : AbstractVerticle() { private fun executeCommandAndSendResult(config: JsonObject) { val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) val responseBuffer = Buffer.buffer() - responseBuffer.appendBytes(sshInputStream.readAllBytes()) + val tmpBuf = ByteArray(512) + while (sshInputStream.read(tmpBuf, 0, 512) != -1) { + responseBuffer.appendBytes(tmpBuf) + } vertx.eventBus().send(eventBusAddress, responseBuffer) channel.disconnect() session.disconnect() diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt index 40c4b5fd..66853fd8 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt @@ -10,7 +10,6 @@ import io.vertx.core.Vertx import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject -import io.vertx.core.json.JsonArray class LogViewerWidget( vertx: Vertx, @@ -34,7 +33,7 @@ class LogViewerWidget( return super.stop() } - private val logs = createTemplateLogs(20) + // private val logs = createTemplateLogs(20) override fun updateState() { if (address.isNotBlank()) { connectionStrategy.sendRequest(address, config) @@ -42,44 +41,44 @@ class LogViewerWidget( sendConfigurationError("Endpoint URL is blank") } - send(JsonObject().put("logs", logs)) + // send(JsonObject().put("logs", logs)) } - private fun createTemplateLogs(n: Int): JsonArray { - val types = arrayOf("info", "error", "debug", "success", "warn") - val logs = JsonArray() + // private fun createTemplateLogs(n: Int): JsonArray { + // val types = arrayOf("info", "error", "debug", "success", "warn") + // val logs = JsonArray() - for (i in 1..n) { - logs.add(createTemplateLog(types[i % types.size])) - } - return logs - } + // for (i in 1..n) { + // logs.add(createTemplateLog(types[i % types.size])) + // } + // return logs + // } - private fun createTemplateLog(type: String): JsonObject { - return JsonObject(""" - { - "type": "$type", - "date": "2021-04-22 14:08:37", - "additionalData": { - "ID": "123456", - "Type": "sys", - "IP address": "127.0.0.1", - "Port": "27017" - }, - "variableData": { - "template": ["Provider", "Message"], - "header": [ - "mongodb.log", - "Expected corresponding JSX closing tag for ." - ], - "description": [ - "provider desc", - "SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6)" - ] - } - } - """) - } + // private fun createTemplateLog(type: String): JsonObject { + // return JsonObject(""" + // { + // "type": "$type", + // "date": "2021-04-22 14:08:37", + // "additionalData": { + // "ID": "123456", + // "Type": "sys", + // "IP address": "127.0.0.1", + // "Port": "27017" + // }, + // "variableData": { + // "template": ["Provider", "Message"], + // "header": [ + // "mongodb.log", + // "Expected corresponding JSX closing tag for ." + // ], + // "description": [ + // "provider desc", + // "SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6) SyntaxError: /Users/celmer/Documents/js/cogboard/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js: Expected corresponding JSX closing tag for . (21:6)" + // ] + // } + // } + // """) + // } private fun handleResponse(response: Message<*>) { val responseBody = response.body() @@ -96,9 +95,9 @@ class LogViewerWidget( } } - private fun prepareLogs(logs: String): String { + private fun prepareLogs(logs: String): JsonObject { // TODO - return logs + return JsonObject().put("logs", logs) } private fun determineConnectionStrategy() = diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt index fbfa08da..8bcb6564 100644 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/config/EndpointTest.kt @@ -38,11 +38,14 @@ internal class EndpointTest { assert(validEndpoint.containsKey("password")) assert(validEndpoint.containsKey("token")) assert(validEndpoint.containsKey("sshKey")) + assert(validEndpoint.containsKey("sshKeyPassphrase")) assert(invalidEndpoint.containsKey("user")) assert(invalidEndpoint.containsKey("password")) assert(invalidEndpoint.containsKey("token")) assert(invalidEndpoint.containsKey("sshKey")) + assert(invalidEndpoint.containsKey("sshKeyPassphrase")) + } @Test @@ -51,6 +54,8 @@ internal class EndpointTest { assertEquals("password1", validEndpoint.getString("password")) assertEquals("token1", validEndpoint.getString("token")) assertEquals("key1", validEndpoint.getString("sshKey")) + assertEquals("pass1", validEndpoint.getString("sshKeyPassphrase")) + } @Test @@ -59,6 +64,7 @@ internal class EndpointTest { assertEquals("", invalidEndpoint.getString("password")) assertEquals("", invalidEndpoint.getString("token")) assertEquals("", invalidEndpoint.getString("sshKey")) + assertEquals("", invalidEndpoint.getString("sshKeyPassphrase")) } @Test @@ -72,7 +78,8 @@ internal class EndpointTest { "user" : "user1", "password" : "password1", "token" : "token1", - "sshKey": "key1" + "sshKey": "key1", + "sshKeyPassphrase" : "pass1" } """) @@ -89,7 +96,8 @@ internal class EndpointTest { "user" : "", "password" : "", "token" : "", - "sshKey" : "" + "sshKey" : "", + "sshKeyPassphrase" : "" } """) diff --git a/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json b/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json index 87cb0991..b5b43109 100644 --- a/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json +++ b/cogboard-app/src/test/resources/com/cognifide/cogboard/config/credentials-test.json @@ -6,7 +6,8 @@ "user": "user1", "password": "password1", "token": "token1", - "sshKey": "key1" + "sshKey": "key1", + "sshKeyPassphrase": "pass1" }, { "id": "credentials2", @@ -14,7 +15,8 @@ "user": "user2", "password": "password2", "token": "token2", - "sshKey": "key2" + "sshKey": "key2", + "sshKeyPassphrase": "pass2" } ] } diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js index b3292860..39cdffda 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/index.js @@ -14,7 +14,7 @@ const LogViewerWidget = ({ id }) => { return ( - + {/* */} ); }; From 52170d23f8bb5c8f780bf502b626008755bde3b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Przypa=C5=9Bniak?= Date: Sun, 7 Nov 2021 04:47:24 +0100 Subject: [PATCH 26/35] Successfully sending parsed data to front-end --- cogboard-app/build.gradle.kts | 1 + .../cognifide/cogboard/CogboardConstants.kt | 5 +- .../com/cognifide/cogboard/ssh/SSHClient.kt | 43 +++++++++---- .../cogboard/ssh/auth/SSHAuthData.kt | 4 +- .../cognifide/cogboard/widget/WidgetIndex.kt | 2 +- .../connectionStrategy/ConnectionStrategy.kt | 2 +- .../ConnectionStrategyFactory.kt | 30 +++++++-- .../HttpConnectionStrategy.kt | 5 +- .../SSHConnectionStrategy.kt | 4 +- .../type/{ => logviewer}/LogViewerWidget.kt | 22 +++++-- .../logviewer/logparser/LogParserStrategy.kt | 19 ++++++ .../logparser/LogParserStrategyFactory.kt | 16 +++++ .../logparser/MockLogParserStrategy.kt | 29 +++++++++ .../type/logviewer/logparser/ParsedLog.kt | 63 +++++++++++++++++++ .../type/{ => logviewer}/LogViewerTest.kt | 4 +- .../logparser/MockLogParserStrategyTest.kt | 30 +++++++++ 16 files changed, 244 insertions(+), 35 deletions(-) rename cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/{ => logviewer}/LogViewerWidget.kt (68%) create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategyFactory.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategy.kt create mode 100644 cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/ParsedLog.kt rename cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/{ => logviewer}/LogViewerTest.kt (94%) create mode 100644 cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategyTest.kt diff --git a/cogboard-app/build.gradle.kts b/cogboard-app/build.gradle.kts index f1ce38a0..48a4bd34 100644 --- a/cogboard-app/build.gradle.kts +++ b/cogboard-app/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.10.0") implementation(kotlin("stdlib-jdk8")) implementation("com.jcraft:jsch:0.1.55") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2") testImplementation("org.assertj:assertj-core:3.12.2") testImplementation("org.junit.jupiter:junit-jupiter-api:5.4.2") diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt index c7ed2383..c7f60733 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/CogboardConstants.kt @@ -45,11 +45,8 @@ class CogboardConstants { const val SSH_KEY_PASSPHRASE = "sshKeyPassphrase" const val URL = "url" - const val LOG_SOURCE = "logSource" - const val LOG_SOURCE_TYPE = "logSourceType" const val LOG_REQUEST_TYPE = "logRequestType" - const val LOG_LINES = "logLines" - const val LOG_FILE_PATH = "logFilePath" + const val LOG_LINES = "logLinesField" const val REQUEST_ID = "requestId" const val PUBLIC_URL = "publicUrl" const val USER = "user" diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt index 433a6a09..695a1523 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/SSHClient.kt @@ -13,6 +13,10 @@ import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject import io.vertx.core.logging.Logger import io.vertx.core.logging.LoggerFactory +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import java.io.InputStream class SSHClient : AbstractVerticle() { @@ -42,27 +46,31 @@ class SSHClient : AbstractVerticle() { } fun tryToConnect(config: JsonObject) { - - try { - connect(config) - } catch (e: JSchException) { - LOGGER.error(e.message) - val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) - vertx.eventBus().send(eventBusAddress, e) + LOGGER.info(config) + coroutineScope.launch { + try { + connect(config) + } catch (e: JSchException) { + LOGGER.error(e.message) + val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) + vertx.eventBus().send(eventBusAddress, e.message) + } } } - private fun connect(config: JsonObject) { + private suspend fun connect(config: JsonObject) { val authData = SSHAuthData(config) createSSHChannel(authData) executeCommandAndSendResult(config) } - private fun createSSHChannel(authData: SSHAuthData) { + private suspend fun createSSHChannel(authData: SSHAuthData) { with(authData) { initSSHSession(authData) if (session.isConnected) { createChannel(createCommand()) + } else { + LOGGER.error("Failed to connect to ${authData.host}") } } } @@ -85,14 +93,27 @@ class SSHClient : AbstractVerticle() { private fun executeCommandAndSendResult(config: JsonObject) { val eventBusAddress = config.getString(CogboardConstants.Props.EVENT_ADDRESS) - val responseBuffer = Buffer.buffer() - responseBuffer.appendBytes(sshInputStream.readAllBytes()) + val responseBuffer = readResponse() vertx.eventBus().send(eventBusAddress, responseBuffer) channel.disconnect() session.disconnect() } + private fun readResponse(): Buffer { + val responseBuffer = Buffer.buffer() + val tmpBuf = ByteArray(512) + var readBytes = sshInputStream.read(tmpBuf, 0, 512) + while (readBytes != -1) { + responseBuffer.appendBytes(tmpBuf, 0, readBytes) + readBytes = sshInputStream.read(tmpBuf, 0, 512) + } + + return responseBuffer + } + companion object { val LOGGER: Logger = LoggerFactory.getLogger(SSHClient::class.java) + + val coroutineScope = CoroutineScope(Job() + Dispatchers.IO) } } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt index ee0d41ea..26ef790f 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/ssh/auth/SSHAuthData.kt @@ -39,8 +39,8 @@ class SSHAuthData(private val config: JsonObject) { } fun createCommand(): String { - val logLines = config.getString(CogboardConstants.Props.LOG_LINES) ?: "0" - val logFilePath = config.getString(CogboardConstants.Props.LOG_FILE_PATH) ?: "" + val logLines = config.getInteger(CogboardConstants.Props.LOG_LINES) ?: 0 + val logFilePath = config.getString(CogboardConstants.Props.PATH) ?: "" return "cat $logFilePath | tail -$logLines" } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt index e057a29b..ee5235c1 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/WidgetIndex.kt @@ -20,7 +20,7 @@ import com.cognifide.cogboard.widget.type.WorldClockWidget import com.cognifide.cogboard.widget.type.randompicker.RandomPickerWidget import com.cognifide.cogboard.widget.type.sonarqube.SonarQubeWidget import com.cognifide.cogboard.widget.type.zabbix.ZabbixWidget -import com.cognifide.cogboard.widget.type.LogViewerWidget +import com.cognifide.cogboard.widget.type.logviewer.LogViewerWidget import io.vertx.core.Vertx import io.vertx.core.json.JsonArray import io.vertx.core.json.JsonObject diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt index fcf425be..dcafef06 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategy.kt @@ -6,7 +6,7 @@ import io.vertx.core.Vertx import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject -abstract class ConnectionStrategy(protected val vertx: Vertx) { +abstract class ConnectionStrategy(protected val vertx: Vertx, protected val eventBusAddress: String) { protected fun JsonObject.endpointProp(prop: String): String { return this.getJsonObject(CogboardConstants.Props.ENDPOINT_LOADED)?.getString(prop) ?: "" } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt index cc92d9a8..b734cb99 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/ConnectionStrategyFactory.kt @@ -13,6 +13,7 @@ class ConnectionStrategyFactory( ) { private val connectionType: String private lateinit var vertx: Vertx + private lateinit var eventBusAddress: String init { connectionType = determineConnectionType(uri, config) @@ -23,6 +24,11 @@ class ConnectionStrategyFactory( return this } + fun addEventBusAddress(eventBusAddress: String): ConnectionStrategyFactory { + this.eventBusAddress = eventBusAddress + return this + } + private fun determineConnectionType(uri: String, config: JsonObject): String { val url = URI.create(uri) return when (url.scheme) { @@ -44,13 +50,23 @@ class ConnectionStrategyFactory( } } - fun build(): ConnectionStrategy { - if (!::vertx.isInitialized) { - throw RuntimeException("Vertx instance not passed to builder") + fun checkRequiredParameters() { + var message = "" + when { + !::vertx.isInitialized -> message = "Vertx instance not passed to builder" + !::eventBusAddress.isInitialized -> message = "Eventbus address not passed to builder" + } + + if (message.isNotBlank()) { + throw MissingBuilderParametersException(message) } + } + + fun build(): ConnectionStrategy { + checkRequiredParameters() return when (connectionType) { - HTTP -> HttpConnectionStrategy(vertx) - SSH -> SSHConnectionStrategy(vertx) + HTTP -> HttpConnectionStrategy(vertx, eventBusAddress) + SSH -> SSHConnectionStrategy(vertx, eventBusAddress) else -> throw UnknownConnectionTypeException("Unknown strategy type") } } @@ -59,3 +75,7 @@ class ConnectionStrategyFactory( class UnknownConnectionTypeException( message: String? ) : RuntimeException(message) + +class MissingBuilderParametersException( + message: String? +) : RuntimeException(message) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt index f7cff289..c4dc5500 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/HttpConnectionStrategy.kt @@ -11,7 +11,8 @@ import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.Json import io.vertx.core.json.JsonObject -class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { +class HttpConnectionStrategy(vertx: Vertx, eventBusAddress: String) : + ConnectionStrategy(vertx, eventBusAddress) { override fun sendRequest(address: String, arguments: JsonObject) { when (arguments.getString(Props.LOG_REQUEST_TYPE, "")) { GET -> vertx.eventBus().send(Event.HTTP_GET, getProps(arguments)) @@ -30,7 +31,7 @@ class HttpConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { private fun basicProps(props: JsonObject): JsonObject = JsonObject() .put(Props.URL, props.endpointProp(Props.URL)) - .put(Props.EVENT_ADDRESS, props.endpointProp(Props.EVENT_ADDRESS)) + .put(Props.EVENT_ADDRESS, eventBusAddress) .put(Props.USER, props.endpointProp(Props.USER)) .put(Props.PASSWORD, props.endpointProp(Props.PASSWORD)) .put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt index 1be55656..bd1805f9 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/connectionStrategy/SSHConnectionStrategy.kt @@ -9,7 +9,8 @@ import io.vertx.core.json.Json import io.vertx.core.json.JsonObject import java.nio.charset.Charset -open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { +open class SSHConnectionStrategy(vertx: Vertx, eventBusAddress: String) : + ConnectionStrategy(vertx, eventBusAddress) { override fun sendRequest(address: String, arguments: JsonObject) { val config = prepareConfig(arguments) vertx.eventBus().send(CogboardConstants.Event.SSH_COMMAND, config) @@ -27,6 +28,7 @@ open class SSHConnectionStrategy(vertx: Vertx) : ConnectionStrategy(vertx) { ) tmpConfig.getString(Props.AUTHENTICATION_TYPES) ?: config.put(Props.AUTHENTICATION_TYPES, Json.encode(authenticationTypes())) + tmpConfig.put(Props.EVENT_ADDRESS, eventBusAddress) return tmpConfig } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt similarity index 68% rename from cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt rename to cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt index 16392012..e8374cff 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt @@ -1,4 +1,4 @@ -package com.cognifide.cogboard.widget.type +package com.cognifide.cogboard.widget.type.logviewer import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.config.service.BoardsConfigService @@ -6,6 +6,8 @@ import com.cognifide.cogboard.widget.BaseWidget import com.cognifide.cogboard.widget.Widget import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategy import com.cognifide.cogboard.widget.connectionStrategy.ConnectionStrategyFactory +import com.cognifide.cogboard.widget.type.logviewer.logparser.LogParserStrategy +import com.cognifide.cogboard.widget.type.logviewer.logparser.LogParserStrategyFactory import io.vertx.core.Vertx import io.vertx.core.eventbus.Message import io.vertx.core.eventbus.MessageConsumer @@ -20,6 +22,7 @@ class LogViewerWidget( private var consumer: MessageConsumer<*>? = null private val connectionStrategy: ConnectionStrategy = determineConnectionStrategy() + private val logParsingStrategy: LogParserStrategy = determineLogParsingStrategy() override fun start(): Widget { consumer = connectionStrategy.getConsumer(eventBusAddress) @@ -57,13 +60,20 @@ class LogViewerWidget( } } - private fun prepareLogs(logs: String): String { - // TODO - return logs + private fun prepareLogs(logs: String): JsonObject { + val logLines = logs.split("\n") + return JsonObject().put("logs", logParsingStrategy.parseLines(logLines)) } private fun determineConnectionStrategy() = ConnectionStrategyFactory(config, address) - .addVertxInstance(vertx) - .build() + .addVertxInstance(vertx) + .addEventBusAddress(eventBusAddress) + .build() + + private fun determineLogParsingStrategy() = + LogParserStrategyFactory() + .build(LogParserStrategyFactory.MOCK) + /* temporary solution, we'll have to decide if we'll get information of log types from + front-end or if we'll determine it from the logs themselves */ } diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategy.kt new file mode 100644 index 00000000..5685e51d --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategy.kt @@ -0,0 +1,19 @@ +package com.cognifide.cogboard.widget.type.logviewer.logparser + +import io.vertx.core.json.JsonArray +import io.vertx.core.json.JsonObject + +abstract class LogParserStrategy { + fun parseLines(logLines: Collection): JsonArray { + val resultArray = JsonArray() + for (line in logLines) { + val parsedLine = parseLine(line) + resultArray.add(parsedLine) + } + return resultArray + } + + abstract fun parseLine(logLine: String): JsonObject +} + +class LogParsingException(message: String) : RuntimeException(message) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategyFactory.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategyFactory.kt new file mode 100644 index 00000000..889dcbeb --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/LogParserStrategyFactory.kt @@ -0,0 +1,16 @@ +package com.cognifide.cogboard.widget.type.logviewer.logparser + +class LogParserStrategyFactory { + companion object { + const val MOCK = "mock" + } + + fun build(type: String): LogParserStrategy { + return when (type) { + MOCK -> MockLogParserStrategy() + else -> throw UnknownParserTypeException("Unknown strategy type") + } + } +} + +class UnknownParserTypeException(message: String) : RuntimeException(message) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategy.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategy.kt new file mode 100644 index 00000000..a0a9cb5e --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategy.kt @@ -0,0 +1,29 @@ +package com.cognifide.cogboard.widget.type.logviewer.logparser + +import io.vertx.core.json.JsonObject +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.TYPE +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.DATE +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.PROVIDER +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.MESSAGE + +class MockLogParserStrategy : LogParserStrategy() { + private val regex = """^(?<$DATE>[0-9-:]+) \*(?<$TYPE>[A-Z]+)\* \[(?<$PROVIDER>[a-zA-Z]+)\][ ]+(?<$MESSAGE>.+)$""".trimMargin().toRegex() + + override fun parseLine(logLine: String): JsonObject { + val groups = regex.matchEntire(logLine.trim())?.groups + // ?: throw LogParsingException("Unable to parse line: $logLine") + + return createLogObject(groups) + } + + private fun createLogObject(groups: MatchGroupCollection?): JsonObject { + val mapOfCapturedValues = mutableMapOf() + mapOfCapturedValues[TYPE] = groups?.get(TYPE)?.value ?: "" + mapOfCapturedValues[DATE] = groups?.get(DATE)?.value ?: "" + mapOfCapturedValues[PROVIDER] = groups?.get(PROVIDER)?.value ?: "" + mapOfCapturedValues[MESSAGE] = groups?.get(MESSAGE)?.value ?: "" + + val parsedLog = ParsedLog(mapOfCapturedValues) + return parsedLog.parsedLogJson + } +} diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/ParsedLog.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/ParsedLog.kt new file mode 100644 index 00000000..d9de522f --- /dev/null +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/ParsedLog.kt @@ -0,0 +1,63 @@ +package com.cognifide.cogboard.widget.type.logviewer.logparser + +import io.vertx.core.json.JsonArray +import io.vertx.core.json.JsonObject + +class ParsedLog(values: Map) { + companion object { + const val DATE = "date" + const val TYPE = "type" + const val PROVIDER = "Provider" + const val MESSAGE = "Message" + const val TEMPLATE = "template" + const val HEADERS = "headers" + const val VARIABLE_DATA = "variableData" + const val DESCRIPTION = "description" + const val ADDITIONAL_DATA = "additionalData" + const val ID = "ID" + const val IP_ADDRESS = "IP address" + const val PORT = "Port" + } + + private val _parsedLogJson = JsonObject() + private val variableData = JsonObject() + + val parsedLogJson: JsonObject + get() { + _parsedLogJson.put(VARIABLE_DATA, variableData) + return _parsedLogJson + } + + init { + values[TYPE]?.let { _parsedLogJson.put(TYPE, it) } + values[DATE]?.let { _parsedLogJson.put(DATE, it) } + values[PROVIDER]?.let { addFieldToVariableData(PROVIDER, it) } + values[MESSAGE]?.let { addFieldToVariableData(MESSAGE, it) } + addAdditionalData() + } + + private fun addFieldToVariableData(template: String, value: String) { + val templateArray = variableData.getJsonArray(TEMPLATE, JsonArray()) + val headersArray = variableData.getJsonArray(HEADERS, JsonArray()) + val descriptionArray = variableData.getJsonArray(DESCRIPTION, JsonArray()) + + if (!templateArray.contains(template)) { + templateArray.add(template) + headersArray.add(value) + descriptionArray.add("No description") + } + variableData.put(TEMPLATE, templateArray) + variableData.put(HEADERS, headersArray) + variableData.put(DESCRIPTION, descriptionArray) + } + + private fun addAdditionalData() { + val additionalData = JsonObject() + additionalData.put(ID, "None") + additionalData.put(TYPE.capitalize(), "None") + additionalData.put(IP_ADDRESS, "None") + additionalData.put(PORT, "None") + + _parsedLogJson.put(ADDITIONAL_DATA, additionalData) + } +} diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerTest.kt similarity index 94% rename from cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt rename to cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerTest.kt index 8afc13e8..50db30b4 100644 --- a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/LogViewerTest.kt +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerTest.kt @@ -1,8 +1,8 @@ -package com.cognifide.cogboard.widget.type +package com.cognifide.cogboard.widget.type.logviewer -import com.cognifide.cogboard.CogboardConstants.ConnectionType import com.cognifide.cogboard.CogboardConstants.Props import com.cognifide.cogboard.CogboardConstants.RequestMethod +import com.cognifide.cogboard.widget.type.WidgetTestBase import io.vertx.core.buffer.Buffer import io.vertx.core.eventbus.MessageConsumer import io.vertx.core.json.JsonObject diff --git a/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategyTest.kt b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategyTest.kt new file mode 100644 index 00000000..bb56a0fd --- /dev/null +++ b/cogboard-app/src/test/kotlin/com/cognifide/cogboard/widget/type/logviewer/logparser/MockLogParserStrategyTest.kt @@ -0,0 +1,30 @@ +package com.cognifide.cogboard.widget.type.logviewer.logparser + +import org.junit.jupiter.api.Test +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.TYPE +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.DATE +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.VARIABLE_DATA +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.HEADERS +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.TEMPLATE +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.PROVIDER +import com.cognifide.cogboard.widget.type.logviewer.logparser.ParsedLog.Companion.MESSAGE + +class MockLogParserStrategyTest { + private val sampleLog = "2021-11-06:22:40:25 *DEBUG* [FelixStartLevel] Integer lobortis. bibendum Nulla mi" + private val parser = MockLogParserStrategy() + + @Test + fun parseSampleLog() { + val output = parser.parseLine(sampleLog) + val variableData = output.getJsonObject(VARIABLE_DATA) + val template = variableData.getJsonArray(TEMPLATE) + val headers = variableData.getJsonArray(HEADERS) + + assert(output.getString(TYPE) == "DEBUG") + assert(output.getString(DATE) == "2021-11-06:22:40:25") + assert(template.getString(0) == PROVIDER) + assert(template.getString(1) == MESSAGE) + assert(headers.getString(0) == "FelixStartLevel") + assert(headers.getString(1) == "Integer lobortis. bibendum Nulla mi") + } +} \ No newline at end of file From 9650fc82dcc9c43b29ba1212512d1f7e48d62648 Mon Sep 17 00:00:00 2001 From: clmrv Date: Sun, 7 Nov 2021 21:33:04 +0100 Subject: [PATCH 27/35] Fix log structure typo --- .../widgets/types/LogViewerWidget/LogList/LogEntry.js | 8 ++++---- .../widgets/types/LogViewerWidget/LogList/index.js | 11 +++++------ .../components/widgets/types/LogViewerWidget/index.js | 4 +++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/LogEntry.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/LogEntry.js index 3999565e..a56b7d48 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/LogEntry.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/LogEntry.js @@ -34,10 +34,10 @@ export default function LogEntry({ type, date, additionalData, variableData }) { const VariablePart = ({ description }) => { const variableFieldsTemplate = getGridTemplate(variableData.template); - const data = description ? variableData.description : variableData.header; + const data = description ? variableData.description : variableData.headers; return ( - {data.map((text, index) => ( + {data?.map((text, index) => ( {text} ))} @@ -73,7 +73,7 @@ LogEntry.propTypes = { additionalData: objectOf(oneOfType([string, number, bool])), variableData: shape({ template: arrayOf(string).isRequired, - header: arrayOf(oneOfType([string, number, bool])).isRequired, + headers: arrayOf(oneOfType([string, number, bool])).isRequired, description: arrayOf(oneOfType([string, number, bool])).isRequired }) }; @@ -82,7 +82,7 @@ LogEntry.defaultProps = { type: 'info', variableData: { template: [], - header: [], + headers: [], description: [] }, additionalData: {} diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js index d1a3514f..c85f9192 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/index.js @@ -11,13 +11,11 @@ import { } from './styled'; import getGridTemplate from './helpers'; -const testLogTemplate = ['Provider', 'Message']; - -export default function LogList({ logs }) { +export default function LogList({ logs, template }) { const theme = useTheme(); const VariableLogListHeader = () => ( - - {testLogTemplate.map((name, index) => ( + + {template.map((name, index) => ( {name} ))} @@ -34,8 +32,9 @@ export default function LogList({ logs }) { - {logs?.map(log => ( + {logs?.map((log, index) => ( { shallowEqual ); useEffect(() => console.log(widgetData), [widgetData]); + + const logs = widgetData.content?.logs; return ( - {/* */} + {logs && } ); }; From 0d8f46fd77f9b1f11a6c72815988a3c3b98f6e62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Przypa=C5=9Bniak?= Date: Sun, 7 Nov 2021 21:51:11 +0100 Subject: [PATCH 28/35] Fixed sending blank log --- .../cogboard/widget/type/logviewer/LogViewerWidget.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt index 3ef904c0..71b6697b 100644 --- a/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt +++ b/cogboard-app/src/main/kotlin/com/cognifide/cogboard/widget/type/logviewer/LogViewerWidget.kt @@ -99,7 +99,8 @@ class LogViewerWidget( } private fun prepareLogs(logs: String): JsonObject { - val logLines = logs.split("\n") + var logLines = logs.split("\n") + logLines = logLines.filter { it.isNotEmpty() } return JsonObject().put("logs", logParsingStrategy.parseLines(logLines)) } From 86da1ef5372afccda5c604413d4181afb5675cc6 Mon Sep 17 00:00:00 2001 From: clmrv Date: Mon, 8 Nov 2021 18:24:42 +0100 Subject: [PATCH 29/35] Add logLevels config file --- .../types/LogViewerWidget/LogList/styled.js | 24 +++++++++---------- .../Toolbar/FilterPicker/index.js | 19 ++++++++------- .../types/LogViewerWidget/logLevels.js | 11 +++++++++ 3 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 cogboard-webapp/src/components/widgets/types/LogViewerWidget/logLevels.js diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/styled.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/styled.js index 2ff61248..62669eaf 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/styled.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/LogList/styled.js @@ -1,6 +1,7 @@ import styled from '@emotion/styled/macro'; import { COLORS } from '../../../../../constants'; import { Typography, Accordion } from '@material-ui/core'; +import logLevels from '../logLevels'; export const Container = styled.div` max-height: 100%; @@ -36,23 +37,22 @@ export const ColumnTitle = styled(Typography)` `; export const Text = styled(Typography)(props => { - const getColor = type => - ({ - info: COLORS.WHITE, - success: COLORS.GREEN, - warn: COLORS.YELLOW, - error: COLORS.RED - }[type.toLowerCase()]); + let logTypeStyles = ``; + if (props.type) { + const logLevel = logLevels.find( + level => level.value === props.type?.toLowerCase() + ); + logTypeStyles = ` + font-weight: 500; + color: ${logLevel?.color || COLORS.WHITE}; + `; + } return ` line-height: 19px; font-size: 0.8rem; font-weight: 400; - ${props.type && - ` - font-weight: 500; - color: ${getColor(props.type)}; - `} + ${logTypeStyles} `; }); diff --git a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js index c999852c..851dc841 100644 --- a/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js +++ b/cogboard-webapp/src/components/widgets/types/LogViewerWidget/Toolbar/FilterPicker/index.js @@ -10,6 +10,7 @@ import { import { ScrollableBox } from './styled'; import ToolbarGroup from '../ToolbarGroup'; import { useState } from 'react'; +import logLevels from '../../logLevels'; const FilterPicker = () => { const handleDelete = name => { @@ -48,10 +49,11 @@ const FilterPicker = () => { )} > - DEBUG - INFO - WARN - ERROR + {logLevels.map((level, index) => ( + + {level.value.toUpperCase()} + + ))} @@ -64,10 +66,11 @@ const FilterPicker = () => { value={logLevel} onChange={e => setLogLevel(e.target.value)} > - DEBUG - INFO - WARN - ERROR + {logLevels.map((level, index) => ( + + {level.value.toUpperCase()} + + ))}